Comment passer plusieurs attributs dans une directive d'attribut Angular.js?

116

J'ai une directive d'attribut restreinte comme suit:

 restrict: "A"

J'ai besoin de passer deux attributs; un nombre et une fonction / rappel, y accédant dans la directive en utilisant l' attrsobjet.

Si la directive était une directive d'élément, limitée avec "E"je pourrais à ceci:

<example-directive example-number="99" example-function="exampleCallback()">

Cependant, pour des raisons que je ne vais pas aborder, j'ai besoin que la directive soit une directive attributaire.

Comment passer plusieurs attributs dans une directive d'attribut?

Undistraction
la source
Cela dépend du type de champ d'application créé par votre directive (le cas échéant). Les choix sont: pas de nouvelle portée (par défaut, ou explicite avec scope: false), nouvelle portée (avec héritage prototypique normal, c'est-à-dire, scope: true) et isoler la portée (c'est-à-dire, scope: { ... }). Quel type de champ d'application votre directive crée-t-elle?
Mark Rajcok
1
@MarkRajcok Il a une portée isolée.
Undistraction

Réponses:

202

La directive peut accéder à n'importe quel attribut défini sur le même élément, même si la directive elle-même n'est pas l'élément.

Modèle:

<div example-directive example-number="99" example-function="exampleCallback()"></div>

Directif:

app.directive('exampleDirective ', function () {
    return {
        restrict: 'A',   // 'A' is the default, so you could remove this line
        scope: {
            callback : '&exampleFunction',
        },
        link: function (scope, element, attrs) {
            var num = scope.$eval(attrs.exampleNumber);
            console.log('number=',num);
            scope.callback();  // calls exampleCallback()
        }
    };
});

fiddle

Si la valeur de l'attribut example-numberest codée en dur, je suggère de l'utiliser $evalune fois et de stocker la valeur. La variable numaura le type correct (un nombre).

Mark Rajcok
la source
J'ai modifié l'exemple HTML pour utiliser snake-case. Je sais que je ne peux pas l'utiliser comme élément. C'est le but de la question.
Undistraction
@Pedr, ouais, désolé j'ai lu trop vite sur l'utilisation de l'élément. J'ai mis à jour la réponse, notant que vous devez également utiliser snake-case pour les attributs.
Mark Rajcok
Aucun problème. Merci pour votre réponse. J'ai modifié les noms d'attributs pour utiliser snake-case. Vous êtes d'accord si je supprime cela de votre réponse car c'était juste une erreur stupide de ma part et distrait du point de la question et de la réponse?
Undistraction
Je ne comprends pas cela - comment la directive sait-elle nommer exactement la même chose spécifiée dans l'utilisation de la directive ("exampleCallback ()") dans sa portée? ("callback: '& exampleCallback') La portée ne devrait-elle pas être" callback: "& exampleFunction"?
blaster
1
@FredrikL, pour plusieurs directives sur le même élément, veuillez consulter stackoverflow.com/a/28735005/215945
Mark Rajcok
19

Vous le faites exactement de la même manière que vous le feriez avec une directive d'élément. Vous les aurez dans l'objet attrs, mon exemple les a une liaison bidirectionnelle via la portée isolate mais ce n'est pas obligatoire. Si vous utilisez une portée isolée, vous pouvez accéder aux attributs avec scope.$eval(attrs.sample)ou simplement scope.sample, mais ils peuvent ne pas être définis lors de la liaison en fonction de votre situation.

app.directive('sample', function () {
    return {
        restrict: 'A',
        scope: {
            'sample' : '=',
            'another' : '='
        },
        link: function (scope, element, attrs) {
            console.log(attrs);
            scope.$watch('sample', function (newVal) {
                console.log('sample', newVal);
            });
            scope.$watch('another', function (newVal) {
                console.log('another', newVal);
            });
        }
    };
});

utilisé comme:

<input type="text" ng-model="name" placeholder="Enter a name here">
<input type="text" ng-model="something" placeholder="Enter something here">
<div sample="name" another="something"></div>
Jonathan Rowny
la source
9

Vous pouvez passer un objet comme attribut et le lire dans la directive comme ceci:

<div my-directive="{id:123,name:'teo',salary:1000,color:red}"></div>

app.directive('myDirective', function () {
    return {            
        link: function (scope, element, attrs) {
           //convert the attributes to object and get its properties
           var attributes = scope.$eval(attrs.myDirective);       
           console.log('id:'+attributes.id);
           console.log('id:'+attributes.name);
        }
    };
});
Théo Itzaris
la source
Est-il possible d'envoyer une valeur booléenne à l'aide d'un objet? J'ai essayé {{true}}mais il renvoie toujours la valeur de la chaîne true.
Peter Boomsma
4

Cela a fonctionné pour moi et je pense que c'est plus compatible HTML5. Vous devriez changer votre html pour utiliser le préfixe «data-»

<div data-example-directive data-number="99"></div>

Et dans la directive, lisez la valeur de la variable:

scope: {
        number : "=",
        ....
    },
jmontenegro
la source
0

Si vous "avez besoin" de 'exampleDirective' d'une autre directive + votre logique est dans le contrôleur 'exampleDirective' (disons 'exampleCtrl'):

app.directive('exampleDirective', function () {
    return {
        restrict: 'A',
        scope: false,
        bindToController: {
            myCallback: '&exampleFunction'
        },
        controller: 'exampleCtrl',
        controllerAs: 'vm'
    };
});
app.controller('exampleCtrl', function () {
    var vm = this;
    vm.myCallback();
});
Chat Ilker
la source