2013-03-01 22 views
35

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

私はそれを使って手品を作りました。コンソールが開いていることを確認してください。あなたがリンクとコントローラ機能内

scope.text = $attrs.text; 

を設定した場合、どのように動作することは、ある

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

答えて

25

:ここhttp://jsfiddle.net/paulocoelho/uKA2L/1/

は、私はフィドルに使用していたコードです。これは、2ウェイ・データバインディングがないため、最初は機能します。あなたは$attrs.observeを使用することができます。

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

+0

うんを、私の作品:)感謝の男 – PCoelho

+1

これは、リンティングを失敗します:タイムアウトなしのコードを以下によりcontrollerから属性値を取得するとき、私は何の問題もありません。 'attrs.text'は不明です。 –

+1

@DougChamberlain JSDocを使ってそのことを知ることができます。 '' @param {string} attrs.text''のようなものがあなたの問題を解決するはずです。 –

1

リンク機能は、その時点でスコープ変数が定義されていない、$ダイジェストループの前に呼び出されます。リンク機能の動作を理解するには、this chapterthis otherを参照してください。ディレクティブのウォッチやビヘイビアを定義するためにリンク関数を使用するだけで、モデルを操作するのではなく、コントローラーで行います。

+0

これはすべてではありません。スコープ変数は、リンク後関数が実行される時間によって定義され、リンク関数でデータモデルを操作することは問題ありません。コントローラーは、requireプロパティーを介して別のディレクティブと通信するために使用する予定がある場合にのみ、ディレクティブ上に必要です。コントローラーが実際に最初に実行され、続いてpre-linkが実行され、ドムツリーから葉まで下がってからルートにポストリンクバックされます。明確にするために、このスレッドを参照してください。 https://stackoverflow.com/questions/24615103/angular-directives-when-and-how-to-use-compile-controller-pre-link-and-post –

23

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

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

ローカルスコーププロパティを親スコーププロパティにバインドするデータに '='を使用すると、プロパティの値はリンク関数で使用できます($ observeまたは$ watchまたは$ evalの必要はありません)。あなたはディレクティブを使用して、ビューに挿入するために、あなたの指示からこの値にアクセスしている場合は

+0

+1これは私を馬鹿にしていました。 – GFoley83

+0

+1説明をありがとう! –

0

あなたは$コンパイルAPIを使用してこの属性にアクセスすると角1.3以来、この

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

のような何かをすることができ、あなたが使用することができます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 
    }; 
}); 

角度1.3は、それが言うまさにませbindToControllerと呼ばれるディレクティブの定義 オブジェクトに新しいプロパティを導入します。 controllerAsを使用する独立スコープのディレクティブで をtrueに設定すると、 コンポーネントのプロパティは、 スコープではなくコントローラにバインドされます。つまり、コントローラで がインスタンス化されると、隔離されたスコープバインディングの初期値は であり、今後の変更も自動的に になります。

+1

これは私のために働かなかった、this.textは未定義です。 – rjh

+0

@rjhこのような指令を呼び出すときに 'text'を渡しましたか? '' – Neel

5

代わりディレクティブは個人的に私はcontroller機能のため$attrsを使用して好む、または単にattrslink関数の3番目のパラメータで、値を属性取得する$scopeを使用。

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 
    }] 
    }; 
}); 
関連する問題