如何获得自定义指令中的评估属性

我试图从我的自定义指令得到一个评估属性,但我找不到正确的方式做到这一点。

我已经创build了这个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); } }); 

我错过了什么?

注意:我更新这个答案,因为我find更好的解决scheme。 只要他们保持联系,我也会保留旧的答案。 最新,最好的答案是第一位的。

更好的回答:

angularjs中的指令非常强大,但是需要时间来理解哪些进程在他们后面。

创build指令时,angularjs允许您创build一个与父范围绑定的独立范围。 这些绑定是通过在DOM中附加元素的属性以及如何在指令定义对象中定义scope属性来指定的

有三种types的绑定选项,您可以在范围中定义,并将其作为与前缀相关的属性进行编写。

 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> 

在这种情况下,在指令的范围内(不pipe是链接函数还是控制器),我们可以像这样访问这些属性:

 /* 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是一个不在当前范围的属性的服务,这意味着它只需要angular度expression式,不能达到范围。 {{}}expression式是在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>​​​​​​​​ 

你应该注意的一件事是,如果你想设置值的string,你应该把它包在引号。 (见第三个input)

这里是小提琴玩: http : //jsfiddle.net/neuTA/6/

老答案:

我不会删除这个人谁可以像我这样的误导,请注意,使用$eval是完全正确的方式来做到这一点,但$parse有不同的行为,你可能不会需要这个在大多数案件。

做到这一点的方法是再次使用scope.$eval 。 它不仅编译angular度expression式,还访问当前作用域的属性。

 var myApp = angular.module('myApp',[]); myApp.directive('myDirective', function () { return function (scope, element, attr) { element.val("value = "+ scope.$eval(attr.value)); } }); function MyCtrl($scope) { }​ 

你缺less的是$eval

http://docs.angularjs.org/api/ng.$ro​​otScope.Scope#$eval

在返回结果的当前范围内执行expression式。 expression式中的任何exception都会传播(未捕获)。 这在评估angular度expression式时非常有用。

对于需要在不使用隔离范围的指令中进行插值的属性值,例如,

 <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 ,并且需要正确的types:

 return function (scope, element, attr) { var number = scope.$eval(attr.value); console.log(number, number + 1); }); 

如果属性值是一个string常量,或者希望该值在您的指令中是stringtypes,则可以直接访问它:

 return function (scope, element, attr) { var str = attr.value; console.log(str, str + " more"); }); 

在你的情况,但是,因为你想支持插值和常量,使用$observe

这里的其他答案是非常正确的,有价值的。 但是有时候你只是想简单一点:在指令实例化时得到一个普通的旧的parsing值,而不需要更新,而且不会影响隔离范围。 例如,在你的指令中提供一个声明性的有效载荷作为一个数组或哈希对象的forms可能很方便:

 my-directive-name="['string1', 'string2']" 

在这种情况下,你可以切换到追逐,只需使用一个很好的基本angular.$eval(attr.attrName)

 element.val("value = "+angular.$eval(attr.value)); 

工作小提琴 。

对于同样的解决scheme,我正在Angularjs directive with ng-Model寻找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) { } 

使用$超时,因为在dom加载后指令调用,所以你的变化不适用

很多好的答案在这里,但有时候你只是想要一个简单的,简单的,旧的,jQuery的解决scheme。

我的解决scheme不处理对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 }