Как получить оцененные атрибуты внутри пользовательской директивы
Я пытаюсь получить оценка атрибут из моей пользовательской директивы, но я не могу найти правильный способ сделать это.
Я создал этот jsFiddle подробнее.
<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);
}
});
чего мне не хватает?
6 ответов:
обратите внимание: я обновляю этот ответ, поскольку нахожу лучшие решения. Я также сохраняю старые ответы для дальнейшего использования, пока они остаются связанными. Самый последний и самый лучший ответ приходит сперва.
лучше ответь:
директивы в angularjs очень мощные, но требуется время, чтобы понять, какие процессы лежат за ними.
при создании директив angularjs позволяет создать изолированные области С привязки к родительской области. Эти привязки задаются параметром атрибут вы прикрепляете элемент в DOM и как вы определяете scope собственность в объект определения директивы.
существует 3 типа параметров привязки, которые вы можете определить в области видимости, и вы пишете их как атрибут, связанный с префиксами.
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>
в таком случае, в области действия директивы (будь то это в функции связывания или контроллера), мы можем получить доступ к этим свойствам следующим образом:
/* 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 .
" все еще хорошо " ответ:
поскольку этот ответ был принят, но имеет некоторые проблемы, я собираюсь обновить его до лучшего. Видимо,
$parse
это сервис, который не лежит в свойствах текущей области, что означает, что он принимает только угловые выражения и не может достичь области.{{
,}}
выражения компилируются при инициализации angularjs, что означает, когда мы пытаемся чтобы получить к ним доступ в наших директивахpostlink
метод, они уже скомпилированы. ({{1+1}}
и2
уже в директиве).это, как вы хотели бы использовать:
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>
здесь вы должны заметить, что если вы хотите установить строку значения, вы должны заключить ее в кавычки. (См. 3-й вход)
вот скрипка, чтобы играть с:http://jsfiddle.net/neuTA/6/
старый Ответ:
я не удаляю это для людей, которые могут быть введены в заблуждение, как я, обратите внимание, что с помощью
$eval
это прекрасно правильный способ сделать это, но$parse
имеет другое поведение, вам, вероятно, не нужно будет это использовать в большинстве случаев.способ сделать это, еще раз, используя
scope.$eval
. Он не только компилирует угловое выражение, но и имеет доступ к свойствам текущей области.var myApp = angular.module('myApp',[]); myApp.directive('myDirective', function () { return function (scope, element, attr) { element.val("value = "+ scope.$eval(attr.value)); } }); function MyCtrl($scope) { }
то, что вам не хватает было
$eval
.http://docs.angularjs.org/api/ng.$rootScope. Scope#$eval
выполняет выражение в текущей области, возвращающее результат. Любые исключения в выражении распространяются (не перехватываются). Это полезно при оценке угловых выражений.
для значения атрибута, которое должно быть интерполировано в директиве, которая не использует изолированную область, например,
<input my-directive value="{{1+1}}">
использовать метод атрибутов
$observe
:myApp.directive('myDirective', function () { return function (scope, element, attr) { attr.$observe('value', function(actual_value) { element.val("value = "+ actual_value); }) } });
С директива страницы
наблюдение интерполированных атрибутов: использовать
$observe
для наблюдения за изменением значений атрибутов, содержащих интерполяцию (например,src="{{bar}}"
). Это не только очень эффективно, но это также единственный способ легко получить фактическое значение, потому что во время фазы связывания интерполяция еще не была оценена, и поэтому значение в это время установлено вundefined
.если значение атрибута является просто константой, например,
<input my-directive value="123">
можно использовать $ eval если значение является числом или логическим, и вы хотите правильный тип:
return function (scope, element, attr) { var number = scope.$eval(attr.value); console.log(number, number + 1); });
если значение атрибута является Строковой константой, или вы хотите, чтобы значение было строковым типом в вашей директиве, вы можете доступ к нему напрямую:
return function (scope, element, attr) { var str = attr.value; console.log(str, str + " more"); });
в вашем случае, однако, поскольку вы хотите поддерживать интерполированные значения и константы, используйте
$observe
.
другие ответы здесь очень правильные и ценные. Но иногда вы просто хотите просто: получить простое старое проанализированное значение при создании экземпляра директивы, без необходимости обновления и без возни с областью изоляции. Например, может быть удобно предоставить декларативную полезную нагрузку в вашу директиву в виде массива или хэш-объекта в виде:
my-directive-name="['string1', 'string2']"
в этом случае вы можете сократить погоню и просто использовать хороший базовый
angular.$eval(attr.attrName)
.element.val("value = "+angular.$eval(attr.value));
рабочая Скрипка.
для того же решения, которое я искал
Angularjs directive with ng-Model
.
вот код, который решает проблему.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">
мой результат:92108-2223
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) { }
используйте $ timeout, потому что директива вызывает после загрузки dom, поэтому ваши изменения не применяются
много хороших ответов здесь, но иногда вы просто хотите простой, легкий, старый, jQuery-иш, решение.
мое решение не обрабатывает изменения в DOM. Если атрибут может измениться, не используйте мой метод!
в моем случае у меня был элемент, и мне нужно было получить значение атрибута (rel).
шаблон:
<div ng-repeat="elm in array"> <button class="poi-lines-show" rel="li-{{$index}}">button-text</button> </div>
в моей директивы:
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 }
Comments