I have an abstract parent view that is meant to share a controller with its nested views.
.state('edit', {
abstract: true,
url: '/home/edit/:id',
templateUrl: 'app/templates/editView.html',
controller: 'editController'
})
.state('edit.details', {
url: '/details',
templateUrl: 'app/templates/editDetailsView.html'
})
.state('edit.info', {
url: '/info',
templateUrl: 'app/templates/editInfoView.html'
})
The routing works as expected.
The problem is that when I update a $scope
variable from one of the nested views, the change is not reflected in the view. When I do the same from the parent view, it works fine. This is not situation that requires an $apply
.
My guess is that a new instance of editController
is being created for each view, but I'm not sure why or how to fix it.
The issue here would be related to this Q & A: How do I share $scope data between states in angularjs ui-router?.
The way how to solve it is hidden in the:
In AngularJS, a child scope normally prototypically inherits from its parent scope.
...Having a '.' in your models will ensure that prototypal inheritance is in play.
// So, use
<input type="text" ng-model="someObj.prop1">
// rather than
<input type="text" ng-model="prop1">.
And also this
Keep in mind that scope properties only inherit down the state chain if the views of your states are nested. Inheritance of scope properties has nothing to do with the nesting of your states and everything to do with the nesting of your views (templates).
It is entirely possible that you have nested states whose templates populate ui-views at various non-nested locations within your site. In this scenario you cannot expect to access the scope variables of parent state views within the views of children states.
Having that we should do this in edit Controller
controller('editController', function ($scope) {
$scope.Model = $scope.Model || {SomeProperty : "xxx"};
})
And we can even reuse that controller: 'editController'
(we can do not have to, because the $scope.Model will be there - thanks to inheritance)
.state('edit', {
abstract: true,
url: '/home/edit/:id',
templateUrl: 'app/templates/editView.html',
controller: 'editController'
})
.state('edit.details', {
url: '/details',
templateUrl: 'app/templates/editDetailsView.html',
controller: 'editController'
})
.state('edit.info', {
url: '/info',
templateUrl: 'app/templates/editInfoView.html',
controller: 'editController'
})
Now, the same controller will be instantiated many times (parent all the children) but the $scope.Model
will be initiated only once (inside of parent) and available everywhere
Check this similar working example here