私は時々AngularJSを理解するのに深刻な問題を抱えています。だから私は私のコントローラのような基本的な配列を持っています
$scope.items = ["a","b","c"]
私は、テンプレートで項目配列ng-repeat = "item in items"をngRepeatingしています。これまでのところ非常にまっすぐです。 UXアクションを数回実行した後、新しいものをアレイにプッシュします。
$scope.items.Push("something");
そのため、50%の時間、新しい要素がビューに追加されます。しかし、残りの50%は何も起こりません。そして、それはとてもイライラするようなものです。 bc $ scope。$ apply()内でラップすると、「$ digest already in progress」エラーが発生しました。それを$ timeoutにラップすることも役に立ちません。
そして、Chrome拡張機能を使用して要素スコープを検査すると、新しいデータが存在し、$ scope.items値が正しいことがわかります。 DOMに。
ありがとう!
角度の50%の$digest
サイクルの外側でスコープを変更しています。
Anglejsからではないコールバックがある場合; (おそらくjquery)。 $apply
サイクルを強制するには、$digest
を呼び出す必要があります。ただし、$apply
サイクル中に$digest
を呼び出すことはできません。変更はすべて自動的に反映されるためです。
コールバックがangularからではなく、$apply
を呼び出す必要がある場合はいつかを知る必要があります。
あなたが知らないで学ぶことができない場合、ここにきちんとしたトリックがあります:
var applyFn = function () {
$scope.someProp = "123";
};
if ($scope.$$phase) { // most of the time it is "$digest"
applyFn();
} else {
$scope.$apply(applyFn);
}
UmurKontacıが指摘したように、ダイジェストサイクル以外でモデルを変更することもあります。ただし、この問題を回避して、適用/ダイジェストコンテキストにあるかどうかを検出しようとする代わりに、これが発生しないことを確認することをお勧めします。
この問題の主な原因は、関数がDOMイベントへの反応として呼び出されることです。例えば。
jQuery('.some-element').click(function() { seeminglyProblematicCode() })
これは、関数内ではなく、$ apply()が必要な場所です。そうしないと、コード全体に遅かれ早かれそのような区別が散らばってしまいます。このイベントハンドラーのコンテキストにスコープがあると仮定すると、次のように記述できます。
jQuery('.some-element').click(function() {
$scope.$apply(function() { seeminglyProblematicCode() })
})
ただし、注意が必要な注意事項が1つあります。コードからクリックイベントをトリガーすると、ダイジェストサイクルが既に進行しているという問題が発生します。これは、$ timeoutが必要な場所です。 この質問 への答えは、この問題を非常によくカバーしています。
私は同じ問題を抱えていましたが、私の修正は、ネストされたディレクティブでどのコントローラーが呼び出されているかを監視することでした。
# Parent Controller
app.controller 'storeController', ($scope, products) ->
$scope.cart = ["chicken", "pizza"]
$scope.addToCart = (item) ->
$scope.cart.Push item
# from service
products.get().then (items) ->
$scope.products = items
# Parent Directives
app.directive 'storeContainer', ($scope, config) ->
restrict: 'E'
templatUrl: 'store-container.html'
controller: 'storeController'
# Nested Directive
app.directive 'storeFront', ($scope, config) ->
restrict: 'E'
templatUrl: 'store-front.html'
controller: 'storeController'
# Parent Template templates/directives/store-container.html
<div ng-repeat="item in cart">{{ item }}</div>
<strore-front></store-front>
# Nested Template templates/directives/store-front.html
<ul ng-repeat="item in products">
<li ng-click"addToCart(item)">{{ item }}</li>
</ul>
ここでのバグは、ネストされたディレクティブがプロトタイプチェーン内に2番目のコントローラー(storeControllerの複製)を作成し、親テンプレートがアクセスできないことです。解決するには、ネストされたコントローラーを次のように記述します。
# Nested Directive
app.directive 'storeFront', ($scope, config) ->
restrict: 'E'
templatUrl: 'store-front.html'
継承チェーンを作成するより良い方法がありますが、これにより、AngularJSを学習している多くの人々の問題が解決されます。