2016-11-04 8 views
3

私は、AngularJS 1.5でコンポーネントライブラリを作成するためにディレクティブを使用しています。したがって、私の指示はスコープを分離する必要があります。AngularJSディレクティブがコールバックのスコープを更新しない

私のディレクティブの中にはコールバックがあるものがあるので、ディレクティブによって呼び出される関数を渡すことができます。しかし、そのコールバックがディレクティブによって呼び出されたとき、$ scope属性の変更が完全に更新されているとは思えません。ここで

は、この動作を示しPlunkerです:clickersCallbackが呼び出されたときに

<script> 
    var app = angular.module('myApp', []); 
    app.controller('Controller', ['$scope',function($scope) { 
     // initialize the value to something obvious 
     $scope.clickersValue = "BEFORE"; 

     // when this call back is called we would expect the value to be updated by updated by the directive 
     $scope.clickersCallback = function() { 
     //$scope.$apply(); // $apply is not allowed here 
     $scope.clickersValueRightAfterCall = $scope.clickersValue; 
     console.log("clickersCallback: scope.clickersValue", $scope.clickersValue); 
    }; 
    } 
]); 

app.directive('clicker', [function() { 
    return { 
    restrict: 'EA', 
    template: '<div ng-click="clicked()">click me!</div>', 
    controller: ['$scope', function($scope) { 
     $scope.clicked = function() { 
     console.log("you clicked me."); 
     $scope.newValue = 'VALID'; 
     $scope.myUpdate(); 
     } 
    }], 
    scope: { 
     "newValue": "=", 
     "myUpdate": "&" 
    } 
    }; 
}]); 
</script> 

だからclickersValue属性はまだ古い値を持っています。ここ http://embed.plnkr.co/Rg15FHtHgCDExxOYNwNa/

のようなコードが見えるものです。私は$ scopeを使ってみましたが、$ applyを適用しましたが、別の更新が起きたときには許可されません。私はまた、controller_bindを使ってみましたが、同じ効果がありました。

答えて

2

$timeoutの機能の中でclickersCallbackのコードを囲みます。

$timeout(function() { 
    $scope.clickersValueRightAfterCall = $scope.clickersValue; 
    console.log("clickersCallback: scope.clickersValue", $scope.clickersValue); 
}); 

Updated plunker

$タイムアウトが現在のサイクルの後、タイムアウト待ち、それは確実にこの方法があることがアンギュラ伝えますので、$タイムアウト「は既に進行中の$ダイジェスト」のようなエラーが発生しませんダイジェストサイクルの間に衝突が起こらず、$ timeoutの出力が新しい$ダイジェストサイクルで実行されることになります。 source

編集1: OPは以下の言ったように、ディレクティブの使用者が自分のコールバック関数内の任意の「特別な」コードを記述する必要はありません。

この動作を実現するために、コントローラからディレクティブに$タイムアウトを変更しました。

コントローラコールバック関数(変化なし):

$scope.clickersCallback = function() { 
    $scope.clickersValueRightAfterCall = $scope.clickersValue; 
    console.log("clickersCallback: scope.clickersValue", $scope.clickersValue); 
}; 

指令コード(ディレクティブでジェクト$タイムアウト):

$scope.clicked = function() { 
    console.log("you clicked me."); 
    $scope.newValue = 'VALID'; 
    $timeout(function() { 
     $scope.myUpdate(); 
    }); 
} 

Updated plunker

+1

ガブリエル、創造的なアプローチに感謝します。しかし、これには、ディレクティブのユーザーがコード内で特別なことを行う必要があります。私は実際に、ディクショナリユーザーがng-clickのように式を使用できる方法を探しています。しかし、私はまだあなたの提案に投票しました。 – Toddsden

+1

'$ timeout'の中に' $ scope.myUpdate(); 'を書くことができます。それはあなたが欲しいものですか? [plunker](https://embed.plnkr.co/4ZuiTsDL3KGUX9ZN1NH2/) –

+1

はい!それはまさに私が望んでいたものです!私はあなたの提案の後にそ​​れを試しましたが、何とか私のコードで間違っていたに違いないでしょう。答えとして投稿することができますので、私はそれに答えることができますか?十分にあなたに感謝することはできません、これは素晴らしいです。 – Toddsden

関連する問題