A-1 AtScript
This is a package that uses annotations to provide syntactic sugar around Angular 1.x's Dependency Injection mechanism. It is designed to be a "bridge" to Angular 2.0 -- to get you as close as possible to writing Angular 2.0 like code in Angular 1.x. More features will be added as Angular 2.0's feature set becomes more clear.
Initial setup
You must be building your Angular 1.x with an ES Next transpiler. The system has been tested with both Babel.js and Traceur. See "Using a transpiler other than Traceur" for important caveats if you are not using Traceur. Check for tutorials on the internet for how to setup a JS build system that incorporates ES6.
Install the module
bower install a1atscript --save
or
npm install a1atscript
Angular Type Annotations
import {Controller, Service} from 'bower_components/dist/a1atscript.js';
@Controller('ExampleController', ['$scope', 'SomeService'])
export class ExampleController {
constructor($scope, SomeService) {
}
}
@Service('ExampleService', ['SomeService'])
export class ExampleService {
constructor(SomeService) {
}
}
Setting up modules
import {Module} from 'bower_components/dist/a1atscript.js';
import {
ExampleController,
ExampleService
} from './theCodeBlockRightAbove';
import { AnotherModule } from './anotherA1AtScriptModule';
export var MyModule = new Module('MyModule', [
AnotherModule,
ExampleController,
ExampleService,
'aRegularAngularModule'
]);
Note you can mix other modules, controllers, and services all together in the list -- A1AtScript will figure out how to sort out the module definition.
You can include regular angular modules by just referencing them as strings.
Shortform notation
If you want to quickly define a module with only one component... just use two annotations
@AsModule('ServiceModule')
@Service('ExampleService')
class ExampleService {
constructor() {
this.value = 'Test Value';
}
}
Compile your main app module
import {bootstrap, Module} from 'bower_components/dist/a1atscript.js';
import { MyModule } from './myModule'
var AppModule = Module('AppModule', [
MyModule
]);
bootstrap(AppModule, "myAppPrefix");
Get ready for Angular 2!
Angular 2 introduces an entirely new syntax for working with directives. The most common type of directive is a Component. The good news is with A1AtScript you can write components right now, using a syntax remarkably similar to Angular 2.
@Component({
selector: "awesome",
properties: [ "apple" ],
appInjector: ["ExampleService"]
})
@View({
templateUrl: "awesome.tpl.html"
})
class AwesomeComponent {
constructor(exampleService) {
this.exampleService = exampleService;
this.test = "test";
}
setValue() {
this.value = this.exampleService.value;
}
}
<awesome apple="stringLiteral"></awesome>
<awesome bind-apple="expression"></awesome>
Routeable Components
You can take your Angular 2 prep a step further by using A1AtScript with the new Angular router, using routable component syntax from Angular 2.
make sure to install the new router:
npm install angular-new-router
Then you can build an amazing route aware app using a super simple syntax like this:
app.js:
@Component({})
@View({
template: "<p>Sub</p>"
})
class SubComponent {
}
@Component({})
@View({
template: "<p>Home</p><ng-viewport></ng-viewport>"
})
@RouteConfig({
path: "/sub", component: SubComponent
})
class HomeComponent {
}
@AsModule('AppModule', ['templates', 'ngNewRouter', HomeComponent, SubComponent])
@Component({
selector: "awesome"
})
@View({
templateUrl: "app.tpl.html"
})
@RouteConfig({
path: "/home", component: HomeComponent
})
class AppComponent {
}
bootstrap(AppComponent)
app.tpl.html:
<ng-viewport><ng-viewport>
index.html:
<body>
<awesome></awesome>
<body>
navigate to /home/sub would yield:
<body>
<awesome>
<ng-viewport>
<p>Home</p>
<ng-viewport>
<p>Sub</p>
</ng-viewport>
</ng-viewport>
</awesome>
<body>
That's what Angular 2 routing is likely to look like -- except you can use this today!
Note: the name of the ng-viewport directive is about to change in the next release of the new Angular router to ng-outlet
Notes:
functionally the initial component declaration above is equivalent to:
angular.directive('awesome', function() {
return {
restrict: 'E',
bindToController: {
apple: "@apple"
___bindable___apple: "=?bindApple"
},
controller, ['ExampleService', AwesomeComponent]
controllerAs: 'awesome',
scope: {},
templateUrl: "awesome.tpl.html",
}
function AwesomeComponent(exampleService) {
this.exampleService = exampleService;
this.test = "test";
}
AwesomeComponent.prototype.setValue = function() {
this.value = this.exampleService.value
}
});
The syntax is supported in a Angular 1.3+ (in 1.3 it will set bindToController to true, and set properties on scope, because bindToController object syntax is 1.4 only). If angular 1.x adopts a built-in component feature (see https://github.com/angular/angular.js/issues/10007) then this module will be updated to use that feature when it is available.
Other features:
- Selector is a very, very basic css selector. If you pass '[awesome]', your directive will be called awesome and it'll be set restrict: 'A', and if you pass '.awesome' it'll be set restrict: 'C'
- What about properties? Well, rather than force you to use Angular 1's bizarre character syntax, we try to emulate Angular 2's behavior. if you call your directive with a plain old attribute, it's just interpreted as a string literal. If you call it with a bind- prefix, it gets passed the value of the expression. Sorry, no [] abbreviated syntax here -- Angular 1.x doesn't let you specify scope properties that have [] characters in them
- Services is optional for injecting dependencies into your component class
- Class inheritance does work with components, but you'll need to define annotations on the child class
- Component supports somes Angular1 customizations. You can specify a require or transclude property. You can also specify a custom controllerAs value.
- Template annotation supports simply "url" for templateUrls and 'inline' for inline templates
Angular 2's Directive will be supported in a future release. I'm still examining the best way to port this to Angular 1.x and maintain a similar feature set and syntax to 2.0.
Wrapping up
More Info
Check out the Wiki for more specialized topics.
What's included?
The /src folder contains the es6 source files so that you can package up A1AtScript using whatever packaging system is most comfortable for you. However, if you want an ES5 global build, in dist is a1atscript.bundle.js that will load everything as global.
Wait a second, I thought AtScript was called TypeScript now
A new name is coming as soon as I get big enough to be able to lose what little brand recognition I have.
That's It. Enjoy