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

我试图从我的自定义指令中获得评估属性,但我找不到正确的方法。

我创建了这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);
}
});

我错过了什么?

309845 次浏览

注意:当我找到更好的解决方案时,我会更新这个答案。我也保留旧的答案,以备将来参考,只要它们仍然相关。最新最好的答案是第一位的。

更好的回答:

angularjs中的指令非常强大,但是理解它们背后的进程需要时间。

在创建指令时,angularjs允许你创建带有父作用域绑定的范围隔离。这些绑定由DOM中附加元素的属性和在指令定义对象中定义范围属性的方式指定。

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

超文本标记语言

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

“仍然OK"答:

因为这个答案被接受了,但有一些问题,我将把它更新为一个更好的答案。显然,$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>​​​​​​​​

这里您应该注意的一点是,如果您想设置值字符串,您应该用引号将其括起来。(见第三个输入)

下面是用来演奏的小提琴: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
下面是解决问题的代码。
< / p >

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


}


});


}
};
});
< p >
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">
< p >
我的结果是:

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加载后,所以你的改变不适用