2015-06-25 2 views
0

у меня есть что-то вроде этого:angularjs директива о выходе связывания

.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: контроллер работает и работает по назначению. Проблема не связана с этим. Я не включил его, чтобы сократить пост.

+0

Какая манипуляция мы говорим здесь? Если вы дадите нам общую идею, мы сможем определить, есть ли более простой способ исправить вашу проблему (что, похоже, есть) –

+0

Неприемлемо. Даже простой вывод должен выводить замененный текст, а не шаблонный заполнитель. Идея заключается в том, что директива должна запускаться после того, как была проведена привязка текста. –

+0

Это не имеет значения. Очень вероятно, что то, что вы пытаетесь сделать, не означает, что это нужно делать с директивами, а вместо этого с каким-то фильтром. Предварительные, ссылки и пост-ссылки функции директивы выполняются до составления директивы - это их контракт. Единственный способ изменить текст - либо заменить текст внутри элемента, либо изменить переменную области видимости после компиляции. Если вы хотите выполнить некоторую обработку после компиляции, используйте контроллер. –

ответ

3

Если это должно быть директива

Если вы пытаетесь сделать манипуляции со строками в функции связи, вы будете иметь плохое время. Функция ссылки выполняется до того, как будет скомпилирована директива (это идея функции ссылки), поэтому любые привязки (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> 

Можно, конечно, сделать это атрибут вместо этого, но лучше практика показывает, что директивы, вместо этого шаблон должен быть элементом.

Вышеуказано, только если вы необходимо это директива. В противном случае это должен быть определенно фильтр.

+0

Право, теперь я понимаю, что мой пост был неполным. Это поток. В моем контроллере я делаю запрос '$ http' и захватываю содержимое переменной из БД. Это, в свою очередь, означает, что $ scope.myTextVar назначается, скорее всего, после выполнения директивы. Любопытно, что я попытался отложить выполнение директивы с помощью 'ng-if' после результатов возврата http. –

+0

'Это, в свою очередь, означает, что $ scope.myTextVar назначается, скорее всего, после того, как была выполнена директива' Это говорит мне о том, что вам действительно нужен фильтр, а не директива. Директивы существуют только для взаимодействия с DOM (добавление/удаление элементов или свойств этих элементов). Для любой формы логики, такой как манипуляция с переменными (даже в области $ scope), вам нужны контроллеры/фильтры/службы. Контроллеры предоставляют фильтры/услуги с помощью моделей, фильтров и сервисов, которые фактически выполняют их, а затем контроллер назначает их области. –

+0

Даже учитывая ваш поток, да, вам нужен фильтр (а не директива). Даже если это будет работать так, как вы планировали, я все равно считаю, что фильтр здесь более уместен. Могу ли я спросить, почему изменение строки в 'success' не является вариантом? –

2

Если вам нужно изменить переменную $ области действия от вашего контроллера, необходимо изолировать объем,

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's isolate scope and the parent scope. 
    }  

см https://docs.angularjs.org/guide/directive

+0

Это была опечатка. Фактический код верен. Пункт по-прежнему указывает, что привязка не выполняется перед внешней директивой. –

1

Я не уверен, определено ли вы $ scope.myTextVar в правильный объем. Например, если вы определили его в любом контроллере, директива должна находиться под областью контроллера.

Вот обновленный HTML

<div ng-controller ="MainController"> 
    <div class="myClass" manipulate-header> 
     <p>{{myTextVar}}</p> 
    </div> 
    </div> 

JS:

app.controller ('MainController', [ '$ сфера', функция ($ Scope) {

$ scope.myTextVar = "некоторый текст здесь"; }]);

app.directive('manipulateHerader',function(){ 
    return{ 
     restrict: 'A', 
     link: function(scope, elem){ 
       console.log(angular.element(elem).find('p')); 
       } 
    } 
}); 

Вот plunker

+0

Правильно, это было связано с контроллером в некотором роде. Эта переменная, я получаю из БД через запрос '$ http', поэтому он присваивается области после запуска директивы. Это корень проблемы, на которую я верю. –

1

По предложению @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's 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: '*'}); 
+0

Не хорошо разбирается в фильтрах. Попробуй понять код и вернуться, чтобы посмотреть, смогу ли я его отрегулировать. Спасибо. –

+0

Обратите внимание: вы также можете использовать фильтры по коду. См. Мой пример того, как вы можете одновременно сохранить эту директиву и фильтр. –