Jak uzyskać ocenione atrybuty wewnątrz dyrektywy niestandardowej
Próbuję uzyskać oceniony atrybut z mojej niestandardowej dyrektywy, ale nie mogę znaleźć odpowiedniego sposobu na zrobienie tego.
Stworzyłem ten jsFiddle do rozwinięcia.
<div ng-controller="MyCtrl">
<input my-directive value="123">
<input my-directive value="{{1+1}}">
</div>
myApp.directive('myDirective', function () {
return function (scope, element, attr) {
element.val("value = "+attr.value);
}
});
Co mi umyka? 6 answers
Uwaga: aktualizuję tę odpowiedź, ponieważ znajduję lepsze rozwiązania. Zachowuję również stare odpowiedzi do przyszłego odniesienia, o ile pozostaną ze sobą powiązane. Najnowsza i najlepsza odpowiedź jest na pierwszym miejscu.
Lepsza odpowiedź:
Dyrektywy w angularjs są bardzo potężne, ale potrzeba czasu, aby zrozumieć, które procesy za nimi stoją.Podczas tworzenia dyrektyw, angularjs pozwala na utworzenie izolowanego zakresu z pewnymi powiązaniami z zakresem nadrzędnym. Te wiązania są określone atrybutem dołączasz element w DOM i jak definiujesz właściwość scope w obiekcie definicji dyrektywy .
Istnieją 3 typy opcji wiążących, które można zdefiniować w scope i zapisać je jako atrybut związany z prefiksami.
angular.module("myApp", []).directive("myDirective", function () {
return {
restrict: "A",
scope: {
text: "@myText",
twoWayBind: "=myTwoWayBind",
oneWayBind: "&myOneWayBind"
}
};
}).controller("myController", function ($scope) {
$scope.foo = {name: "Umur"};
$scope.bar = "qwe";
});
HTML
<div ng-controller="myController">
<div my-directive my-text="hello {{ bar }}" my-two-way-bind="foo" my-one-way-bind="bar">
</div>
</div>
W takim przypadku, w zakresie dyrektywy (czy to w funkcji linkującej czy w kontrolerze), możemy uzyskać dostęp do takich właściwości jak to:
/* Directive scope */
in: $scope.text
out: "hello qwe"
// this would automatically update the changes of value in digest
// this is always string as dom attributes values are always strings
in: $scope.twoWayBind
out: {name:"Umur"}
// this would automatically update the changes of value in digest
// changes in this will be reflected in parent scope
// in directive's scope
in: $scope.twoWayBind.name = "John"
//in parent scope
in: $scope.foo.name
out: "John"
in: $scope.oneWayBind() // notice the function call, this binding is read only
out: "qwe"
// any changes here will not reflect in parent, as this only a getter .
"nadal OK" odpowiedź:
Ponieważ ta odpowiedź została zaakceptowana, ale ma pewne problemy, zaktualizuję ją do lepszego. Najwyraźniej $parse
jest usługą, która nie leży we właściwościach bieżącego zakresu, co oznacza, że zajmuje tylko wyrażenia kątowe i nie może osiągnąć zakresu.
{{
,}}
wyrażenia są kompilowane podczas inicjowania angularjs, co oznacza, że gdy próbujemy uzyskać do nich dostęp w naszej metodzie dyrektyw postlink
, są one już kompilowane. ({{1+1}}
jest 2
w dyrektywa już).
Tak chciałbyś użyć:
var myApp = angular.module('myApp',[]);
myApp.directive('myDirective', function ($parse) {
return function (scope, element, attr) {
element.val("value=" + $parse(attr.myDirective)(scope));
};
});
function MyCtrl($scope) {
$scope.aaa = 3432;
}
.
<div ng-controller="MyCtrl">
<input my-directive="123">
<input my-directive="1+1">
<input my-directive="'1+1'">
<input my-directive="aaa">
</div>
Należy zauważyć, że jeśli chcesz ustawić łańcuch wartości, powinieneś zawinąć go w cudzysłowy. (Patrz 3. wejście)
Oto skrzypce do zabawy: http://jsfiddle.net/neuTA/6/
Stara Odpowiedź:
nie usuwam tego dla ludzi, którzy mogą być wprowadzani w błąd, jak ja, zauważ, że używanie $eval
jest całkowicie poprawne, ale $parse
ma inne zachowanie, prawdopodobnie nie będzie to potrzebne do użycia w większości przypadków.
Sposobem na to jest, po raz kolejny, użycie scope.$eval
. Nie tylko kompiluje wyrażenie kątowe, ale ma również dostęp do właściwości bieżącego zakresu.
var myApp = angular.module('myApp',[]);
myApp.directive('myDirective', function () {
return function (scope, element, attr) {
element.val("value = "+ scope.$eval(attr.value));
}
});
function MyCtrl($scope) {
}
Brakuje ci $eval
.
Http://docs.angularjs.org/api/ng.$rootScope. Scope#$eval
Wykonuje wyrażenie na bieżącym obszarze zwracając wynik. Wszelkie wyjątki w wyrażenie jest propagowane (uncaught). Jest to przydatne przy ocenie wyrażeń kątowych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-24 10:08:30
Dla wartości atrybutu, która musi być interpolowana w dyrektywie, która nie używa izolowanego zakresu, np.
<input my-directive value="{{1+1}}">
Użyj metody atrybutów $observe
:
myApp.directive('myDirective', function () {
return function (scope, element, attr) {
attr.$observe('value', function(actual_value) {
element.val("value = "+ actual_value);
})
}
});
Ze strony dyrektywy ,
Obserwacja interpolowanych atrybutów: Użyj
$observe
, aby obserwować zmiany wartości atrybutów zawierających interpolację(np.src="{{bar}}"
). Nie tylko jest to bardzo wydajne, ale jest to również jedyny sposób na łatwe uzyskanie rzeczywistej wartości, ponieważ podczas łączenia Faza interpolacja nie została jeszcze oceniona, więc wartość jest w tym momencie ustawiona naundefined
.
Jeśli wartość atrybutu jest tylko stałą, np.
<input my-directive value="123">
Możesz użyć $eval jeśli wartość jest liczbą lub wartością logiczną i chcesz mieć prawidłowy typ:
return function (scope, element, attr) {
var number = scope.$eval(attr.value);
console.log(number, number + 1);
});
Jeśli wartość atrybutu jest stałą łańcuchową lub chcesz, aby wartość była typu string w Twojej dyrektywie, możesz uzyskać do niej bezpośredni dostęp:
return function (scope, element, attr) {
var str = attr.value;
console.log(str, str + " more");
});
W Twoim przypadku, jednak, ponieważ chcesz obsługa wartości interpolowanych i stałych, użyj $observe
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-01 21:39:21
Inne odpowiedzi tutaj są bardzo poprawne i cenne. Ale czasami po prostu chcesz proste: aby uzyskać zwykłą starą parsowaną wartość w instancjacji dyrektywy, bez konieczności aktualizacji, i bez mieszania z izolować zakres. Na przykład, może być przydatne dostarczenie deklaratywnego ładunku do dyrektywy w postaci tablicy lub obiektu hash w postaci:
my-directive-name="['string1', 'string2']"
W takim razie możesz przejść do sedna i po prostu użyć ładnego podstawowego angular.$eval(attr.attrName)
.
element.val("value = "+angular.$eval(attr.value));
Praca Skrzypce .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-05 16:00:36
Dla tego samego rozwiązania, którego szukałem Angularjs directive with ng-Model
.
Oto kod, który rozwiązuje problem.
myApp.directive('zipcodeformatter', function () {
return {
restrict: 'A', // only activate on element attribute
require: '?ngModel', // get a hold of NgModelController
link: function (scope, element, attrs, ngModel) {
scope.$watch(attrs.ngModel, function (v) {
if (v) {
console.log('value changed, new value is: ' + v + ' ' + v.length);
if (v.length > 5) {
var newzip = v.replace("-", '');
var str = newzip.substring(0, 5) + '-' + newzip.substring(5, newzip.length);
element.val(str);
} else {
element.val(v);
}
}
});
}
};
});
HTML DOM
<input maxlength="10" zipcodeformatter onkeypress="return isNumberKey(event)" placeholder="Zipcode" type="text" ng-readonly="!checked" name="zipcode" id="postal_code" class="form-control input-sm" ng-model="patient.shippingZipcode" required ng-required="true">
mój wynik to:
92108-2223
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-27 13:14:21
var myApp = angular.module('myApp',[]);
myApp .directive('myDirective', function ($timeout) {
return function (scope, element, attr) {
$timeout(function(){
element.val("value = "+attr.value);
});
}
});
function MyCtrl($scope) {
}
Użyj $ timeout, ponieważ dyrektywa wywołuje po załadowaniu dom, więc twoje zmiany nie mają zastosowania
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-02 07:54:45
Wiele dobrych odpowiedzi tutaj, ale czasami po prostu chcesz zwykły, łatwy, Stary, jQuery-owski, rozwiązanie.
Moje rozwiązanie nie obsługuje zmian w DOM. Jeśli atrybut może się zmienić, nie używaj mojej metody!
W moim przypadku miałem element i musiałem pobrać wartość atrybutu (rel).
Szablon:
<div ng-repeat="elm in array">
<button class="poi-lines-show" rel="li-{{$index}}">button-text</button>
</div>
In my directive:
var buttons = element[0].querySelectorAll('button');
for (var i=0; i<buttons.length; i++) {
var target = angular.element(buttons[i]);
console.log(target.attr('rel')); // Outputs 'li-0', 'li-1', 'li-2' etc
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-31 08:54:08