Was genau machen Sie mit der Transclude-Funktion und der Klonverknüpfungsfunktion?

70

Aus der Direktive Angular docs geht hervor , dass die Kompilierungsfunktion drei Parameter hat, von denen einer ist transclude. Die einzige Erklärung, die die Dokumente liefern, ist:

transclude - Eine Transclude-Verknüpfungsfunktion: function (scope, cloneLinkingFn).

Ich versuche zu verstehen, was genau Sie in der Klonverknüpfungsfunktion tun würden. Ich weiß nicht einmal, welche Parameter übergeben werden. Ich habe ein Beispiel gefunden , dessen Parameter cloneein HTML-Element zu sein scheint. Gibt es andere Parameter? Welches HTML-Element ist das genau? Ich schaue auch wahrscheinlich transclude: 'element'in meiner Direktive zu verwenden. Ändern sich die Antworten auf diese Fragen bei der Verwendung 'element'anstelle von true?

Ich verstehe die Transklusion mit den einfachen Beispielen, aber ich kann anscheinend keine komplexeren Beispiele finden, insbesondere mit transclude: 'element'. Ich hoffe, jemand kann eine gründlichere Erklärung zu all dem geben. Vielen Dank.

dnc253
quelle

Antworten:

55

BEARBEITEN: Ich habe meine Antwort vollständig und vollständig geändert und dies als "Community-Wiki" markiert (was für mich keine Punkte bedeutet), da ich mich völlig geirrt habe, als ich darauf geantwortet habe

Wie @Jonah unten ausgeführt hat, ist hier ein wirklich guter Artikel über die Kompilierungsoption von Direktiven und die Verwendung der Transclusionsfunktion

Die Grundidee ist, dass die Kompilierungsfunktion eine Verknüpfungsfunktion zurückgeben sollte. Mit der in der Verknüpfungsfunktion bereitgestellten Transclusionsfunktion können Sie einen Klon des transkludierten DOM-Elements erstellen, kompilieren und überall dort einfügen, wo es eingefügt werden muss.

Hier ist ein besseres Beispiel, das ich auf Plunker aus meinem Hintern gezogen habe

Die Idee der Kompilierungsfunktion besteht darin, dass Sie die DOM-Elemente basierend auf Attributen, die übergeben wurden, bevor die Verknüpfungsfunktion erstellt und aufgerufen wird, programmgesteuert ändern können.

// a silly directive to repeat the items of a dictionary object.
app.directive('keyValueRepeat', function ($compile){
  return {
    transclude: true,
    scope: {
      data: '=',
      showDebug: '@'
    },
    compile: function(elem, attrs, transclude) {

      if(attrs.showDebug) {                
        elem.append('<div class="debug">DEBUG ENABLED {{showDebug}}</div>');
      }

      return function(scope, lElem, lAttrs) {
        var items = [];
        console.log(lElem);
        scope.$watch('data', function(data) {

          // remove old values from the tracking array
          // (see below)
          for(var i = items.length; i-- > 0;) {
            items[i].element.remove();
            items[i].scope.$destroy();
            items.splice(i,1);
          }

          //add new ones
          for(var key in data) {

            var val = data[key],
                childScope = scope.$new(),
                childElement = angular.element('<div></div>');

            // for each item in our repeater, we're going to create it's
            // own scope and set the key and value properties on it.
            childScope.key = key;
            childScope.value = val;

            // do the transclusion.
            transclude(childScope, function(clone, innerScope) {
              //clone is a copy of the transcluded DOM element content.
              console.log(clone);

              // Because we're still inside the compile function of the directive,
              // we can alter the contents of each output item
              // based on an attribute passed.
              if(attrs.showDebug) {                
                clone.prepend('<span class="debug">{{key}}: {{value}}</span>');
              }

              //append the transcluded element.
              childElement.append($compile(clone)(innerScope));
            });

            // add the objects made to a tracking array.
            // so we can remove them later when we need to update.
            items.push({
              element: childElement,
              scope: childScope
            });

            lElem.append(childElement);
          }
        });
      };
    }
  };
});
Ben Lesh
quelle
3
@blesh, ich bin mir ziemlich sicher, dass diese Antwort falsch ist. Wenn Sie die Konsole öffnen und Ihr plnk ausführen, wird der folgende Fehler angezeigt : TypeError: Cannot read property '1' of null. Dies liegt daran, dass Sie ein Element an das erste Argument von transcludeLinkingFn übergeben und es einen Bereich erwartet. In den Dokumenten ist transclude - A transclude linking function: function(scope, cloneLinkingFn). dies klar formuliert: Beispiele wie dieses sind kein vorgesehener Anwendungsfall. Dieser Artikel zeigt einen besseren.
Jonah
9
@ Jonah: Du bist zu 1000% korrekt. Meine Antwort war einfach falsch. Das ist eine Weile her und ich habe besser gelernt. Unabhängig davon habe ich die Antwort komplett geändert und auf Community-Wiki gesetzt (keine Punkte vergeben).
Ben Lesh
17
@blesh, ich bin sehr froh zu sehen, dass es einigen Mitgliedern von SO mehr darum geht, die Dinge richtig zu machen als um das Ego. Danke für das Update!
Jonah
10
Kein Schweiß. Ich bin beschämter zu glauben, dass jemand darauf gestoßen ist und gelernt hat, etwas falsch zu machen !
Ben Lesh
4
Nur für andere, die sich die eckigen Dokumente ansehen, sind einige interessante neue Dinge enthalten. Note: The transclude function that is passed to the compile function is deperecated, as it e.g. does not know about the right outer scope. Please use the transclude function that is passed to the link function instead. Dies liegt daran, dass der Gültigkeitsbereich vorgebunden ist.
DeMeNteD