Angular Language Rules:
http://code.google.com/p/closure-compiler/wiki/ManageClosureDependencies
Detail About Closure https://github.com/google/closure-compiler
How to implement: http://apphacker.wordpress.com/2009/12/28/howto-how-to-use-goog-require-and-goog-provide-for-your-own-code/
2.Modules should reference other modules using the Angular Module's "name" property
For example:
Note to readers outside Google: the current externs file is located in an internal-to-Google directory, but an example can be found on github here.
Recommended: Use the JSCompiler (the closure compiler that works with js_binary by default) and ANGULAR_COMPILER_FLAGS_FULL from //javascript/angular/build_defs/build_defs for your base flags.
Note - if you are using @export for methods, you will need to add the compiler flag
Google Angular applications should use the 'controller as' style to export the controller onto the scope. This is fully implemented in Angular 1.2 and can be mimicked in pre-Angular 1.2 builds.
Pre Angular 1.2, this looks like:
After Angular 1.2, this looks like:
And in the template:
- Manage dependencies with Closure's goog.require and goog.provide
- Modules
- Modules should reference other modules using the "name" property
- Use the provided Angular externs file
- JSCompiler Flags
- Controllers and Scopes
- Directives
- Services
1. Manage dependencies with Closure's goog.require and goog.provide
Choose a namespace for your project, and use goog.provide and goog.require.goog.provide('hello.about.AboutCtrl'); goog.provide('hello.versions.Versions');Why? Google BUILD rules integrate nicely with closure provide/require.
http://code.google.com/p/closure-compiler/wiki/ManageClosureDependencies
Detail About Closure https://github.com/google/closure-compiler
How to implement: http://apphacker.wordpress.com/2009/12/28/howto-how-to-use-goog-require-and-goog-provide-for-your-own-code/
2.Modules should reference other modules using the Angular Module's "name" property
For example:
// file submodulea.js: goog.provide('my.submoduleA'); my.submoduleA = angular.module('my.submoduleA', []); // ... // file app.js goog.require('my.submoduleA'); Yes: my.application.module = angular.module('hello', [my.submoduleA.name]); No: my.application.module = angular.module('hello', ['my.submoduleA']);Why? Using a property of my.submoduleA prevents Closure presubmit failures complaining that the file is required but never used. Using the .name property avoids duplicating strings.
Use a common externs file
This maximally allows the JS compiler to enforce type safety in the presence of externally provided types from Angular, and means you don't have to worry about Angular vars being obfuscated in a confusing way.Note to readers outside Google: the current externs file is located in an internal-to-Google directory, but an example can be found on github here.
JSCompiler Flags
Reminder: According to the JS style guide, customer facing code must be compiled.Recommended: Use the JSCompiler (the closure compiler that works with js_binary by default) and ANGULAR_COMPILER_FLAGS_FULL from //javascript/angular/build_defs/build_defs for your base flags.
Note - if you are using @export for methods, you will need to add the compiler flag
"--generate_exports",If you are using @export for properties, you will need to add the flags:
"--generate_exports", "--remove_unused_prototype_props_in_externs=false", "--export_local_property_definitions",
Controllers and Scopes
Controllers are classes. Methods should be defined on MyCtrl.prototype. See the JavaScript style guideGoogle Angular applications should use the 'controller as' style to export the controller onto the scope. This is fully implemented in Angular 1.2 and can be mimicked in pre-Angular 1.2 builds.
Pre Angular 1.2, this looks like:
/** * Home controller. * * @param {!angular.Scope} $scope * @constructor * @ngInject * @export */ hello.mainpage.HomeCtrl = function($scope) { /** @export */ $scope.homeCtrl = this; // This is a bridge until Angular 1.2 controller-as /** * @type {string} * @export */ this.myColor = 'blue'; }; /** * @param {number} a * @param {number} b * @export */ hello.mainpage.HomeCtrl.prototype.add = function(a, b) { return a + b; };And the template:
<div ng-controller="hello.mainpage.HomeCtrl"/>
<span ng-class="homeCtrl.myColor">I'm in a color!</span>
<span>{{
homeCtrl.add(5, 6)}}</span>
</div>
After Angular 1.2, this looks like:
/** * Home controller. * * @constructor * @ngInject * @export */ hello.mainpage.HomeCtrl = function() { /** * @type {string} * @export */ this.myColor = 'blue'; }; /** * @param {number} a * @param {number} b * @export */ hello.mainpage.HomeCtrl.prototype.add = function(a, b) { return a + b; };If you are compiling with property renaming, expose properties and methods using the @export annotation. Remember to @export the constructor as well.
And in the template:
<div ng-controller="hello.mainpage.HomeCtrl as homeCtrl"/>
<span ng-class="homeCtrl.myColor">I'm in a color!</span>
<span>{{homeCtrl.add(5, 6)}}</span>
</div>
Why? Putting methods and properties directly onto the controller, instead of building up a scope object, fits better with the Google Closure class style. Additionally, using 'controller as' makes it obvious which controller you are accessing when multiple controllers apply to an element. Since there is always a '.' in the bindings, you don't have to worry about prototypal inheritance masking primitives.Directives
All DOM manipulation should be done inside directives. Directives should be kept small and use composition. Files defining directives should goog.provide a static function which returns the directive definition object.goog.provide('hello.pane.paneDirective'); /** * Description and usage * @return {angular.Directive} Directive definition object. */ hello.pane.paneDirective = function() { // ... };Exception: DOM manipulation may occur in services for DOM elements disconnected from the rest of the view, e.g. dialogs or keyboard shortcuts.
Services
Services registered on the module withmodule.service are classes. Use module.service instead of module.provider or module.factory unless you need to do initialization beyond just creating a new instance of the class./** * @param {!angular.$http} $http The Angular http service. * @constructor */ hello.request.Request = function($http) { /** @type {!angular.$http} */ this.http_ = $http; }; hello.request.Request.prototype.get = function() {/*...*/};In the module:
module.service('request', hello.request.Request
No comments:
Post a Comment