From cd38cbf975b501d846e6149d1d993972a1af0053 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Wed, 6 Jun 2012 15:54:40 -0700 Subject: [PATCH] feat(controller): support as instance syntax Support ng-controller="MyController as my" syntax which publishes the controller instance to the current scope. Also supports exporting a controller defined with route: ````javascript angular.module('routes', [], function($routeProvider) { $routeProvider.when('/home', {controller: 'Ctrl as home', templateUrl: '...'}); }); ```` --- src/ng/controller.js | 34 +++++++++---- src/ng/directive/ngController.js | 73 ++++++++++++++++++++++++++- src/ng/directive/ngView.js | 51 ++++++++++--------- src/ng/route.js | 2 + test/ng/controllerSpec.js | 11 ++++ test/ng/directive/ngControllerSpec.js | 23 +++++++++ test/ng/directive/ngViewSpec.js | 21 ++++++++ 7 files changed, 181 insertions(+), 34 deletions(-) diff --git a/src/ng/controller.js b/src/ng/controller.js index 0474e76613df..cfd730e41851 100644 --- a/src/ng/controller.js +++ b/src/ng/controller.js @@ -11,7 +11,8 @@ * {@link ng.$controllerProvider#register register} method. */ function $ControllerProvider() { - var controllers = {}; + var controllers = {}, + CNTRL_REG = /^(\w+)(\s+as\s+(\w+))?$/; /** @@ -56,17 +57,32 @@ function $ControllerProvider() { * a service, so that one can override this service with {@link https://gist.github.com/1649788 * BC version}. */ - return function(constructor, locals) { - if(isString(constructor)) { - var name = constructor; - constructor = controllers.hasOwnProperty(name) - ? controllers[name] - : getter(locals.$scope, name, true) || getter($window, name, true); + return function(expression, locals) { + var instance, match, constructor, identifier; - assertArgFn(constructor, name, true); + if(isString(expression)) { + match = expression.match(CNTRL_REG), + constructor = match[1], + identifier = match[3]; + expression = controllers.hasOwnProperty(constructor) + ? controllers[constructor] + : getter(locals.$scope, constructor, true) || getter($window, constructor, true); + + assertArgFn(expression, constructor, true); + } + + instance = $injector.instantiate(expression, locals); + + if (identifier) { + if (typeof locals.$scope !== 'object') { + throw new Error('Can not export controller as "' + identifier + '". ' + + 'No scope object provided!'); + } + + locals.$scope[identifier] = instance; } - return $injector.instantiate(constructor, locals); + return instance; }; }]; } diff --git a/src/ng/directive/ngController.js b/src/ng/directive/ngController.js index 438a0d87c1ce..be2f149f4a1a 100644 --- a/src/ng/directive/ngController.js +++ b/src/ng/directive/ngController.js @@ -21,7 +21,8 @@ * @scope * @param {expression} ngController Name of a globally accessible constructor function or an * {@link guide/expression expression} that on the current scope evaluates to a - * constructor function. + * constructor function. The controller instance can further be published into the scope + * by adding `as localName` the controller name attribute. * * @example * Here is a simple form for editing user contact information. Adding, removing, clearing, and @@ -29,8 +30,75 @@ * easily be called from the angular markup. Notice that the scope becomes the `this` for the * controller's instance. This allows for easy access to the view data from the controller. Also * notice that any changes to the data are automatically reflected in the View without the need - * for a manual update. + * for a manual update. The example is included in two different declaration styles based on + * your style preferences. + + +
+ Name: + [ greet ]
+ Contact: +
    +
  • + + + [ clear + | X ] +
  • +
  • [ add ]
  • +
+
+
+ + it('should check controller', function() { + expect(element('.doc-example-live div>:input').val()).toBe('John Smith'); + expect(element('.doc-example-live li:nth-child(1) input').val()) + .toBe('408 555 1212'); + expect(element('.doc-example-live li:nth-child(2) input').val()) + .toBe('john.smith@example.org'); + + element('.doc-example-live li:first a:contains("clear")').click(); + expect(element('.doc-example-live li:first input').val()).toBe(''); + + element('.doc-example-live li:last a:contains("add")').click(); + expect(element('.doc-example-live li:nth-child(3) input').val()) + .toBe('yourname@example.org'); + }); + +
+ + + +