web-dev-qa-db-ja.com

カスタムディレクティブ内部で評価された属性を取得する方法

カスタムディレクティブから evaluate 属性を取得しようとしていますが、正しい方法が見つかりません。

私は この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);
    }
});

何が足りないの?

359
Shlomi Schwartz

Notice:より良い解決策が見つかると、この回答を更新します。私はまた、それらが関連している限り、将来の参考のために古い答えを保管します。最新かつ最善の答えが最初に来る。

より良い答え:

Angularjsの指令は非常に強力ですが、どのプロセスがそれらの背後にあるのかを理解するのに時間がかかります。

ディレクティブを作成している間、angularjsはあなたがisolated scopeを親のscopeへのいくつかの束縛で作成することを可能にします。これらのバインディングは、DOMで要素を付加する attribute と、ディレクティブ定義オブジェクト 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.$ro​​otScope.Scope#$eval

現在のスコープで式を実行して結果を返します。式の中の例外はすべて伝播されます(キャッチされません)。これは角度表現を評価するときに便利です。

566
Umur Kontacı

分離スコープを使用していないディレクティブで補間する必要がある属性値の場合

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

ディレクティブ pageから、

内挿された属性を観察する:内挿を含む属性の値の変化を観察するには$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を使います。

82
Mark Rajcok

私は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
4
Satish Singh

ここでの他の答えは非常に正確で価値があります。しかし、時にはあなたは単純なことを望みます:更新を必要とせずに、そして分離スコープをめちゃくちゃにせずに、ディレクティブのインスタンス生成時に単純で古い解析値を取得します。たとえば、宣言ペイロードをディレクティブに配列またはハッシュオブジェクトとして次の形式で指定すると便利です。

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

その場合は、追いついてニースの基本的なangular.$eval(attr.attrName)を使うことができます。

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

Working Fiddle

4
XML
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のロード後にディレクティブを呼び出して変更が適用されないため、$ timeoutを使用します。

2
user1693371