I'm using ui-router in a AngularJS project where I have a nested view that contains a custom directive. This directive renders an input field (lets say a filter-field) and its value should be in sync with the controller's scope.
This works well for this directive, when the view/state not is nested:
jsFiddle / not nested / working as expected
var myApp = angular.module('myApp', ['ui.router', 'myComponents'])
.config(['$stateProvider', function ($stateProvider) {
$stateProvider.
state('home', {
url: '',
template: '<my-filter text-filter="theFilter"></my-filter><button ng-click="inspect()">inspect</button>{{ theFilter |json}}',
controller: 'myController'
});
}]);
var components = angular.module('myComponents', []);
components.directive('myFilter', [function () {
return {
restrict: 'E',
template: '<input type="text" name="filter" ng-model="textFilter">',
scope: {
textFilter: '='
}
};
}]);
components.controller('myController', ['$scope', function ($scope) {
$scope.theFilter = 'initial filter';
$scope.inspect = function () {
alert($scope.theFilter);
}
}]);
View:
<div ng-app="myApp">
<div ui-View></div>
</div>
When I change the input field's text, it gets reflected on the scope...
...but when I nest the view/state, the value on the scope keeps it's initial value but I expect it to get changed according to the input field's value when overwriting.
var myApp = angular.module('myApp', ['ui.router', 'myComponents'])
.config(['$stateProvider', function ($stateProvider) {
$stateProvider.
state('home', {
abstract: true,
url: '',
template: 'Nested View:<div ui-view></div>',
controller: 'myController'
}).
state('home.detail', {
url: '',
template: '<my-filter text-filter="theFilter"></my-filter><button ng-click="inspect()">inspect</button>{{ theFilter |json}}'
});;
}]);
var components = angular.module('myComponents', []);
components.directive('myFilter', [function () {
return {
restrict: 'E',
template: '<input type="text" name="filter" ng-model="textFilter">',
scope: {
textFilter: '='
}
};
}]);
components.controller('myController', ['$scope', function ($scope) {
$scope.theFilter = 'initial filter';
$scope.inspect = function () {
alert($scope.theFilter);
}
}]);
View:
<div ng-app="myApp" >
<div ui-View></div>
</div>
Here, the text on the scope (see controller) remains the same.
Any idea how I can get the same result with nested views as in the first example?
PS: The directive needs to remain reusable
This is related to a common issue. As mentioned in this video angular JS - best practice (29:19), and explained here: Nested Scopes in Angular JS
So the controller should be creating an object:
and the template should work with an object having property
value
:The upated jsfiddle