2016-04-11 1 views
1

J'essaie de créer un nombre N de Sélectionnez dynamiquement les contrôles à partir de la directive basée sur le tableau transmis depuis l'attribut (où N est la longueur du tableau).AngularJS n'analyse pas les données dynamiquement chargées de la directive

Structure d'un objet du tableau est en tant que tel:

selectDescription = { 
    array: arrayObject, //ng-options, a string as 'item as item.name for item in selectArray[0]' 
    change: methodName, //ng-change, actionname 
    level: levelNumber //level number 
} 

Ainsi, le nombre de contrôles sélectionnez balise span intérieur dépend du nombre de selectDescription(s) que je reçois de l'attribut.

Le premier contrôle de sélection est rendu avec succès. Les contrôles de sélection suivants doivent avoir été rendus sur la sélection d'une option parmi précédentes commandes de sélection rendues. Mais ce n'est pas le cas dans mon cas. Bien que j'attribue avec succès des éléments angulaires dans le inputEl actuel (sur sélection d'une option), il n'est pas affiché dans l'interface utilisateur. Je suppose qu'il me manque quelque chose de très crucial.

Le changement de selectDescriptions, un attribut est défini basculée, à travers lequel je peux appeler scope.$editable.render() de lien, qui exécute à son tour rend la fonction de re-append éléments après avoir effacé le code HTML précédent à l'intérieur span.

Mon code:

app.directive('editableLocation', function(editableDirectiveFactory) { 
    var createElement = function(el, index){ 
     var newElement = angular.element("<select/>"); 
     newElement.attr('ng-model','$data'+index); 
     newElement.attr('ng-options',el.array); 
     newElement.attr('ng-change',el.change.substring(0, el.change.length - 1)+", $data"+index+")"); 
     return newElement; 
    } 

var descriptions = [] ; 
var dir = editableDirectiveFactory({ 
    directiveName: 'editableLocation', 
    inputTpl: '<span></span>', 
    render: function() { 
    this.parent.render.call(this); 
    this.inputEl.html(""); 
    for(var i = 0 ; i < descriptions.length ; i ++){ 
     this.inputEl.append(createElement(descriptions[i], i)); 
    } 
    } 
}); 
var linkOrg = dir.link; 

dir.link = function(scope, el, attrs, ctrl) { 
    console.log(el); 
    descriptions = scope.$eval(attrs.description); 
    scope.$watch('flipped',function(newValue,oldValue){ 
     if(newValue != 0){ 
      scope.$editable.render(); 
     } 
    }); 
    return linkOrg(scope, el, attrs, ctrl); 
}; 

return dir; 
}); 

Répondre

1

Puisque vous ajoutez le contenu HTML dynamique dans la fonction link de la directive angulaire, angulaire ne compilera pas auto/analyser. Vous devez le faire manuellement en utilisant la directive $compile. Donc, après avoir joint en annexe tous les fichiers HTML, procédez comme suit (injection $compile dans votre code)

$compile(element.contents())(scope); 

element est votre tout élément parent dans lequel vous générez HTML dynamique et scope est la portée de la directive ou de toute autre portée que vous voulez qu'il soit attaché au HTML dynamique.

+0

Je l'ai fait comme vous l'avez dit. Bien qu'il affiche deux contrôles select à l'intérieur de this.inputEl.contents(), il ne s'affiche toujours pas au même nombre de contrôles dans l'interface utilisateur. –

+0

Il peut s'agir d'un problème avec votre code. Pouvez-vous fournir un plunkr ou un violon? –

+0

Voilà, vous allez https://plnkr.co/edit/lX7aBnJz9b2D9p35Hke6?p=preview –

0

En regardant xeditable.js J'ai trouvé que xeditable rend l'interface utilisateur en appelant une méthode show définie dans son editableController.

Il est défini comme:

self.show = function() { 
    self.setLocalValue(); 
    self.render(); //calls 'render' function of 'editableDirectiveFactory'; that' where my custom UI lies 
    $element.after(self.editorEl); //attaches newelement(especially whole <form/> element) 
    $compile(self.editorEl)($scope); //renders whole UI(and also the newly attached one) 
    self.addListeners(); 
    $element.addClass('editable-hide'); 
    return self.onshow(); 
}; 

Alors ce que je ressentais est, je besoin d'appeler cette méthode show de ma fonction link, qui reçoit le controller.

Voici ce que je faisais:

dir.link = function (scope, el, attrs, ctrl) { 
    $element = el; 
    scope.$watch(attrs.flipped, function (newValue, oldValue) { 
     //re-render element if flipped is changed; denoting description of select controls have been altered 
     if (newValue != 0) { 
      ctrl[0].show(); //this will call render function and also $compile({{content/html/element}})(scope) 
     } 
    }); 
    return linkOrg(scope, el, attrs, ctrl); 
}; 

Et vous devez cacher l'élément <form/> précédent (qui contient l'interface utilisateur rendu précédent), de sorte que seule une forme s'affiche.

Voilà comment je cachais cet élément précédent dans <form/>render' function of editableDirectiveFactory`:

var prevForm = $element[0].nextElementSibling; //hide previous form element which would already contain previous select 
if (prevForm) 
    prevForm.classList.add('editable-hide'); 

qui a résolu mon problème au moins :)