У меня есть что-то вроде этого:
.controller('contr',['$scope', '$http',function($scope, $http){
$http.post(...).success(function(){
$scope.myTextVar = "some text here";
$scope.completed == true;
});
}]);
HTML-фрагмент:
<div class="myClass" ng-if="completed == true" manipulate-header>
<p>{{myTextVar}}</p>
</div>
и директива, для простоты, скажем, это выглядит так:
.directive('manipulateHeader',function(){
return{
restrict: 'A',
link: function(scope, elem){
console.log(angular.element(elem).find('p'));
}
}
});
Предполагается, что директива manipulate-header
управляет текстом внутри <p></p>
, однако он запускается до {{myTextVar}}
и, следовательно, выводит {{myTextVar}}
вместо some text here
.
Как я могу обойти эту проблему? (я могу передать переменную внутри области действия директивы, но я думаю, что должен быть другой способ).
EDIT: контроллер работает и работает по назначению. Проблема не связана с этим. Я не включил его, чтобы сократить пост.
Если это ДОЛЖНО быть директивой
Если вы пытаетесь сделать строковые манипуляции в своей функции ссылок, у вас будет плохое время. Функция ссылки выполняется до того, как будет скомпилирована директива (что идея функции ссылки), поэтому любые привязки (ng-bind или иначе) не будут скомпилированы внутри функций ссылок.
Чтобы выполнить код после этапа компиляции, вы должны использовать контроллер. Однако вы не можете получить доступ к DOM в контроллерах (или, скорее, не должны). Поэтому логическое решение заключается в том, чтобы вместо этого изменить аргумент области. Я предлагаю что-то вроде этого:
angular.directive('manipulateHeader', function() {
return {
scope: {
myTextVar: '='
},
controller: function($scope, myFilter) {
// you can't use bindToController here because bindToController executes *after*
// this function
this.modifiedText = myFilter($scope.myTextVar);
},
controllerAs: 'ctrl',
// display the modified text in a template
template: '<span ng-bind="ctrl.modifiedText"></span>'
};
})
.filter('myFilter', function() {
return function(inputText) {
// do some text manipulation here
};
});
Применение:
<manipulate-header myTextVar='myTextVar'></manipulate-header>
Или:
<p>{{ myTextVar | myFilter }}</p>
Вы могли бы, конечно, сделать это атрибутом, но лучшая практика указывает, что директивы, имеющие шаблон, должны быть вместо этого.
Вышеизложенное, только если вам нужно, чтобы это было директивой. В противном случае это должен быть определенно фильтр.
Если вам нужно изменить переменную $ scope из вашего контроллера, вам необходимо выделить область действия,
scope:{
myattr='@', // this will provide one way communication , you can define in your template as <p myattr="hello"><p>
message:'&', //This allows you to invoke or evaluate an expression on the parent scope of whatever the directive is inside
message:'=' // sets up a two-way binding expression between the directive isolate scope and the parent scope.
}
Я не уверен, что вы определили $ scope.myTextVar в правильной области. Например, если вы определили его в любом контроллере, директива должна находиться под областью контроллера.
Вот обновленный HTML
<div ng-controller ="MainController">
<div class="myClass" manipulate-header>
<p>{{myTextVar}}</p>
</div>
</div>
JS:
app.controller('MainController', ['$ scope', function ($ scope) {
$ scope.myTextVar = "некоторый текст здесь"; }]);
app.directive('manipulateHerader',function(){
return{
restrict: 'A',
link: function(scope, elem){
console.log(angular.element(elem).find('p'));
}
}
});
Вот плункер
$http
, следовательно, она назначается области действия после выполнения директивы. Это корень проблемы, я верю.
Как было предложено @DanPantry - вы, скорее всего, хотите, чтобы фильтр не был директивой
Прочтите это руководство об использовании фильтров https://docs.angularjs.org/guide/filter
Вот пример такого фильтра (из документации)
angular.module('myStatefulFilterApp', [])
.filter('decorate', ['decoration', function(decoration) {
function decorateFilter(input) {
//This is the actual modification of text
//That what you are looking for
return decoration.symbol + input + decoration.symbol;
}
decorateFilter.$stateful = true;
return decorateFilter;
}])
.controller('MyController', ['$scope', 'decoration', function($scope, decoration) {
$scope.greeting = 'hello';
$scope.decoration = decoration;
}])
.value('decoration', {symbol: '*'});
$http
и получаю содержимое переменной из БД. Это, в свою очередь, означает, что $ scope.myTextVar назначается наиболее вероятно после выполнения директивы. Любопытно, что я попытался отложить выполнение директивы с помощьюng-if
после того, как http вернул результаты.This in turn means the $scope.myTextVar is assigned most likely after the directive was executed
Это говорит о том, что вам действительно нужен фильтр, а не директива. Директивы предназначены только для взаимодействия с DOM (добавление / удаление элементов или свойств этих элементов). Для любой формы логики, такой как манипулирование переменными (даже в $ scope), вам нужны контроллеры / фильтры / сервисы. Контроллеры предоставляют фильтры / сервисы с моделями, фильтры и сервисы - те, которые фактически делают их, и затем контроллер назначает их области.