2013-09-06 15 views
6

AngularJSを使用する。私は双方向のデータバインディングをしたいという指示があります。このディレクティブには、「activate」という属性があります。最初に、「有効化」の値は「1」になります。属性の変更

ディレクティブのリンク機能は、「有効化」が「1」に等しいかどうかをチェックします。もしそうなら、それは "活性化"を0に変えますが、他の何かをします。

後で、コントローラでもう一度指示をしたい場合は、再度「アクティブ化」を「1」に変更します。ディレクティブにはウォッチがあるため、サイクルが繰り返されます。

残念ながら、私はこれを行うたびに、「testDirective」のディレクティブで使用される「式 '0」が割り当てられません!または「割り当て不可能なモデル式:1(指示:testDirective)」を選択します。ここで

はHTMLです:

<body ng-app="app"> 
    <test-directive activate="1"></test-directive>  
</body> 
ここ

はJSです:

var app = angular.module('app', []); 


app.directive('testDirective', function() { 
    return { 
     restrict: 'E', 
     scope: { 
      activate : '=' 
     }, 


     link: function(scope, elem, attrs, controller) { 
      var el = elem[0]; 

      var updateContent = function() { 
       el.innerText = 'Activate=' + scope.activate; 
      }; 

      updateContent(); 
      attrs.$observe('activate', function() { 
       console.log('Activate=' + scope.activate); 
       if(scope.activate == '1') { 
        scope.activate = '0' 
        updateContent(); 
       } 
      }); 
     } 
    } 
});  

ここでは、jsFiddleである:http://jsfiddle.net/justbn/mgSpY/3/

なぜ私はディレクティブの属性に格納されている値を変更することはできません。 ?私は2ウェイバインディングを使用しています。

ドキュメントでは、「親スコーププロパティが存在しない場合、NON_ASSIGNABLE_MODEL_EXPRESSION例外がスローされます。

注:更新内容に「有効化」の値が正しく表示されます。ただし、「」内の「有効化」の値は更新されません。

親スコープのプロパティが存在するので、それは私には意味がありません。

アイデア?スコープのプロパティを監視するために

答えて

12

attrs.$observeの代わりに$watchを使用することに同意しますが、それはあなたが受け取ったエラーメッセージの主な理由ではありません。

問題は、あなたが非割り当て可能式に値を代入しようとしているということです - エラーメッセージがわかりますよう:Non-assignable model expression: 1 (directive: testDirective)

この場合、非割り当て可能な表現が数「1」である

<test-directive activate="1"> 

あなたはディレクティブの初期値(1)を渡すために管理しますが、ディレクティブはその値を更新しようとしたときに属性を変更することはできませんアクティブ - それは数だから。

それで、変数を変数に変更して後で値を更新できるようにする必要があります。

以下のコードを参照して、コントローラを介してactivate.initialValueという$ scopeの変数を初期化します。

さらにattrs.$observeの代わりに$watchを使用しました。

イベントをシミュレートするためにちょうど2秒後に有効値を変更するために$timeoutを追加しました。

HTML

<body ng-app="app" ng-controller="appCtrl"> 
    <test-directive activate="activate.initialValue"></test-directive>  
</body> 

JS

var app = angular.module('app', []); 

app.controller('appCtrl', function($scope){ 
    $scope.activate = { 
     initialValue : 1 
    } 
}); 

var app = angular.module('app', []); 

app.controller('appCtrl', function($scope){ 
    $scope.activate = { 
     initialValue : 2 
    } 
}); 

app.directive('testDirective', function($timeout) { 
    return { 
     restrict: 'E', 
     scope: { 
      activate : '=' 
     },  
     link: function(scope, elem, attrs) { 
      scope.$watch('activate', function(newValue, oldValue){ 
       console.log('activate has changed', newValue); 
      }); 

      $timeout(function(){ 
        scope.activate = 0;  
       }, 2000); 
     }, 
     template: "{{activate}}" 
    } 
}); 

あなたがここにも(http://jsfiddle.net/mgSpY/63/)作業を見ることができます。

そして、ここでは、それはそれについてAngularJS公式ドキュメント(http://docs.angularjs.org/error/ngModel:nonassign

+0

dluz:私は働く解決策のためにMichaelに答えを与えました。しかし、私はあなたにそれを変更しました。あなたは私がそれをより良く理解できるようにそれを説明しました。本当にありがとう! – Justin

+0

ジャスティン:喜んで助けてください! :) –

+0

これは私の答えの一部でした。私はスコープを実行しなければなりませんでした。$ apply()を変更した後に$ watchがトリガーしませんでした。 – LucasBeef

3

、あなたの代わりにattrs.$observescope.$watchを使用する必要があります。

link: function(scope, elem, attrs, controller) { 
    var el = elem[0]; 

    var updateContent = function() { 
    el.innerText = 'Activate=' + scope.activate; 
    }; 

    scope.$watch('activate', function(value) {        
    console.log('Activate=', value); 
    if(value === 1) { 
     scope.activate = '0'      
    } 
    updateContent(); 
    }); 
} 

jsFiddle here。あなたがそのプロパティにバインドされた値は、ディレクティブの前に利用可能であることを確認できない限り、あなたが唯一の安全、$watchコールバック内のスコープのプロパティにアクセスすることができますので、私は、リンク機能からupdateContentの呼び出しを削除した

お知らせAngularによって処理されます。

$observeは、補間を含むDOM属性(たとえば、value="{{ value }}")の値の変化を観測/監視するためにのみ使用してください。より良く理解するには、SO questionをチェックしてください。

+0

マイケルです:答えてくれてありがとうそんなに。間違いなく今は正しく動作します。私は 'scope.activate = 0'をどのように使用するのかが以前は分かりませんでした。私はまだ同じ属性の値を変更しています。 – Justin

+0

私はより多くの情報で答えを更新します。うまくいけば、それは物事をクリアするでしょう。 –

関連する問題