2013-03-22 9 views
30

時々AngularJSを理解することに重大な問題があります。だから、私はアイテムの配列NG・リピート=「項目内の項目」の上に私のテンプレートでngRepeatingよAngularJSはリフレッシュしません。アレイの更新時に返されます

$scope.items = ["a","b","c"] 

のように私のコントローラでの基本的な配列を持っています。これまでのスーパーストレートフォワード。いくつかのUXアクションの後、私はいくつかの新しいものを私の配列にプッシュしたいと思います。

$scope.items.push("something"); 

したがって、時間の50%、新しい要素がビューに追加されます。しかし、他の50%、何も起こりません。そしてそれは超イライラのようなものです。 bcを$ scope内で折り返すと$ apply()、 "$ digest already in progress"というエラーが出ます。それを$ timeoutにラップすることも役に立ちません。

また、Chrome拡張機能を使用して要素の範囲を調べると、新しいデータがあり、$ scope.itemsの値が正しいことがわかります。しかし、その見方はDOMにそれを追加することを気にしていないだけです。

ありがとうございます!

+0

デモはhttp://jsfiddle.net/ –

+2

で作成できますかどうかはダイジェストサイクルに関係しています。配列の更新に使用するコードを投稿する必要があります。 –

+2

私もこの問題を抱えており、答えが大好きです! – Samuel

答えて

21

角度の範囲外で、角度の$digestサイクルの50%を変更しています。

anglejsからではないコールバックがある場合。 (posibbly jquery)。 $digestサイクルを強制するには、$applyに電話する必要があります。 しかし、あなたが行った変更はすべて自動的に反映されるため、$digestのサイクルでは$applyに電話をかけることはできません。

コールバックが角度から来ていないことを知る必要があります。$applyを呼び出す必要があります。

あなたが学ぶことができ知っているといないいない場合は、ここに巧妙なトリックです:

var applyFn = function() { 
    $scope.someProp = "123"; 
}; 
if ($scope.$$phase) { // most of the time it is "$digest" 
    applyFn(); 
} else { 
    $scope.$apply(applyFn); 
} 
+0

私は '$ scope。$$ phase'のチェックを避けるべきだと思います。これは内部変数であり、可能であれば、これらのコードに依存するべきではありません。最善の解決法は '$ apply'を既に使用していますが、' $ apply'がまだ進行中でないことが絶対に確かなところです。これがスコープを更新する可能性のあるコードを求めている理由です。 –

+0

コードを書くのは良い方法ではありませんが、私は同意します。それでも動作し、 '$$ phase'は非常に一貫性と信頼性があります。少なくとも、リリース間で変更できるという事実を除いて、あなたのコードは予期せず破損することはありません。 –

+0

です。私はすでにそれを実際に使ってきました。問題は、次のマイナーリリースで内部状態コントローラのためにこれが壊れるかどうかわかりません。 '$ apply'をしっかりと置く方がいいと思っています。 –

0

私は同じ問題を持っていた、と私の問題を修正する修正プログラムをコントローラがネストされたディレクティブで呼び出さされているかを見ていました。

# 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> 

ここでバグがネストされたディレクティブは、親テンプレートがアクセス権を持っていないプロトタイプチェーン(storeControllerの複製)における第二のコントローラを作成しています。そのようなネストされたコントローラ書き解決するには:

# Nested Directive 
app.directive 'storeFront', ($scope, config) -> 
    restrict: 'E' 
    templatUrl: 'store-front.html' 

が継承チェーンを作成するためのより良い方法がありますが、これはAngularJSを学ぶ多くの人々のための問題を解決します。

4

UmurKontacıによって指摘されているように、ダイジェストサイクルの外でモデルの変更を行うことがあります。しかし、この問題を回避し、適用/ダイジェスト・コンテキストにいるかどうかを検出しようとするのではなく、これが起こらないことを確認することをお勧めします。

この問題の主な原因は、関数がDOMイベントへの反応として呼び出されることです。例えば。

jQuery('.some-element').click(function() { seeminglyProblematicCode() }) 

これは、関数内ではなく、あなたの$ apply()が必要な場所です。それ以外の場合は、コード全体がこのような区別で早急に散在します。このイベントハンドラのコンテキスト内の余地があると仮定すると、あなたが書くことができます:あなたのコードからクリックイベントをトリガしたら、実行されます:

jQuery('.some-element').click(function() { 
    $scope.$apply(function() { seeminglyProblematicCode() }) 
}) 

はしかし、あなたが知っておく必要はあり警告が1つありますダイジェストサイクルがすでに進行中であるという問題に直面しています。ここで$タイムアウトが必要です。 this questionへの回答は、この問題を非常にうまくカバーしています。

関連する問題