it-swarm.com.de

Wie ersetze ich ein Element in der AngularJS-Direktiven-Verknüpfungsfunktion?

Ich erstelle eine AngularJS-Direktive <row>, Die sich selbst ersetzen muss (das Tag <row> Darf nach der Ausführung nicht im DOM vorhanden sein) durch eine dynamische Vorlage, die beliebigen HTML-Code enthalten kann.

Das Problem bei der Verwendung von replace: true Ist, dass es nicht mit den <tr> - Tags der Tabelle funktioniert und dass die Vorlage dynamisch ausgewählt wird.

Ich versuche also, einen Weg zu finden, um das Element in der Verknüpfungsfunktion zu ersetzen, ohne Erfolg.

Wenn Sie die Funktion .replaceWith() von jQuery verwenden, wird ngRepeat aus einem unbekannten Grund unterbrochen.

Irgendwelche Hinweise?

Hier ist die Geige

40
Antonio Madonna

Ihre Geige scheint ziemlich einfach, aber Sie sollten in der Lage sein, nur outerHTML zu verwenden

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

Geige aktualisiert

Wenn Sie mit ng-repeat Arbeiten müssen, können Sie Ihre Elemente an eine Bereichseigenschaft binden und sie in Ihrer kompilierten Vorlage referenzieren. Sobald es kompiliert ist, können Sie jQuery replaceWith() verwenden.

html

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

richtlinie

.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);
        }
    };
});

Beispiel ng-repeat

52
Mark Coleman

Marks Antwort wird funktionieren, aber dieses Beispiel ist zu begrenzt, um das ganze Bild zu zeigen. Während Marks Direktive in der Tat für gemeinsame und einfache UI-Komponenten ausreicht, sollte dieses Muster für komplexere Operationen vermieden werden. Im Folgenden erkläre ich ausführlich den Grund dafür. Tatsächlich bietet Angular bereits eine weitaus einfachere Möglichkeit, das Direktivenelement durch eine Vorlage zu ersetzen am Ende dieser Antwort.

So sieht eine Direktive hinter den Kulissen aus:

.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's 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's 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);
          };
      }
  };
});

Was können wir daraus machen? Es ist dann offensichtlich, dass der manuelle Aufruf von $compile für dasselbe DOM-Layout zweimal ist redundant, schlecht für die Leistung und Auch schlecht für deine Zähne. Was solltest du stattdessen tun? Kompilieren Sie einfach Ihr DOM, wo es kompiliert werden soll :

.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.
          };
      }
  };
});

Wenn Sie weiter unter der Haube von Richtlinien eintauchen möchten, bezeichne ich dies als inoffizielle AngularJS-Direktivenreferenz

Sobald Sie hier fertig sind: https: //github.com/angular/angular.js/wiki/Understanding-Directives


Nun, wie versprochen, ist hier die Lösung, für die Sie hierher gekommen sind:

Mit 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: "="
        }
    };
});
99
pilau