Jak przekazać wiele atrybutów do dyrektywy atrybutów Angular.js?

116

Mam dyrektywę atrybutów ograniczoną w następujący sposób:

 restrict: "A"

Muszę przekazać dwa atrybuty; numer i funkcję / wywołanie zwrotne, uzyskując do nich dostęp w ramach dyrektywy za pomocą attrsobiektu.

Gdyby dyrektywa była dyrektywą elementarną, ograniczyłbym się "E"do tego:

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

Jednak z powodów, którymi nie będę się poruszać, potrzebuję dyrektywy, aby była dyrektywą atrybutów.

Jak przekazać wiele atrybutów do dyrektywy atrybutu?

Nieuwaga
źródło
To zależy od typu zakresu, jaki tworzy Twoja dyrektywa (jeśli istnieje). Do wyboru są: brak nowego zakresu (domyślny lub jawny scope: false), nowy zakres (z normalnym dziedziczeniem prototypowym, tj., scope: true) I zakres izolowany (tj scope: { ... }.). Jaki zakres tworzy Twoja dyrektywa?
Mark Rajcok
1
@MarkRajcok Ma zakres izolowany.
Undistraction

Odpowiedzi:

202

Dyrektywa może uzyskać dostęp do dowolnego atrybutu zdefiniowanego w tym samym elemencie, nawet jeśli sama dyrektywa nie jest tym elementem.

Szablon:

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

Dyrektywa:

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

Jeśli wartość atrybutu example-numberzostanie zakodowana na stałe, sugeruję użycie $evalraz i zapamiętanie wartości. Zmienna numbędzie miała właściwy typ (liczbę).

Mark Rajcok
źródło
Edytowałem przykładowy kod HTML, aby używać przypadku węża. Wiem, że nie mogę tego użyć jako elementu. O to chodzi w pytaniu.
Undistraction
@Pedr, tak, przepraszam, czytam za szybko o użyciu elementu. Zaktualizowałem odpowiedź, zauważając, że do atrybutów musisz również używać przypadku węża.
Mark Rajcok
Nie ma problemu. Dziękuję za odpowiedź. Zmieniłem nazwy atrybutów, aby używać wielkości węża. Wszystko w porządku, jeśli usunę to z Twojej odpowiedzi, ponieważ był to po prostu głupi błąd z mojej strony i odciągający uwagę od właściwego pytania i odpowiedzi?
Undistraction
Nie rozumiem - skąd dyrektywa wie, aby nazwać dokładnie to samo, co określono w użyciu dyrektywy („exampleCallback ()”) w swoim zakresie? ("callback: '& exampleCallback') Czy zakresem nie powinno być" callback: "& exampleFunction"?
blaster,
1
@FredrikL, informacje na temat wielu dyrektyw dotyczących tego samego elementu można znaleźć na stronie stackoverflow.com/a/28735005/215945
Mark Rajcok
19

Robisz to dokładnie w taki sam sposób, jak w przypadku dyrektywy elementu. Będziesz je mieć w obiekcie attrs, moja próbka ma ich dwukierunkowe wiązanie za pośrednictwem zakresu izolowanego, ale nie jest to wymagane. Jeśli używasz zakresu izolowanego, możesz uzyskać dostęp do atrybutów za pomocą scope.$eval(attrs.sample)lub po prostu scope.sample, ale mogą one nie być zdefiniowane podczas łączenia w zależności od sytuacji.

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

użyty jako:

<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
źródło
9

Możesz przekazać obiekt jako atrybut i wczytać go do dyrektywy w następujący sposób:

<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
źródło
Czy można wysłać wartość logiczną za pomocą obiektu? Próbowałem, {{true}}ale nadal zwraca wartość ciągu true.
Peter Boomsma,
4

To zadziałało dla mnie i myślę, że jest bardziej zgodne z HTML5. Powinieneś zmienić swój kod HTML tak, aby używał przedrostka „data-”

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

A w ramach dyrektywy odczytaj wartość zmiennej:

scope: {
        number : "=",
        ....
    },
czarnogóra
źródło
0

Jeśli „wymagasz” „exampleDirective” z innej dyrektywy + Twoja logika znajduje się w kontrolerze „exampleDirective” (powiedzmy „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();
});
Ilker Cat
źródło