Javascript 如何在自定义指令中获取经过计算的属性

Javascript 如何在自定义指令中获取经过计算的属性,javascript,binding,angularjs,directive,Javascript,Binding,Angularjs,Directive,我试图从我的自定义指令中获取一个求值的属性,但我找不到正确的方法 我的创作是为了详细阐述 <div ng-controller="MyCtrl"> <input my-directive value="123"> <input my-directive value="{{1+1}}"> </div> myApp.directive('myDirective', function () { return function (

我试图从我的自定义指令中获取一个求值的属性,但我找不到正确的方法

我的创作是为了详细阐述

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

myApp.directive('myDirective',function(){
返回函数(范围、元素、属性){
element.val(“value=“+attr.value”);
}
});
我遗漏了什么?

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

更好的答案是: 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

“仍然可以”回答: 因为这个答案被接受了,但有一些问题,我将更新到一个更好的。显然,
$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;
}​

您缺少的是
$eval

在返回结果的当前作用域上执行表达式。表达式中的任何异常都会传播(未捕获)。这在计算角度表达式时非常有用


对于需要在不使用隔离作用域的指令中插入的属性值,例如

<input my-directive value="{{1+1}}">
从页面上

观察插值属性:使用
$observe
观察包含插值的属性的值变化(例如
src=“{{bar}}”
)。这不仅非常有效,而且也是容易获得实际值的唯一方法,因为在链接阶段,插值尚未计算,因此此时该值设置为
未定义

如果属性值只是一个常量,例如

<input my-directive value="123">
如果属性值是字符串常量,或者您希望指令中的值是字符串类型,则可以直接访问它:

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

但是,在您的情况下,由于您希望支持插值和常量,请使用
$observe

此处的其他答案非常正确,而且很有价值。但有时您只需要简单:在指令实例化时获取一个普通的旧解析值,而不需要更新,也不需要混淆隔离范围。例如,可以方便地将声明性负载作为数组或哈希对象提供到指令中,格式如下:

my-directive-name="['string1', 'string2']"
在这种情况下,您可以直接使用一个漂亮的基本
angular.$eval(attr.attrName)


工作。

对于我正在寻找的带有ng模型的
Angularjs指令的相同解决方案

以下是解决此问题的代码。


HTMLDOM

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

使用$timeout,因为在dom加载后会调用指令,所以您的更改不会应用

谢谢您的回复,但这不是解决方案。我已经更新了你的密码。在Chrome中,我在尝试使用scope时遇到这个错误。$parse:Object#没有方法“$parse”。如果我注入$parse服务--function($parse){return function(scope…--然后尝试:“value=”+$parse(attr.value)--这似乎对我也不起作用。@请注意,奇怪的是,它在fiddle示例()中起作用,但在我拥有的代码中不起作用……角度版本?在“更好的答案”中第节,
$scope.text
将在链接函数中未定义。按照当前的措辞,答案听起来似乎没有定义。您必须使用$observe()(或者$watch()在这里也可以实际工作)异步查看插值。请参见我的答案以及“仍然正常”中的内容回答似乎
$parse
服务被注入,然后从未使用过。我遗漏了什么吗?这是您找到的唯一解决方案吗?是的,既然指令页面推荐了这种方法,我就是这么做的。+1,这是最好的回答,因为它不会强制指令上的作用域,也会用$o覆盖属性更改bserveI不知道您是否使用了旧的angular版本,但您的所有代码示例要么是无效的javascript(我的指令名=),要么是无效的angular(angular.$eval不存在),所以-1嗯…鉴于这篇文章已经有一年多的历史了,如果有什么东西被弃用了,这一点也不奇怪。然而,10秒钟的谷歌搜索会发现大量关于$eval的资料,包括。你引用的另一个例子是HTML调用,而不是Javascript。$scope.$eval(attr.val)在angular 1.4中工作。需要将$scope注入到指令链接函数中。为了更好地理解指令,您可以遵循下面的链接。
myApp.directive('myDirective', function () {
  return function (scope, element, attr) {
    attr.$observe('value', function(actual_value) {
      element.val("value = "+ actual_value);
    })
 }
});
<input my-directive value="123">
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");
});
my-directive-name="['string1', 'string2']"
element.val("value = "+angular.$eval(attr.value));
    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);
                    }

                }

            });

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

}