¿Cómo paso múltiples atributos a una directiva de atributo Angular.js?

116

Tengo una directiva de atributo restringida de la siguiente manera:

 restrict: "A"

Necesito pasar dos atributos; un número y una función / devolución de llamada, accediendo a ellos dentro de la directiva utilizando el attrsobjeto.

Si la directiva fuera una directiva de elemento, restringida con "E"podría a esto:

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

Sin embargo, por razones en las que no entraré, necesito que la directiva sea una directiva de atributos.

¿Cómo paso varios atributos a una directiva de atributo?

Distracción
fuente
Eso depende del tipo de alcance que crea su directiva (si corresponde). Las opciones son: sin alcance nuevo (predeterminado o explícito con scope: false), alcance nuevo (con herencia prototípica normal, es decir, scope: true) y alcance aislado (es decir, scope: { ... }). ¿Qué tipo de alcance crea su directiva?
Mark Rajcok
1
@MarkRajcok Tiene un alcance aislado.
distracciones

Respuestas:

202

La directiva puede acceder a cualquier atributo que esté definido en el mismo elemento, incluso si la directiva en sí no es el elemento.

Modelo:

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

Directiva:

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 el valor del atributo example-numberestará codificado, sugiero usarlo $evaluna vez y almacenar el valor. La variable numtendrá el tipo correcto (un número).

Mark Rajcok
fuente
He editado el HTML de ejemplo para usar snake-case. Sé que no puedo usarlo como elemento. Ese es el punto de la pregunta.
distracciones
@Pedr, sí, lo siento, leí demasiado rápido sobre el uso del elemento. Actualicé la respuesta, señalando que también necesita usar snake-case para los atributos.
Mark Rajcok
No hay problema. Gracias por tu respuesta. He editado los nombres de los atributos para usar snake-case. ¿Está bien si elimino eso de su respuesta, ya que fue solo un error tonto por mí y me distrae del punto de la pregunta y la respuesta reales?
distracciones
No entiendo esto, ¿cómo sabe la directiva nombrar exactamente lo mismo que se especifica en el uso de la directiva ("exampleCallback ()") en su alcance? ("callback: '& exampleCallback') ¿No debería el alcance ser" callback: "& exampleFunction"?
bláster
1
@FredrikL, para varias directivas sobre el mismo elemento, consulte stackoverflow.com/a/28735005/215945
Mark Rajcok
19

Lo hace exactamente de la misma manera que lo haría con una directiva de elemento. Los tendrá en el objeto attrs, mi muestra los tiene enlaces bidireccionales a través del alcance aislado, pero eso no es obligatorio. Si está utilizando un alcance aislado, puede acceder a los atributos con scope.$eval(attrs.sample)o simplemente scope.sample, pero es posible que no se definan en el enlace según su situación.

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

Usado como:

<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
fuente
9

Puede pasar un objeto como atributo y leerlo en la directiva de esta manera:

<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);
        }
    };
});
Theo Itzaris
fuente
¿Es posible enviar un valor booleano usando un objeto? Lo intenté {{true}}pero todavía devuelve el valor de la cadena true.
Peter Boomsma
4

Esto funcionó para mí y creo que es más compatible con HTML5. Debe cambiar su html para usar el prefijo 'data-'

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

Y dentro de la directiva lea el valor de la variable:

scope: {
        number : "=",
        ....
    },
jmontenegro
fuente
0

Si "requiere" 'exampleDirective' de otra directiva + su lógica está en el controlador de 'exampleDirective' (digamos '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();
});
Gato Ilker
fuente