2014-11-06 29 views
15

Ho una direttiva padre in cui voglio aggiungere dinamicamente direttive figlio nella funzione di collegamento. Le direttive secondarie^richiedono la parentDirective. Sono in grado di aggiungere qualsiasi elemento html ma non appena provo a compilare $ mia direttiva figlia ho il seguente errore che non riesce a trovare il controller richiesto. Se aggiungo manualmente le direttive figlio, funziona perfettamente.Aggiungi direttiva figlio all'interno della direttiva genitore

Errore:

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

mio modello dovrebbe essere simile dopo l'aggiunta degli elementi:

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

direttiva myInput:

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

direttiva myKey:

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

risposta

22

Modificare l'ordine di compilazione-accodare operazioni per aggiungere-compile:

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

A quanto pare è importante in questo caso (localizzazione genitore direttiva elemento), che il nuovo elemento in fase di compilazione è stato già nel DOM.

A meno che l'elemento DOM non sia aggiunto al DOM, non ha un genitore (la sua proprietà parentNode è null). Quando Angular cerca ^myInput attraversa l'albero DOM finché non trova un nodo con la direttiva richiesta. Se l'elemento non è ancora nel DOM, questa ricerca fallisce immediatamente, poiché l'elemento non ha un singolo parentNode. Da qui l'errore che stai ricevendo.

Inoltre vi consiglio di cambiare i nomi delle vostre direttive da camelCase al serpente-caso:

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

Poi parte la compilazione saranno anche cambiare:

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

che funziona perfettamente e ha nemmeno senso (anche se la documentazione su questo sarebbe di aiuto). Stavo usando solo nomi fittizi nel post, ma ovviamente hai ragione con il caso del serpente. Grazie ancora. – jimmy

+1

Non conosco la documentazione, ma è facile da capire. Finché l'elemento DOM non viene aggiunto alla struttura DOM, ** non ha ** un padre (la sua proprietà 'parentNode' è' null'). Quando Angular cerca '^ myInput' attraversa l'albero DOM fino a trovare un nodo con la direttiva richiesta. Nel nostro caso fallisce immediatamente, perché l'elemento non ha un solo parentNode. – dfsq

Problemi correlati