diff options
| author | Vojta Jina | 2011-11-29 21:51:59 -0800 | 
|---|---|---|
| committer | Vojta Jina | 2012-01-23 11:05:36 -0800 | 
| commit | 992c790f0786fa45c1cc3710f29bf49c7c322ba7 (patch) | |
| tree | 581d06ea9ba275a14d5891d83b2df03f9930bd45 /src/service | |
| parent | f5343c9fd3c7cd0fefdb4d71d2b579dbae998d6a (diff) | |
| download | angular.js-992c790f0786fa45c1cc3710f29bf49c7c322ba7.tar.bz2 | |
refactor(scope): separate controller from scope
Controller is standalone object, created using "new" operator, not messed up with scope anymore.
Instead, related scope is injected as $scope.
See design proposal: https://docs.google.com/document/pub?id=1SsgVj17ec6tnZEX3ugsvg0rVVR11wTso5Md-RdEmC0k
Closes #321
Closes #425
Breaks controller methods are not exported to scope automatically
Breaks Scope#$new() does not take controller as argument anymore
Diffstat (limited to 'src/service')
| -rw-r--r-- | src/service/compiler.js | 2 | ||||
| -rw-r--r-- | src/service/filter/filters.js | 16 | ||||
| -rw-r--r-- | src/service/filter/limitTo.js | 6 | ||||
| -rw-r--r-- | src/service/filter/orderBy.js | 6 | ||||
| -rw-r--r-- | src/service/formFactory.js | 41 | ||||
| -rw-r--r-- | src/service/http.js | 29 | ||||
| -rw-r--r-- | src/service/route.js | 10 | ||||
| -rw-r--r-- | src/service/scope.js | 19 | 
8 files changed, 63 insertions, 66 deletions
diff --git a/src/service/compiler.js b/src/service/compiler.js index 727f7983..adf1ffa9 100644 --- a/src/service/compiler.js +++ b/src/service/compiler.js @@ -22,7 +22,7 @@ function $CompileProvider(){            var childScope = scope,                locals = {$element: element};            if (this.newScope) { -            childScope = isFunction(this.newScope) ? scope.$new(this.newScope(scope)) : scope.$new(); +            childScope = scope.$new();              element.data($$scope, childScope);            }            forEach(this.linkFns, function(fn) { diff --git a/src/service/filter/filters.js b/src/service/filter/filters.js index 3e7f8e37..69bfbacf 100644 --- a/src/service/filter/filters.js +++ b/src/service/filter/filters.js @@ -18,8 +18,8 @@     <doc:example>       <doc:source>         <script> -         function Ctrl() { -           this.amount = 1234.56; +         function Ctrl($scope) { +           $scope.amount = 1234.56;           }         </script>         <div ng:controller="Ctrl"> @@ -69,8 +69,8 @@ function currencyFilter($locale) {     <doc:example>       <doc:source>         <script> -         function Ctrl() { -           this.val = 1234.56789; +         function Ctrl($scope) { +           $scope.val = 1234.56789;           }         </script>         <div ng:controller="Ctrl"> @@ -448,8 +448,8 @@ var uppercaseFilter = valueFn(uppercase);     <doc:example>       <doc:source>         <script> -         function Ctrl() { -           this.snippet = +         function Ctrl($scope) { +           $scope.snippet =               '<p style="color:blue">an html\n' +               '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +               'snippet</p>'; @@ -538,8 +538,8 @@ function htmlFilter() {     <doc:example>       <doc:source>         <script> -         function Ctrl() { -           this.snippet = +         function Ctrl($scope) { +           $scope.snippet =               'Pretty text with some links:\n'+               'http://angularjs.org/,\n'+               'mailto:us@somewhere.org,\n'+ diff --git a/src/service/filter/limitTo.js b/src/service/filter/limitTo.js index a250bd3b..eb97fdad 100644 --- a/src/service/filter/limitTo.js +++ b/src/service/filter/limitTo.js @@ -25,9 +25,9 @@     <doc:example>       <doc:source>         <script> -         function Ctrl() { -           this.numbers = [1,2,3,4,5,6,7,8,9]; -           this.limit = 3; +         function Ctrl($scope) { +           $scope.numbers = [1,2,3,4,5,6,7,8,9]; +           $scope.limit = 3;           }         </script>         <div ng:controller="Ctrl"> diff --git a/src/service/filter/orderBy.js b/src/service/filter/orderBy.js index 2e5a0286..c67d2769 100644 --- a/src/service/filter/orderBy.js +++ b/src/service/filter/orderBy.js @@ -32,14 +32,14 @@     <doc:example>       <doc:source>         <script> -         function Ctrl() { -           this.friends = +         function Ctrl($scope) { +           $scope.friends =                 [{name:'John', phone:'555-1212', age:10},                  {name:'Mary', phone:'555-9876', age:19},                  {name:'Mike', phone:'555-4321', age:21},                  {name:'Adam', phone:'555-5678', age:35},                  {name:'Julie', phone:'555-8765', age:29}] -           this.predicate = '-age'; +           $scope.predicate = '-age';           }         </script>         <div ng:controller="Ctrl"> diff --git a/src/service/formFactory.js b/src/service/formFactory.js index 15a4733f..565b22a4 100644 --- a/src/service/formFactory.js +++ b/src/service/formFactory.js @@ -25,15 +25,13 @@      <doc:example>        <doc:source>          <script> -          function EditorCntl() { -            this.html = '<b>Hello</b> <i>World</i>!'; +          function EditorCntl($scope) { +            $scope.html = '<b>Hello</b> <i>World</i>!';            } -          HTMLEditorWidget.$inject = ['$element', 'htmlFilter']; -          function HTMLEditorWidget(element, htmlFilter) { -            var self = this; - -            this.$parseModel = function() { +          HTMLEditorWidget.$inject = ['$element', '$scope', 'htmlFilter']; +          function HTMLEditorWidget(element, scope, htmlFilter) { +            scope.$parseModel = function() {                // need to protect for script injection                try {                  this.$viewValue = htmlFilter(this.$modelValue || '').get(); @@ -47,13 +45,13 @@                }              } -            this.$render = function() { +            scope.$render = function() {                element.html(this.$viewValue);              }              element.bind('keyup', function() { -              self.$apply(function() { -                self.$emit('$viewChange', element.html()); +              scope.$apply(function() { +                scope.$emit('$viewChange', element.html());                });              });            } @@ -104,7 +102,8 @@  function $FormFactoryProvider() {    var $parse; -  this.$get = ['$rootScope', '$parse',  function($rootScope, $parse_) { +  this.$get = ['$rootScope', '$parse', '$injector', +      function($rootScope, $parse_, $injector) {      $parse = $parse_;      /**       * @ngdoc proprety @@ -136,7 +135,9 @@ function $FormFactoryProvider() {      return formFactory;      function formFactory(parent) { -      return (parent || formFactory.rootForm).$new(FormController); +      var scope = (parent || formFactory.rootForm).$new(); +      $injector.instantiate(FormController, {$scope: scope}); +      return scope;      }    }]; @@ -230,8 +231,11 @@ function $FormFactoryProvider() {     * @param {*} viewValue The new value for the view which will be assigned to `widget.$viewValue`.     */ -  function FormController() { -    var form = this, +  FormController.$inject = ['$scope', '$injector']; +  function FormController($scope, $injector) { +    this.$injector = $injector; + +    var form = this.form = $scope,          $error = form.$error = {};      form.$on('$destroy', function(event){ @@ -257,6 +261,7 @@ function $FormFactoryProvider() {      });      propertiesUpdate(form); +    form.$createWidget = bind(this, this.$createWidget);      function removeWidget(queue, errorKey, widget) {        if (queue) { @@ -354,17 +359,19 @@ function $FormFactoryProvider() {     * @returns {Widget} Instance of a widget scope.     */    FormController.prototype.$createWidget = function(params) { -    var form = this, +    var form = this.form,          modelScope = params.scope,          onChange = params.onChange,          alias = params.alias,          scopeGet = $parse(params.model),          scopeSet = scopeGet.assign, -        widget = this.$new(params.controller, params.controllerArgs); +        widget = form.$new(); + +    this.$injector.instantiate(params.controller, extend({$scope: widget}, params.controllerArgs));      if (!scopeSet) {        throw Error("Expression '" + params.model + "' is not assignable!"); -    }; +    }      widget.$error = {};      // Set the state to something we know will change to get the process going. diff --git a/src/service/http.js b/src/service/http.js index b008aa8e..9d57ed76 100644 --- a/src/service/http.js +++ b/src/service/http.js @@ -395,29 +395,28 @@ function $HttpProvider() {          <doc:example>            <doc:source jsfiddle="false">              <script> -              function FetchCtrl($http) { -                var self = this; -                this.method = 'GET'; -                this.url = 'examples/http-hello.html'; +              function FetchCtrl($scope, $http) { +                $scope.method = 'GET'; +                $scope.url = 'examples/http-hello.html'; -                this.fetch = function() { -                  self.code = null; -                  self.response = null; +                $scope.fetch = function() { +                  $scope.code = null; +                  $scope.response = null; -                  $http({method: self.method, url: self.url}). +                  $http({method: $scope.method, url: $scope.url}).                      success(function(data, status) { -                      self.status = status; -                      self.data = data; +                      $scope.status = status; +                      $scope.data = data;                      }).                      error(function(data, status) { -                      self.data = data || "Request failed"; -                      self.status = status; +                      $scope.data = data || "Request failed"; +                      $scope.status = status;                    });                  }; -                this.updateModel = function(method, url) { -                  self.method = method; -                  self.url = url; +                $scope.updateModel = function(method, url) { +                  $scope.method = method; +                  $scope.url = url;                  };                }              </script> diff --git a/src/service/route.js b/src/service/route.js index 77d94e9c..04bcfdb6 100644 --- a/src/service/route.js +++ b/src/service/route.js @@ -63,8 +63,8 @@      </doc:example>   */  function $RouteProvider(){ -  this.$get = ['$rootScope', '$location', '$routeParams', -      function( $rootScope,  $location,  $routeParams) { +  this.$get = ['$rootScope', '$location', '$routeParams', '$injector', +      function( $rootScope,  $location,  $routeParams, $injector) {      /**       * @ngdoc event       * @name angular.module.ng.$route#$beforeRouteChange @@ -278,8 +278,10 @@ function $RouteProvider(){              }            } else {              copy(next.params, $routeParams); -            (Controller = next.controller) && inferInjectionArgs(Controller); -            next.scope = parentScope.$new(Controller); +            next.scope = parentScope.$new(); +            if (next.controller) { +              $injector.instantiate(next.controller, {$scope: next.scope}); +            }            }          }          $rootScope.$broadcast('$afterRouteChange', next, last); diff --git a/src/service/scope.js b/src/service/scope.js index fe72c953..089e4a41 100644 --- a/src/service/scope.js +++ b/src/service/scope.js @@ -126,8 +126,9 @@ function $RootScopeProvider(){         * @function         *         * @description -       * Creates a new child {@link angular.module.ng.$rootScope.Scope scope}. The new scope can optionally behave as a -       * controller. The parent scope will propagate the {@link angular.module.ng.$rootScope.Scope#$digest $digest()} and +       * Creates a new child {@link angular.module.ng.$rootScope.Scope scope}. +       * +       * The parent scope will propagate the {@link angular.module.ng.$rootScope.Scope#$digest $digest()} and         * {@link angular.module.ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope         * hierarchy using {@link angular.module.ng.$rootScope.Scope#$destroy $destroy()}.         * @@ -135,13 +136,10 @@ function $RootScopeProvider(){         * the scope and its child scopes to be permanently detached from the parent and thus stop         * participating in model change detection and listener notification by invoking.         * -       * @param {function()=} Class Constructor function which the scope should be applied to the scope. -       * @param {...*} curryArguments Any additional arguments which are curried into the constructor. -       *        See {@link guide/dev_guide.di dependency injection}.         * @returns {Object} The newly created child scope.         *         */ -      $new: function(Class, curryArguments) { +      $new: function() {          var Child = function() {}; // should be anonymous; This is so that when the minifier munges            // the name it does not become random set of chars. These will then show up as class            // name in the debugger. @@ -161,15 +159,6 @@ function $RootScopeProvider(){          } else {            this.$$childHead = this.$$childTail = child;          } -        // short circuit if we have no class -        if (Class) { -          // can't use forEach, we need speed! -          var ClassPrototype = Class.prototype; -          for(var key in ClassPrototype) { -            child[key] = bind(child, ClassPrototype[key]); -          } -          $injector.invoke(Class, child, curryArguments); -        }          return child;        },  | 
