2014-11-06 16 views
15

Ich habe eine Eltern-Direktive, wo ich Child-Direktiven in der Link-Funktion dynamisch hinzufügen möchte. Die Child-Direktiven^benötigen die ParentDirective. Ich kann jedes HTML-Element hinzufügen, aber sobald ich versuche, meine Child-Direktive zu kompilieren, bekomme ich den folgenden Fehler, dass es den benötigten Controller nicht finden kann. Wenn ich die Child-Direktiven manuell hinzufüge, funktioniert es perfekt.Append-Kind-Direktive innerhalb der Eltern-Direktive

Fehler:

Error: [$compile:ctreq] Controller 'myInput', required by directive 'myKey', can't be found! 

Meine Vorlage sollte so aussehen, nachdem die Elemente hinzufügen:

<myInput> 
<myKey></myKey> <-- added dynamically 
<myKey></myKey> <-- added dynamically 
<myKey></myKey> <-- added dynamically 
    .... 
</myInput> 

myInput Richtlinie:

angular.module('myModule').directive('myInput', ['$log', '$templateCache', '$compile', function($log, $templateCache, $compile) { 
    return { 
    restrict: 'E', 
    transclude: true, 
    scope: { 
     service: '=',   // expects a stimulus object provided by the tatoolStimulusService 
     onkeydown: '&'   // method called on key press 
    }, 
    controller: ['$scope', function($scope) { 
     this.addKey = function(keyCode, value) { 
     $scope.service.addInputKey(keyCode, { givenResponse: value }); 
     }; 
    }], 
    link: function (scope, element, attr) { 

     // add keys directives 
     angular.forEach(scope.service.registeredKeyInputs, function(value, key) { 
     var keyEl = angular.element(
      $compile('<myKey code="'+ key +'" response="'+ value.response +'"></myKey >')($rootScope)); 
     element.children(":first").append(keyEl); 
     }); 

    }, 
    template: '<div ng-transclude></div>' 
    }; 
}]); 

myKey Richtlinie:

angular.module('myModule').directive('myKey', ['$log', '$sce', function($log, $sce) { 
    return { 
    restrict: 'E', 
    scope: {}, 
    require: '^myInput', 
    link: function (scope, element, attr, myCtrl) { 
     myCtrl.addKey(attr.code, attr.response); 

     // ... 
    }, 
    template: '<div class="key"><span ng-bind-html="key"></span></div>' 
    }; 
}]); 

Antwort

22

Ändern der Reihenfolge der Kompilierung hängen Operationen-Kompilierung anhängen:

var keyEl = angular.element('<myKey code="'+ key +'" response="'+ value.response +'"></myKey>'); 
element.append(keyEl); 
$compile(keyEl)(scope); 

Offenbar ist es wichtig, in diesem Fall (Elternelement Richtlinie Ortung), das neue Element war in DOM bereits zusammengestellt werden.

Wenn das DOM-Element nicht an DOM angehängt ist, hat es kein übergeordnetes Element (seine parentNode-Eigenschaft ist null). Wenn Angular nach ^myInput sucht, durchläuft es den DOM-Baum, bis ein Knoten mit der erforderlichen Direktive gefunden wird. Wenn das Element noch nicht im DOM vorhanden ist, schlägt diese Suche sofort fehl, da Element keine einzige parentNode hat. Daher der Fehler, den Sie bekommen.

Auch ich empfehle Namen Ihrer Richtlinien von Camelcase zu schlangen Fall zu ändern:

<my-input> 
    <my-key></my-key> 
</my-input> 

Dann kompilieren Teil wird sich auch ändern:

angular.element('<my-key code="'+ key +'" response="'+ value.response +'"></my-key >'); 
+0

Das funktioniert perfekt und macht auch Sinn machen (obwohl Dokumentation dazu würde helfen). Ich habe nur Dummy-Namen in der Post verwendet, aber Sie haben natürlich Recht mit dem Schlangenfall. Danke noch einmal. – jimmy

+1

Ich weiß nichts über Dokumentation, aber es ist einfach zu verstehen. Bis das DOM-Element an die DOM-Baumstruktur angehängt ist, hat ** ** kein Elternelement (seine Eigenschaft "parentNode" ist "null"). Wenn Angular nach "^ myInput" sucht, durchläuft es den DOM-Baum, bis es einen Knoten mit der erforderlichen Direktive findet. In unserem Fall schlägt es sofort fehl, weil Element keinen einzigen parentNode hat. – dfsq

Verwandte Themen