Первое, что нужно отметить, это то, что директива имеет свой собственный объект isolate scope, атрибут title которого связан с названием области управления. Эта привязка данных в основном выполняется с помощью часов, и вы можете знать, что обнаружение изменений с использованием часов происходит не мгновенно, происходит внутри цикла дайджеста, что всегда происходит после внесения изменений, а стек вызовов вызывается (в следующей задаче микро/макрос Я точно не знаю, что, но не имеет значения здесь). Однако вызов функции происходит мгновенно. Так что же происходит следующее:
- Установить название директивы рамки
- изменения вызова, который вызывает Foo, название области видимости контроллера является старым один
- После вызова углового прогонов дайджеста цикла, замечает изменения в области действия директивы и распространяет его на область управления
Это вполне ожидаемое поведение. Самый простой способ в вашем случае не использовать собственное обнаружение изменений, но использовать один встроенный в угловой:
angular.module('zippyModule', [])
.controller("Ctrl3", function ($scope) {
$scope.title = 'Ori';
$scope.$watch("title", function(newValue, oldValue) {
if (newValue !== oldValue) {
alert(newValue);
}
});
})
.directive('zippy', function() {
return {
restrict: 'AE',
scope: {
title:'=zTitle'
},
template: '<button ng-click="setValue()">What would be the value of title??</button>',
link: function(scope) {
scope.setValue = function() {
scope.title = "Yaniv";
};
}
}
});
button {
font-size:24px;
margin:40px;
padding: 10px 40px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.js"></script>
<div ng-app="zippyModule">
<div ng-controller="Ctrl3">
<div zippy z-title="title"></div>
</div>
</div>
Во время написания этого фрагмента я понял, вы используете древнюю версию angularjs в скрипке (1.0.2). Мне пришлось сделать небольшую модификацию для работы с 1.5.x.
Если вы не хотите использовать часы, то лучшее, что вы можете сделать, это просто передать новый заголовок функции изменения.
angular.module('zippyModule', [])
.controller("Ctrl3", function ($scope) {
$scope.title = 'Ori';
$scope.foo = function(newTitle) {
alert(newTitle);
};
})
.directive('zippy', function() {
return {
restrict: 'AE',
scope: {
change: '&'
},
template: '<button ng-click="setValue()">What would be the value of title??</button>',
link: function(scope) {
scope.setValue = function() {
scope.change({title:"Yaniv"});
};
}
}
});
button {
font-size:24px;
margin:40px;
padding: 10px 40px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.js"></script>
<div ng-app="zippyModule">
<div ng-controller="Ctrl3">
<div zippy change="foo(title)"></div>
</div>
</div>
UPDATE
Оказалось, в комментариях, которые вы хотите сделать несколько более жесткой связи между контроллером и директивы. Такая вещь обычно считается плохим дизайном, но бывают случаи, когда это единственное правильное решение (чаще всего задействуются неглавные компоненты). Поэтому идея состоит в том, чтобы создать объект API, который можно напрямую манипулировать, и передать его в директиву.
angular.module('zippyModule', [])
.controller("Ctrl3", function ($scope) {
$scope.title = 'Ori';
$scope.fooApiImpl = {
title: "Ori",
change: function() {
alert($scope.fooApiImpl.title);
}
};
})
.directive('zippy', function() {
return {
restrict: 'AE',
scope: {
fooApi: '='
},
template: '<button ng-click="setValue()">What would be the value of title??</button>',
link: function(scope) {
scope.setValue = function() {
scope.fooApi.title = "Yaniv";
scope.fooApi.change();
};
}
}
});
button {
font-size:24px;
margin:40px;
padding: 10px 40px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.js"></script>
<div ng-app="zippyModule">
<div ng-controller="Ctrl3">
<div zippy foo-api="fooApiImpl"></div>
</div>
</div>
Благодарим Вас за ясный ответ. Я не хотел использовать $ watch, поэтому я придумал функцию изменения и добрался до этой проблемы. – Yaniv
@ Yaniv Если у вас есть 'change: '&'', новое значение может быть передано с помощью параметра scope.change (val) ',' title: '=' 'is redundant и наоборот. По сути, это то или другое. Есть ли причина вашего решения? Потому что '$ scope. $ Watch' является идиоматическим, * более чистым решением *. – estus