it-swarm.com.ru

Angular Директива не оценивается внутри ng-repeat

У меня есть следующие настройки:

Приложение/Директива

var app = angular.module("MyApp", []);

app.directive("adminRosterItem", function () {
    return {
        restrict: "E",
        scope: {
            displayText: "@"
        },
        template: "<td>{{ displayText }}</td>", // should I have this?
        link: function(scope, element, attrs){
            // What do I put here? I don't seem to have any
            // element to initialize (set up event handlers, for example)
        },
        compile: function(?,?,?){} // should I have this? If so, what goes inside?
    }
});

Контроллер

function PositionsController($scope) {
           $scope.positions = [{ Name: "Quarterback", Code: "QB" },
                               { Name: "Wide Receiver", Code: "WR" }
                              ]; 
}

HTML:

<div ng-app="MyApp">
    <div ng-controller="PositionsController">            
        <table>
            <tr ng-repeat="position in positions">
                <admin-roster-item displayText="{{ position.Name + ' (' + position.Code + ')' }}"></admin-roster-item>
             </tr>
         </table>       
    </div>
</div>

Это очень простой пример, но я не могу его отобразить. Возможно, есть что-то, о чем учебники не говорят мне, или это секретное Angular знание?

Если я удаляю директиву внутри <tr ng-repeat="..." /> и помещаю вместо нее <td>{{ displayText }}</td>, она покажет все записи.

Но я хочу, чтобы директива была более сложной, чем просто один <td>{{}}</td> (в конце концов), чтобы я мог повторно использовать эту директиву в нескольких приложениях.

Итак, я действительно спрашиваю, как нам правильно создать директиву, которая идет внутри ng-repeat? Что мне не хватает? Что нужно снять с кода выше?

10
Mickael Caruso

Согласитесь, что вам нужно подумать о том, где директива начинается и заканчивается. Вот plnkr, который иллюстрирует директиву, привязанную к каждому элементу в массиве - http://plnkr.co/edit/IU8fANreYP7NYrs4swTW?p=preview

Если вы хотите, чтобы директива инкапсулировала перечисление коллекции, определенной родительской областью, она получает немного хитрости. Я не уверен, является ли следующее «наилучшей практикой», но именно так я с этим справился - http://plnkr.co/edit/IU8fANreYP7NYrs4swTW?p=preview

Полагаясь на директиву для выполнения итерации, вы включаетесь в transclusion, которое представляет собой составленное Word, которое означает (насколько я понимаю) взять содержимое, определенное в родительском элементе, вставьте его в директиву и затем оцените его. Я работал с angular в течение нескольких месяцев, и я начинаю думать, что просьба повторить директиву - это запах, и мне всегда удавалось придумать что-то подобное.

8
Jason

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

  1. не используйте смешанный регистр в именах ваших атрибутов. displaytext нет displayText
  2. поместите теги <td> вне директивы, в шаблон

Сделайте это, и это сработает; он думает, что это Angular ошибки.

9
Malvolio

я думаю, что правильный способ подойти к этому - отправить объект в список администратора, например:

<tr ng-repeat="position in positions">
  <admin-roster-item pos="position">         
  </admin-roster-item>
</tr>

и в директиве:

var app = angular.module("MyApp", []);

app.directive("adminRosterItem", function () {
  return {
    restrict: "E",
    scope: {
        pos: "@"
    },
    template: "<td>{{ formattedText }}</td>", // should I have this?
    link: function(scope, element, attrs){
        // all of this can easily be done with a filter, but i understand you just want to     
        // know how it works
        scope.formattedText = scope.pos.Name + ' (' + scope.pos.Code + ')';
    }
  }
});

PS. я не проверял это!

2
user1695032

Вместо того, чтобы писать свою директиву как потомок ng-repeat, попробуйте сохранить пользовательскую директиву на том же уровне, что и ng-repeat, это 

<tr ng-repeat="position in positions" admin-roster-item displayText="{{ position.Name + ' (' + position.Code + ')' }}"></tr>

И более того, разрешите использовать вашу пользовательскую директиву в качестве атрибута. AngulaJS определил приоритет ng-repeat как 1000, так что иногда, когда вы создаете свою пользовательскую директиву, она плохо работает с ng-repeat.

Второй вариант (попробуйте только в случае неудачи первого) - установить приоритет вашей пользовательской директивы больше, чем у ngRepeat, то есть 1001. 

1
Manish M Demblani

У меня была похожая проблема, когда ng-repeat на мой взгляд не оценивался, если представление содержало директиву ('mydirective')

Мое определение директивы было 

angular.module('myApp')
  .directive('myDirective', function () {
    return {
      templateUrl: 'components/directives/mydirective.html',
      restrict: 'EA',
      controller: 'MyDirectiveController',
      controllerAs: 'vm',
      link: function (scope, element, attrs) {
      }
    };
  });

и мое определение контроллера представления было

  angular.module('myApp')
    .component('myView', {
      templateUrl: 'app/views/myview.html',
      controller: myViewComponent,
      controllerAs: "vm"
    });

вы можете заметить, что оба контроллера ссылаются на 'vm', используя параметр 'controllerAs'. Это причина проблемы. Когда директива присутствует в виде, angular всегда ссылается на «vm», определенный в контроллере директивы, а не на вид.

Когда я даю разные имена для ссылок контроллера, проблема исчезла

Теперь мое определение директивы 

angular.module('myApp')
  .directive('myDirective', function () {
    return {
      templateUrl: 'components/directives/mydirective.html',
      restrict: 'EA',
      controller: 'MyDirectiveController',
      controllerAs: 'directiveVM',
      link: function (scope, element, attrs) {
      }
    };
  });

и мое определение контроллера представления было

  angular.module('myApp')
    .component('myView', {
      templateUrl: 'app/views/myview.html',
      controller: myViewComponent,
      controllerAs: "viewCtrlVM"
    });

Надеюсь, поможет.

0
Chandru

У меня точно такая же проблема ... У меня была пользовательская директива в директиве ng-repeat, table-> tr-> td->, и при сортировке таблицы с использованием ng-repeat и Array.sort таблица изменила порядок, но директивы не перерисовывать. Проблема была в том, что я использовал

track by $index

удалил трек по индексу из ng-repeat и это было исправлено.

0
Tomas Katz