web-dev-qa-db-ja.com

AngularJSディレクティブはコントローラーからのアクセスを属性化します

コントローラ関数のディレクティブの属性にアクセスしようとしています。ただし、アクセスするまでには定義されていません。単純なタイマーを実行すると動作することに気付きました。ディレクティブとスコープの準備ができて使用するように設定された後にのみコードを実行する方法はありますか?

私はそれをいじりました。コンソールが開いていることを確認してください。 http://jsfiddle.net/paulocoelho/uKA2L/1/

以下が、私がフィドルで使用しているコードです。

<div ng-app="testApp" >
    <testcomponent text="hello!"></testcomponent>
</div>
var module = angular.module('testApp', [])
    .directive('testcomponent', function () {
    return {
        restrict: 'E',
        template: '<div><p>{{text}} This will run fine! </p></div>',
        scope: {
            text: '@text'
        },
        controller: function ($scope, $element) {
            console.log($scope.text); // this will return undefined
            setTimeout(function () {
                console.log($scope.text);    // this will return the actual value...
            }, 1000);
        },
        link: function ($scope, $element, $attrs) {
            console.log($scope.text);
            setTimeout(function () {
                console.log($scope.text);
            }, 1000);
        }
    };
});
37
PCoelho

動作するのは、設定すると

scope.text = $attrs.text;

リンクおよびコントローラー機能内。 2wayデータバインディングがないため、これは最初にのみ機能します。ただし、 $ attrs.observe を使用できます。

フィドルを参照してください: http://jsfiddle.net/JohannesJo/nm3FL/2/

27

分離スコープでは、「@」で定義されたローカルスコーププロパティにリンク関数でアクセスできません。 @remigioで既に述べたように、そのようなローカルスコーププロパティはその時点ではundefinedです。 (補間された)値を非同期的に取得するには、$ attrs。$ observe()または$ scope。$ watch()を使用する必要があります。

属性に定数値を渡す場合(つまり、補間が不要、つまり属性の値に{{}}が含まれない場合)、「@」、$ observer、または$ watchの必要はありません。 $ attrsを使用できます。属性名 @hugoが示唆するように1回、または数値またはブール値を渡して適切な型を取得したい場合は、$ scope。$ eval($ attrs。属性名)一度。

「=」を使用してローカルスコーププロパティを親スコーププロパティにデータバインドすると、プロパティの値がリンク関数で利用可能になります($ observe、$ watch、または$ evalは不要)。

25
Mark Rajcok

Angular 1.3なので、bindToControllerを使用できます。使用方法のサンプルを次に示します。ここでは、属性をスコープに追加してからbindToControllerを使用しますコントローラ内でそれを使用するには:

var module = angular.module('testApp', [])
    .directive('testcomponent', function () {
    return {
        restrict: 'E',
        template: '<div><p>{{text}} This will run fine! </p></div>',
        scope: {
            text: '@text'
        },
        controller: function () {
            console.log(this.text);
        },
        controllerAs: 'vm',
        bindToController: true
    };
});

Angular 1.3では、bindToControllerと呼ばれるディレクティブ定義オブジェクトに新しいプロパティが導入されており、これはまさにそれを実行します。 controllerAsを使用する分離スコープを持つディレクティブでtrueに設定すると、コンポーネントのプロパティはスコープではなくコントローラーにバインドされます。つまり、Angularは、コントローラがインスタンス化されたときに、分離されたスコープバインディングの初期値がこれで利用可能であり、将来の変更も自動的に利用できることを確認します。

8
Neel

代わりに$scopeディレクティブの属性値を取得するには、個人的には$attrscontroller関数、またはattrs関数の3番目のパラメーターでのlinkのみ。タイムアウトなしで次のコードでcontrollerから属性値を取得しても問題ありません。

var module = angular.module('testApp', [])
    .directive('testcomponent', function () {
    return {
    restrict: 'E',
    template: '<div><p>{{text}} This will run fine! </p></div>',
    scope: {
        text: '@text'
    },
    controller: ['$scope','$attrs', function ($scope, $attrs) {
        console.log($attrs.text); // just call to the $attrs instead $scope and i got the actual value
        $scope.text = $attrs.text; //assign attribute to the scope
    }]
    };
});
6
Bayu

リンク関数は、$ digestループの前に呼び出され、その時点でスコープ変数は未定義です。 この章この他 を見て、リンク関数の動作を理解してください。リンク関数は、モデルの操作ではなく、ディレクティブの監視や動作を定義するためにのみ使用します。これはコントローラーで行われます。

1
remigio

ディレクティブを使用してビューに挿入するためにディレクティブからこの値にアクセスしている場合、$ compile apiを使用してこの属性にアクセスし、次のようなことを行うことができます。

var string = "<div> " + scope.text + "</div>";
$compile(string)(scope, function(cloned, scope){
       element.append(cloned);
});
0
cuterthanbacon