директива angularjs о выходе связывания

0

У меня есть что-то вроде этого:

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

Теги:
angularjs-directive

4 ответа

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
    This in turn means the $scope.myTextVar is assigned most likely after the directive was executed Это говорит о том, что вам действительно нужен фильтр, а не директива. Директивы предназначены только для взаимодействия с DOM (добавление / удаление элементов или свойств этих элементов). Для любой формы логики, такой как манипулирование переменными (даже в $ scope), вам нужны контроллеры / фильтры / сервисы. Контроллеры предоставляют фильтры / сервисы с моделями, фильтры и сервисы - те, которые фактически делают их, и затем контроллер назначает их области.
Показать ещё 3 комментария
2

Если вам нужно изменить переменную $ 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. 
    }     

см. 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', function ($ scope) {

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

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

Вот плункер

  • 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 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
    Обратите внимание, что вы также можете использовать фильтры через код. Смотрите мой пример того, как вы можете сохранить эту директиву и фильтр одновременно.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню