angular.js v1.0.0.rc1 Release Notes

Release Date: 2012-03-13 // about 12 years ago
  • $compile rewrite

    The compiler was completely rewritten from scratch using ideas from this ๐Ÿ“„ design document. Please check out the [$compile] and ๐Ÿ“„ $compileProvider.directive ๐Ÿ“„ docs. The biggest improvements and changes are listed below.

    • ๐Ÿ‘ the compiler now transparently supports several directive syntaxes. For example while before there was just one way to use ng:include directive: <ng:include src="someSrc"></ng:include>. The new compiler treats all of the following as equivalent:

      • <ng:include src="someSrc"></ng:include>
      • <ng-include src="someSrc"></ng-include>
      • <x-ng-include src="someSrc"></x-ng-include>
      • <div ng:include src="someSrc"></div>
      • <div ng-include src="someSrc"></div>
      • <div data-ng-include src="someSrc"></div>
      • <div ng:include="someSrc"></div>
      • <div ng-include="someSrc"></div>
      • <div data-ng-include="someSrc"></div>
      • <div class="ng-include: someSrc"></div>

    This will give template creators great flexibility to consider the tradeoffs between html code validity and code conciseness and pick the syntax that works the best for them.

    • ๐Ÿ’… we are switching all of our code/docs/examples to use ng-foo directive name style instead of ng:foo. The new compiler doesn't distinguish between these and other name styles (all of them are equally supported), the main difference is that ng-foo is easier to select with css selectors. Check out the Internet Explorer Compatibility doc to learn about various IE-related requirements for different directive naming styles.

    • ๐Ÿ”€ angular.directive, angular.widget, angular.attrWidget were merged into a single concept: a directive which is registered via myModule.directive or $compileProvider.directive. You can control execution priority of multiple directives on the same element (previously the main difference between a attribute widget and a directive) via a directive priority setting.

    • previously the linking functions of directives were called top to bottom following the DOM tree, to enable a linking fn to work child DOM nodes that were already processed by child linking fns the order was changed as follows: compile functions run top to bottom following the DOM tree, but linking functions run bottom-up following the DOM tree. In some rare cases it is desirable for linking fns to be called top to bottom and for these it is possible to register "prelinking" functions (check out the docs for the return value of the compile function).

    • angular.markup and angular.attrMarkup were replaced with interpolation via $interpolate service.

      • In the past {{foo}} markup was getting translated to <span ng-bind="foo"></span> during the early stage of template compilation. Addition of this extra node was in some cases undesirable and caused problems. The new compiler with the help of the $interpolate service removes the need for these artificial nodes.
      • As a side-effect of not using artificial nodes available for all bindings, the html filter which used to innerHTML (sanitized) html into the artificial node was converted into a directive. So instead of {{ someRawHtml | html }} use <div ng-bind-html="someRawHtml"></div> and instead of {{ someRawHtml | html:"unsafe" }} use <div ng-bind-html-unsafe="someRawHtml"></div>. Please check out the ng-bind-html and ng-bind-html-unsafe directive docs.
      • Custom markup has been used by developers only to switch from {{ }} markup to (( )) or something similar in order to avoid conflicts with server-side templating libraries. We made it easier to do this kind of customization by making the start and end symbol of the interpolation configurable via $interpolateProvider.
    • ๐Ÿ“„ template loader loads template fragments from script elements and populates the $templateCache with them. Templates loaded in this way can be then used with ng-include, ng-view as well as directive templates (see the templateUrl property of the directive config object).

    Forms / input controls / two-way data binding

    The implementation of forms and input bindings was modified to address issues around composability, ease of adding custom validation and formatting. Please check out the ๐Ÿ“„ forms dev guide article to learn about forms, form control bindings and input validation. The biggest changes are listed below.

    • ๐Ÿ“œ any directive can add formatter/parser (validators, convertors) to an input type. This allows better composability of input types with custom validators and formatters. So instead of creating new custom input type for everything, it's now possible to take existing input type and add an additional formatter and/or validator to it via a custom directive.

    • 0๏ธโƒฃ inputs propagates changes only on the blur event by default (use new ng-model-instant directive if you want to propagate changes on each keystroke).

    • no more custom input types, use directives to customize existing types.

    • โœ‚ removed $formFactory.

    • โœ‚ removed parallel scope hierarchy (forms, widgets).

    • โœ‚ removed list input type (use ng-list directive instead).

    • โœ‚ removed integer input type.

    Controller-scope separation

    Controllers are now standalone objects, created using the "new" operator, and not mixed with scope object anymore. This addresses many issues including: #321 and #425.

    ๐Ÿ“„ The design doc explains the reasoning for this major change and how it solves many issues.

    Before:

    function MyCtrl() { var self = this;

    this.model = 'some model of any type';

    this.fnUsedFromTemplate = function() { someApiThatTakesCallback(function callbackFn() { self.model = 'updatedModel'; }); }; }

    After:

    function MyCtrl($scope) { $scope.model = 'some model of any type';

    $scope.fnUsedFromTemplate = function() { someApiThatTakesCallback(function() { $scope.model = 'updatedModel'; }); } }

    Temporary backwards compatibility: Load the following module in your app to recreate the previous behavior and migrate your controllers one at a time: https://gist.github.com/1649788

    $route service changes

    • ๐Ÿ”ง As advertised in the past we moved the $route configuration from the run phase of the application to the config phase. This means that instead of defining routes via $route.when/$route.otherwise you should use $routeProvider.when/$routeProvider.otherwise instead.

    • route scope is now being created by the ng-view rather than by $route, this resolved many issues we've previously faced. For more info, read the commit message.

    • โœ‚ removed $route.parent() - it's unnecessary because the scope is properly created in the scope hierarchy by ng-view.

    • ๐Ÿ†• new $viewContentLoaded and $includeContentLoaded events which directives can use to be notified when a template content is (re)loaded.

    • ng-view now has onload attribute which behaves similarly to the one on ng-include.

    Directives

    • ๐Ÿ‘ ng-model binding on select[multiple] element should support binding to an array (commit)
    • event object is now accessible as $event in ng-click and other directives (commit, issue #259
    • ๐Ÿ‘ ng-class directive now support map of classnames and conditions e.g. <div ng-class="{'hide': !visible, 'warning': isAlert()}"... (contributed by Kai Groner) (commit)

    Scope changes

    • scope.$emit/$broadcast return the event object, add cancelled property (commit)

    • scope.$new() takes one argument - a boolean indicating if the newly-created child scope should be isolated (not prototypically inheriting from the current scope). Previously the first argument was reference to the controller constructor, but because of the scope/controller separation the controllers should be instantiated via the $controller service. (commit)

    • fn signature change for change listener functions registered via scope.$watch - this means that the scope object can be listed in the arguments list only if it's needed and skipped otherwise. (commit)

      • before: scope.$watch('someModel', function(scope, newVal, oldVal) {})
      • after: scope.$watch('someModel', function(newVal, oldVal, scope) {})
    • scope.$watch now compares object by reference and only if extra boolean flag is passed comparison by equality is used. This was done to avoid unintended performance issues. (commit)

      • before: scope.$watch('expression', function(scope, newVal, oldVal) {})
      • after: scope.$watch('expression', function(newVal, oldVal, scope) {}, true)
    • scope.$destroy doesn't cause the $destroy event to be emitted any more - this event was primarily used by the old forms implementation and is not needed any more. We are considering broadcasting this event in the future, which could then be used by directives and child scopes to be notified of their scope destruction.

    ๐Ÿ†• New directives:

    $injector / modules

    • $injector.instantiate should return the object returned from constructor if one was returned (commit)
    • ๐Ÿ‘ $injector.instantiate should support array annotations for Type argument (e.g. instantiate(['dep1', 'dep2', Type])) (commit)
    • quickly fail if circular dependencies are detected during instantiation (commit)
    • โž• added $provide.constant to enable registration of constants that are available in both the config and run phase (commit)
    • $provide.service was renamed to $provide.provider (commit)
    • $provide.service takes a constructor fn and creates a service instance by using $injector.instantiate

    ๐Ÿ†• New services:

    jqLite (angular.element)

    • โž• added contents() (commit)
    • โž• added wrap() (commit)
    • ๐Ÿ›  fix memory leaking in IE8 (remove monkey patched methods on Event) (commit, commit)

    ๐Ÿ“„ Docs

    ๐Ÿ›  Small bug fixes

    • ๐Ÿ›  fix incorrect comparison of dates by angular.equals (commit)
    • ๐Ÿ‘ scope.$watch support watching functions (commit, commit)
    • $http should not json-serialize File objects, instead just send them raw (commit)
    • ๐Ÿ’… $compile should ignore content of style and script elements (commit, commit)
    • TzDate#getDay() should take into account the timezone offset (contributed by Stephane Bisson) (commit)

    Small features

    • ๐Ÿ“œ $parse service now supports local vars in expressions (commit)