213 votes

Ajouter dynamiquement des directives sur angularjs

J'ai un très cuit version de ce que je fais qui obtient le problème à l'échelle.

J'ai une simple directive. Chaque fois que vous cliquez sur un élément qu'il ajoute un autre. Cependant, il doit être compilé en premier afin de le rendre correctement.

Ma recherche m'a conduit à $compiler. Mais tous les exemples utilisent une structure compliquée que je ne sais pas vraiment comment l'appliquer ici.

Violon violons ici: http://jsfiddle.net/paulocoelho/fBjbP/1/

Et le JS est ici:

var module = angular.module('testApp', [])
    .directive('test', function () {
    return {
        restrict: 'E',
        template: '<p>{{text}}</p>',
        scope: {
            text: '@text'
        },
        link:function(scope,element){
            $( element ).click(function(){
                // does not compile :(
                $(this).parent().append("<test text='n'></test>");
            });
        }
    };
});

Solution par Josh David Miller:

http://jsfiddle.net/paulocoelho/fBjbP/2/

261voto

Josh David Miller Points 66508

Vous avez beaucoup de jQuery inutile, mais le service $ compile est en fait très simple :

 .directive( 'test', function ( $compile ) {
  return {
    restrict: 'E',
    scope: { text: '@' },
    template: '<p ng-click="add()">{{text}}</p>',
    controller: function ( $scope, $element ) {
      $scope.add = function () {
        var el = $compile( "<test text='n'></test>" )( $scope );
        $element.parent().append( el );
      };
    }
  };
});
 

Vous remarquerez que j'ai également modifié votre directive pour suivre certaines des meilleures pratiques. Faites-moi savoir si vous avez des questions sur l'un de ceux-ci.

77voto

deadrunk Points 3902

En plus de l'exemple parfait de Riceball LEE d'ajouter une nouvelle directive d'élément

 newElement = $compile("<div my-diretive='n'></div>")($scope)
$element.parent().append(newElement)
 

L'ajout d'un nouvel attribut-directive à un élément existant pourrait se faire de cette manière:

Disons que vous souhaitez ajouter à la volée my-directive à l'élément span .

 template: '<div>Hello <span>World</span></div>'

link: ($scope, $element, $attrs) ->

  span = $element.find('span').clone()
  span.attr('my-directive', 'my-directive')
  span = $compile(span)($scope)
  $element.find('span').replaceWith span
 

J'espère que cela pourra aider.

45voto

Riceball LEE Points 684

L'ajout dynamique de directives sur angularjs a deux styles:

Ajouter un angularjs directive dans une autre directive

  • l'insertion d'un nouvel élément(directive)
  • l'insertion d'un nouvel attribut(directive) à l'élément

l'insertion d'un nouvel élément(directive)

c'est simple. Et u peut utiliser en "lien" ou "compiler".

var newElement = $compile( "<div my-diretive='n'></div>" )( $scope );
$element.parent().append( newElement );

l'insertion d'un nouvel attribut à l'élément

C'est dur, et de me faire mal de tête en moins de deux jours.

À l'aide de "$compiler" permettra de soulever des critiques récursive d'erreur!! Peut-être qu'il devrait ignorer la directive en vigueur lors de la re-compilation de l'élément.

$element.$set("myDirective", "expression");
var newElement = $compile( $element )( $scope ); // critical recursive error.
var newElement = angular.copy(element);          // the same error too.
$element.replaceWith( newElement );

Donc, je dois trouver un moyen d'appeler la directive "lien" de la fonction. Il est très difficile d'obtenir les méthodes utiles qui sont cachés profondément à l'intérieur de fermetures.

compile: (tElement, tAttrs, transclude) ->
   links = []
   myDirectiveLink = $injector.get('myDirective'+'Directive')[0] #this is the way
   links.push myDirectiveLink
   myAnotherDirectiveLink = ($scope, $element, attrs) ->
       #....
   links.push myAnotherDirectiveLink
   return (scope, elm, attrs, ctrl) ->
       for link in links
           link(scope, elm, attrs, ctrl)       

Maintenant, C'est de bien travailler.

9voto

user1212212 Points 41
function addAttr(scope, el, attrName, attrValue) {
  el.replaceWith($compile(el.clone().attr(attrName, attrValue))(scope));
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X