Подтвердить что ты не робот

Как заменить элемент в функции привязки директив AngularJS?

Я создаю директиву <row> AngularJS, которая должна заменить себя (тег <row> не должен присутствовать в DOM после выполнения) с динамическим шаблоном, который может содержать любой HTML-код.

Проблема при использовании replace: true заключается в том, что он не работает с тегами table <tr> и что шаблон динамически выбран.

Итак, я пытаюсь найти способ заменить элемент в функции связывания без успеха.

Использование jQuery .replaceWith() по неизвестной причине прерывает ngRepeat.

Любые подсказки?

Вот fiddle

4b9b3361

Ответ 1

Ваша скрипка кажется довольно простой, но вы должны просто использовать outerHTML

element[0].outerHTML ='<div>I should not be red</div>';

Обновлена ​​скрипка

Если вам нужно иметь дело с ng-repeat, вы можете привязать свои объекты к свойству scope и ссылаться на них в своем шаблоне, который вы компилируете. После его компиляции вы можете использовать jQuery replaceWith()

HTML

<row items="items">***</row>

директива

.directive('row', function ($compile) {
    return {
        restrict: 'E',
        scope: {
            items: "="
        },
        link: function (scope, element, attrs) {
            var html ='<div ng-repeat="item in items">I should not be red</div>';
            var e =$compile(html)(scope);
            element.replaceWith(e);
        }
    };
});

ng-repeat пример

Ответ 2

Отметьте ответ, но этот пример слишком ограничен, чтобы показать всю картину. В то время как директива Mark действительно может быть достаточной для простых и простых компонентов пользовательского интерфейса, для более сложных операций этот шаблон следует избегать. Ниже я объясняю подробно причину этого. Фактически Angular уже предоставляет гораздо более простой способ заменить элемент директивы шаблоном. Это можно найти в нижней части этого ответа.

Вот как выглядит директива за кулисами:

.directive('row', function ($compile) {
  return {
      restrict: 'E',
      scope: {
          items: "="
      },

      // Whether you define it this way or not, this is the order of
      // operation (execution) behind every AngularJS directive.
      // When you use the more simple syntax, Angular actually generates this
      // structure for you (this is done by the $compile service):

      compile: function CompilingFunction($templateElement, $templateAttributes, transcludeFn) {

        // The compile function hooks you up into the DOM before any scope is
        // applied onto the template. It allows you to read attributes from
        // the directive expression (i.e. tag name, attribute, class name or
        // comment) and manipulate the DOM (and only the DOM) as you wish.

        // When you let Angular generate this portion for you, it basically
        // appends your template into the DOM, and then some ("some" includes
        // the transclude operation, but that out of the $scope of my answer ;) )

          return function LinkingFunction($scope, $element, $attrs) {

            // The link function is usually what we become familiar with when
            // starting to learn how to use directives. It gets fired after
            // the template has been compiled, providing you a space to
            // manipulate the directive scope as well as DOM elements.

            var html ='<div ng-repeat="item in items">I should not be red</div>';
            var e = $compile(html)($scope);
            $element.replaceWith(e);
          };
      }
  };
});

Что мы можем сделать из этого? Очевидно, что вручную вызов $compile для одного и того же макета DOM дважды избыточен, плохо для производительности и для ваших зубов. Что вы должны делать вместо этого? Просто скомпилируйте свой DOM, где он должен быть скомпилирован:

.directive('row', function ($compile) {
  return {
      restrict: 'E',
      template: '<div ng-repeat="item in items">I should not be red</div>',
      scope: {
          items: "="
      },

      compile: function CompilingFunction($templateElement, $templateAttributes) {
          $templateElement.replaceWith(this.template);

          return function LinkingFunction($scope, $element, $attrs) {
            // play with the $scope here, if you need too.
          };
      }
  };
});

Если вы хотите еще больше погрузиться под капот директив, вот что мне нравится называть неофициальной ссылкой на Directular для AngularJS

Как только вы закончите с этой головой: https://github.com/angular/angular.js/wiki/Understanding-Directives


Теперь, как и было обещано, вот решение, для которого вы пришли сюда:

Использование replace: true:

.directive('row', function ($compile) {
    return {
        restrict: 'E',
        template: '<div ng-repeat="item in items">I should not be red</div>',
        replace: true,
        scope: {
            items: "="
        }
    };
});