From 570df3bb3976c91e43615d7ac39bf37f5a6a7932 Mon Sep 17 00:00:00 2001
From: Mike Frysinger This is the external version of a document that was primarily written for Google
- engineers. It describes a recommended style for AngularJS apps that use Closure, as used
- internally at Google. Members of the broader AngularJS community should feel free to apply
- (or not apply) these recommendations, as relevant to their own use cases. This document describes style for AngularJS apps in google3. This guide
- supplements and extends the
- Google JavaScript Style Guide.
- Style Note: Examples on the AngularJS external webpage, and many external apps, are
- written in a style that freely uses closures, favors functional inheritance, and does not often use
-
- JavaScript types. Google follows a more rigorous Javascript style to support JSCompiler
- optimizations and large code bases - see the javascript-style mailing list.
- This is not an Angular-specific issue, and is not discussed further in this style guide.
- (But if you want further reading:
- Martin Fowler on closures,
- much longer description, appendix A of the
-
- closure book has a good description of inheritance patterns and why it prefers
- pseudoclassical,
-
- Javascript, the Good Parts as a counter.) Choose a namespace for your project, and use goog.provide and goog.require. Why?
- Google BUILD rules integrate nicely with closure provide/require. Your main application module should be in your root client directory. A module should never be
- altered other than the one where it is defined. Modules may either be defined in the same file as their components (this works well for a module
- that contains exactly one service) or in a separate file for wiring pieces together. Why?
- A module should be consistent for anyone that wants to include it as a reusable component.
- If a module can mean different things depending on which files are included, it is not consistent.
- For example: 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. 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. 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 If you are using @export for properties, you will need to add the flags: Controllers are classes. Methods should be defined on MyCtrl.prototype. 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: And the template: After Angular 1.2, this looks like: 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: 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. 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. Exception: DOM manipulation may occur in services for DOM elements disconnected from the
- rest of the view, e.g. dialogs or keyboard shortcuts. Services registered on the module with In the module: Do not use $ to prepend your own object properties and service identifiers. Consider this style
- of naming reserved by AngularJS and jQuery. Yes: No: Why?
- It's useful to distinguish between Angular / jQuery builtins and things you add yourself.
- In addition, $ is not an acceptable character for variables names in the JS style guide.
- For custom elements (e.g. These are not strict style guide rules, but are placed here as reference for folks getting
- started with Angular at Google. Angular is designed for test-driven development. The recommended unit testing setup is Jasmine + Karma (though you could use closure tests
- or js_test) Angular provides easy adapters to load modules and use the injector in Jasmine tests.
-
+[angular]: https://angular.dev/style-guide
[cpp]: https://google.github.io/styleguide/cppguide.html
[csharp]: csharp-style.md
[swift]: https://google.github.io/swift/
@@ -93,7 +93,6 @@ primarily optimizing for Google's internal needs.
[js]: https://google.github.io/styleguide/jsguide.html
[markdown]: docguide/style.md
[ts]: https://google.github.io/styleguide/tsguide.html
-[angular]: https://google.github.io/styleguide/angularjs-google-style.html
[cl]: lispguide.md
[vim]: vimscriptguide.md
[emacs]: https://raw.githubusercontent.com/google/styleguide/gh-pages/google-c-style.el
diff --git a/angularjs-google-style.html b/angularjs-google-style.html
deleted file mode 100644
index 6ca190b..0000000
--- a/angularjs-google-style.html
+++ /dev/null
@@ -1,367 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- An AngularJS Style Guide for Closure Users at Google
-
-Background
-
-1 Angular Language Rules
-
-Manage dependencies with Closure's goog.require and goog.provide
-
-goog.provide('hello.about.AboutCtrl');
-goog.provide('hello.versions.Versions');
-
-
-Modules
-
-
- Modules should reference other modules using the Angular Module's "name" property
-
-
-
-// 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']);
-
-
-Use a common externs file
-
-JSCompiler Flags
-
-"--generate_exports",
-
-
-
-"--generate_exports",
-"--remove_unused_prototype_props_in_externs=false",
-"--export_local_property_definitions",
-
-
-Controllers and Scopes
-
-/**
- * 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;
-};
-
-
-
-<div ng-controller="hello.mainpage.HomeCtrl"/>
- <span ng-class="homeCtrl.myColor">I'm in a color!</span>
- <span>{{homeCtrl.add(5, 6)}}</span>
-</div>
-
-
-
-/**
- * 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;
-};
-
-
-
-<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>
-
-
-Directives
-
-
-goog.provide('hello.pane.paneDirective');
-
-/**
- * Description and usage
- * @return {angular.Directive} Directive definition object.
- */
-hello.pane.paneDirective = function() {
- // ...
-};
-
-
-Services
-
-module.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() {/*...*/};
-
-
-
-module.service('request', hello.request.Request);
-
-
-
-2 Angular Style Rules
-
-Reserve $ for Angular properties and services
-
- $scope.myModel = { value: 'foo' }
- myModule.service('myService', function() { /*...*/ });
- var MyCtrl = function($http) {this.http_ = $http;};
-
-
-
- $scope.$myModel = { value: 'foo' } // BAD
- $scope.myModel = { $value: 'foo' } // BAD
- myModule.service('$myService', function() { ... }); // BAD
- var MyCtrl = function($http) {this.$http_ = $http;}; // BAD
-
-
-Custom elements
-
-<ng-include src="template"></ng-include>), IE8
- requires special support (html5shiv-like hacks) to enable css styling. Be aware of this
- restriction in apps targeting old versions of IE.3 Angular Tips, Tricks, and Best Practices
-
-Testing
-
-
- This directory structure doc describes how to structure your application with controllers in - nested subdirectories and all components (e.g. services and directives) in a 'components' dir. -
- - -See - The Nuances of Scope Prototypal Inheritance
- -This removes the need to add myCtrl['$inject'] = ... to prevent minification from
- messing up Angular's dependency injection.
Usage:
-
-/**
- * My controller.
- * @param {!angular.$http} $http
- * @param {!my.app.myService} myService
- * @constructor
- * @export
- * @ngInject
- */
-my.app.MyCtrl = function($http, myService) {
- //...
-};
-
-
-