Skip to content

Commit

Permalink
fix($controller): throw better error when controller expression is bad
Browse files Browse the repository at this point in the history
Previously, the error was a JS runtime error when trying to access a property of `null`. But, it's
a bit nicer to throw a real error and provide a description of how to fix it. Developer ergonomics
and all that.

Closes angular#10875
Closes angular#10910
  • Loading branch information
caitp committed Jan 29, 2015
1 parent aa0f644 commit dda65e9
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 2 deletions.
46 changes: 46 additions & 0 deletions docs/content/error/$controller/ctrlfmt.ngdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
@ngdoc error
@name $controller:ctrlfmt
@fullName Badly formed controller string
@description

This error occurs when {@link ng.$controller $controller} service is called
with a string that does not match the supported controller string formats.

Supported formats:

1. `__name__`
2. `__name__ as __identifier__`

N'either `__name__` or `__identifier__` may contain spaces.

Example of incorrect usage that leads to this error:
```html
<!-- unclosed ng-controller attribute messes up the format -->
<div ng-controller="myController>
```

or

```js
// does not match `__name__` or `__name__ as __identifier__`
var myCtrl = $controller("mY contRoller", { $scope: newScope });
```

or

```js
directive("myDirective", function() {
return {
// does not match `__name__` or `__name__ as __identifier__`
controller: "mY contRoller",
link: function() {}
};
});
```

To fix the examples above, ensure that the controller string matches the supported
formats, and that any html attributes which are used as controller expressions are
closed.


Please consult the {@link ng.$controller $controller} service api docs to learn more.
9 changes: 8 additions & 1 deletion src/ng/controller.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

var $controllerMinErr = minErr('$controller');

/**
* @ngdoc provider
* @name $controllerProvider
Expand Down Expand Up @@ -87,7 +89,12 @@ function $ControllerProvider() {
}

if (isString(expression)) {
match = expression.match(CNTRL_REG),
match = expression.match(CNTRL_REG);
if (!match) {
throw new $controllerMinErr('ctrlfmt',
"Badly formed controller string '{0}'. " +
"Must match `__name__ as __id__` or `__name__`.", expression);
}
constructor = match[1],
identifier = identifier || match[3];
expression = controllers.hasOwnProperty(constructor)
Expand Down
43 changes: 42 additions & 1 deletion test/ng/controllerSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,16 @@ describe('$controller', function() {
var foo = $controller('a.Foo', {$scope: scope});
expect(foo).toBeDefined();
expect(foo instanceof Foo).toBe(true);
}));
}));


it('should throw ctrlfmt if name contains spaces', function() {
expect(function() {
$controller('ctrl doom');
}).toThrowMinErr("$controller", "ctrlfmt",
"Badly formed controller string 'ctrl doom'. " +
"Must match `__name__ as __id__` or `__name__`.");
});
});


Expand Down Expand Up @@ -168,5 +177,37 @@ describe('$controller', function() {
}).toThrowMinErr("$controller", "noscp", "Cannot export controller 'a.b.FooCtrl' as 'foo'! No $scope object provided via `locals`.");

});


it('should throw ctrlfmt if identifier contains non-ident characters', function() {
expect(function() {
$controller('ctrl as foo<bar');
}).toThrowMinErr("$controller", "ctrlfmt",
"Badly formed controller string 'ctrl as foo<bar'. " +
"Must match `__name__ as __id__` or `__name__`.");
});


it('should throw ctrlfmt if identifier contains spaces', function() {
expect(function() {
$controller('ctrl as foo bar');
}).toThrowMinErr("$controller", "ctrlfmt",
"Badly formed controller string 'ctrl as foo bar'. " +
"Must match `__name__ as __id__` or `__name__`.");
});


it('should throw ctrlfmt if identifier missing after " as "', function() {
expect(function() {
$controller('ctrl as ');
}).toThrowMinErr("$controller", "ctrlfmt",
"Badly formed controller string 'ctrl as '. " +
"Must match `__name__ as __id__` or `__name__`.");
expect(function() {
$controller('ctrl as');
}).toThrowMinErr("$controller", "ctrlfmt",
"Badly formed controller string 'ctrl as'. " +
"Must match `__name__ as __id__` or `__name__`.");
});
});
});

0 comments on commit dda65e9

Please sign in to comment.