I have the following situation with Angular:
Controller
function Controller () {
// form used in template
this.form ...
}
Template that has a form and uses this controller
Template
<div ng-controller="Controller as ctrl">
<form name="ctrl.form">
...
</div>
I have to say I'm in general confused why Angular doesn't have a better way of adding the form to the controller other than automatically adding either this.form
or $scope.form
, depending on how you use controllers, but that's I guess another question.
The real issue I have right now is that I'm not sure how I should test this. If I just instantiate the controller in the test, then my form is undefined
$controller('Controller as ctrl')
I did find a way, by just compiling the template
$scope = $rootScope.$new();
$compile(template)($scope);
But because ng-controller
in the template starts a new scope, I can't access the controller directly with $scope.ctrl
, instead I'd have to do something like $scope.$$childHead.login
... and I feel it's getting too complicated. edit: not to mention that $$ indicates a 'private' property.
I've solved it myself, but I'm leaving it here unaccepted because I don't think the solution is very nice. If anyone knows a better way, please post.
The problem with compiling templates is that it's also not possible to insert mock services in the controller, at least I didn't figure it out. You get a controller instance on $scope, like
$scope.ctrl
, but that's it.The second attempt was to locate just the form in the template, compile and add it to a controller that was instantiated separately. This worked, but not really, because the $scope for the form and controller were different and so any update to a field didn't reflect on the controller state.
The way it works in the end is to instantiate the controller with a $scope
and then to compile the partial template (just the form) with the same $scope
This way, the controller ends up in
$scope.ctrl
, but because the form is already namedname="ctrl.form"
it gets inserted into$scope.ctrl.form
and it's visible inside a controller.