Javascript 如何在自定义指令中获取评估的属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12371159/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:50:11  来源:igfitidea点击:

How to get evaluated attributes inside a custom directive

javascriptbindingangularjsdirective

提问by Shlomi Schwartz

I'm trying to get an evaluatedattribute from my custom directive, but I can't find the right way of doing it.

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

I've created this jsFiddleto elaborate.

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

What am I missing?

我错过了什么?

回答by Umur Kontac?

Notice: I do update this answer as I find better solutions. I also keep the old answers for future reference as long as they remain related. Latest and best answer comes first.

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

Better answer:

更好的答案:

Directives in angularjs are very powerful, but it takes time to comprehend which processes lie behind them.

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

While creating directives, angularjs allows you to create an isolated scopewith some bindings to the parent scope. These bindings are specified by the attributeyou attach the element in DOM and how you define scopeproperty in the directive definition object.

在创建指令时,angularjs 允许您创建一个独立的作用域,并绑定到父作用域。这些绑定由您在 DOM 中附加元素的属性以及您在指令定义对象中定义范围属性的方式指定

There are 3 types of binding options which you can define in scope and you write those as prefixes related attribute.

您可以在范围内定义 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

HTML

<div ng-controller="myController">
    <div my-directive my-text="hello {{ bar }}" my-two-way-bind="foo" my-one-way-bind="bar">
    </div>
</div>

In that case, in the scope of directive (whether it's in linking function or controller), we can access these properties like this:

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

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

"Still OK" Answer:

“还行” 答案:

Since this answer got accepted, but has some issues, I'm going to update it to a better one. Apparently, $parseis a service which does not lie in properties of the current scope, which means it only takes angular expressions and cannot reach scope. {{,}}expressions are compiled while angularjs initiating which means when we try to access them in our directives postlinkmethod, they are already compiled. ({{1+1}}is 2in directive already).

由于此答案已被接受,但存在一些问题,因此我会将其更新为更好的答案。显然,$parse是一个不属于当前作用域属性的服务,这意味着它只需要角度表达式,不能到达作用域。 {{,}}表达式在 angularjs 启动时被编译,这意味着当我们尝试在我们的指令postlink方法中访问它们时,它们已经被编译。({{1+1}}已经2在指令中)。

This is how you would want to use:

这是您想要使用的方式:

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

One thing you should notice here is that, if you want set the value string, you should wrap it in quotes. (See 3rd input)

这里你应该注意的一件事是,如果你想设置值字符串,你应该把它用引号括起来。(见第三个输入)

Here is the fiddle to play with: http://jsfiddle.net/neuTA/6/

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

Old Answer:

旧答案:

I'm not removing this for folks who can be misled like me, note that using $evalis perfectly fine the correct way to do it, but $parsehas a different behavior, you probably won't need this to use in most of the cases.

对于像我这样可能被误导的人,我不会删除它,请注意,使用$eval是完全正确的正确方法,但是$parse有不同的行为,在大多数情况下您可能不需要使用它。

The way to do it is, once again, using scope.$eval. Not only it compiles the angular expression, it has also access to the current scope's properties.

这样做的方法是再次使用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) {

}?

What you are missing was $eval.

你缺少的是$eval.

http://docs.angularjs.org/api/ng.$rootScope.Scope#$eval

Executes the expression on the current scope returning the result. Any exceptions in the expression are propagated (uncaught). This is useful when evaluating angular expressions.

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

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

回答by Mark Rajcok

For an attribute value that needs to be interpolated in a directive that is not using an isolated scope, e.g.,

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

<input my-directive value="{{1+1}}">

use Attributes' method $observe:

使用属性的方法$observe

myApp.directive('myDirective', function () {
  return function (scope, element, attr) {
    attr.$observe('value', function(actual_value) {
      element.val("value = "+ actual_value);
    })
 }
});

From the directivepage,

指令页面,

observing interpolated attributes: Use $observeto observe the value changes of attributes that contain interpolation (e.g. src="{{bar}}"). Not only is this very efficient but it's also the only way to easily get the actual value because during the linking phase the interpolation hasn't been evaluated yet and so the value is at this time set to undefined.

观察插值属性:$observe用于观察包含插值的属性的值变化(例如src="{{bar}}")。这不仅非常有效,而且还是轻松获取实际值的唯一方法,因为在链接阶段尚未评估插值,因此此时将值设置为undefined.

If the attribute value is just a constant, e.g.,

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

<input my-directive value="123">

you can use $evalif the value is a number or boolean, and you want the correct type:

如果值是数字或布尔值,并且您想要正确的类型,则可以使用$eval

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

If the attribute value is a string constant, or you want the value to be string type in your directive, you can access it directly:

如果属性值是字符串常量,或者您希望指令中的值是字符串类型,则可以直接访问它:

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

In your case, however, since you want to support interpolated values and constants, use $observe.

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

回答by XML

The other answers here are very much correct, and valuable. But sometimes you just want simple: to get a plain old parsed value at directive instantiation, without needing updates, and without messing with isolate scope. For instance, it can be handy to provide a declarative payload into your directive as an array or hash-object in the form:

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

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

In that case, you can cut to the chase and just use a nice basic angular.$eval(attr.attrName).

在这种情况下,您可以切入正题,只使用一个不错的基本angular.$eval(attr.attrName).

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

Working Fiddle.

工作小提琴

回答by Satish Singh

For the same solution I was looking for Angularjs directive with ng-Model.
Here is the code that resolve the problem.

对于我正在寻找的相同解决方案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


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


My Result is:


我的结果是:

92108-2223

回答by user1693371

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

}

Use $timeout because directive call after dom load so your changes doesn`'t apply

使用 $timeout 因为在 dom 加载后调用指令,因此您的更改不适用