¿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?


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).


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>

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

¿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 : "=",
        ....
    },

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();
});
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.