0

Ich möchte den orderBy Filter mit der ng-repeat-Direktive beim Iterieren über eine Objekteigenschaften verwenden. Da der orderBy-Filter nur mit Array funktioniert, schlägt der Angular doc vor, den toArray Filter zu verwenden.Warum verwendet ToArray Filter mit ng-repeat und ein Objekt von Strings eine unendliche Digest-Schleife?

Der toArray Filter wirkt wie ein Zauber mit Objekt-Eigenschaften wie:

var obj = { 
    a: { name: 'A' }, 
    b: { name: 'B' }, 
    c: { name: 'C' } 
}; 

Aber es verursacht eine Endlosschleife verdauen, wenn sie mit Nicht-Objekteigenschaften verwendet:

var obj = { 
    a: 'A', 
    b: 'B', 
    c: 'C' 
}; 

Hier wird eine plunker, die das Problem veranschaulicht.

Antwort

1

Sie sollten das sowieso nicht machen, Filter sind in der Regel eine schlechte Idee, wenn Sie Daten umwandeln, weil sie jedes Mal neu berechnet werden, wenn der Digest-Zyklus eine Schleife macht. Ihr Plumer funktioniert nicht, daher ist es schwer zu sagen, warum, aber wenn ich Code betrachte, würde ich sagen, dass er mit jeder Digest-Schleife ein völlig neues Array erstellt und im Falle von Objekten $ key-Eigenschaft hinzufügt, was den Digest-Zyklus stoppt. Eine Eigenschaft kann Strings nicht hinzugefügt werden. Aber da bin ich mir nicht sicher.

Edit: wenn Sie console.log zu toArray hinzufügen:

return Object.keys(obj).map(function (key) { 
     var value = obj[key]; 

     console.log(key, value); 

     return angular.isObject(value) ? 
      Object.defineProperty(value, '$key', { enumerable: false, value: key}) : 
      { $key: key, $value: value }; 
     }); 

In meldet Sie Antwort auf Ihre Frage finden können:

VM596 angular-toArrayFilter.js:15 b b 
VM596 angular-toArrayFilter.js:15 a a 
VM596 angular-toArrayFilter.js:15 c Object {p: "c"} 
VM596 angular-toArrayFilter.js:15 b Object {p: "b"} 
VM596 angular-toArrayFilter.js:15 a Object {p: "a"} 
VM596 angular-toArrayFilter.js:15 c Object {p: "c", $key: "c"} 
VM596 angular-toArrayFilter.js:15 b Object {p: "b", $key: "b"} 
VM596 angular-toArrayFilter.js:15 a Object {p: "a", $key: "a"} 
VM596 angular-toArrayFilter.js:15 c c 
VM596 angular-toArrayFilter.js:15 b b 
VM596 angular-toArrayFilter.js:15 a a 
VM596 angular-toArrayFilter.js:15 c Object {p: "c", $$hashKey: "object:11", $key: "c"} 
VM596 angular-toArrayFilter.js:15 b Object {p: "b", $$hashKey: "object:10", $key: "b"} 
VM596 angular-toArrayFilter.js:15 a Object {p: "a", $$hashKey: "object:9", $key: "a"} 

Bei Objekten, Winkel die gleichen Objekte verwendet und schafft keine neuen. Damit kann davon ausgegangen werden, dass sich das Array nicht geändert hat und den Digest-Zyklus beendet hat. Im Falle von String-Werten erzeugt es jedes Mal neue Objekte, wenn das Filter ausgeführt wird, so dass es jedes Mal, wenn ein anderes Array erstellt wird, davon ausgeht, dass es den Digest-Zyklus nicht beenden kann.

+0

Vielen Dank für Ihre Antwort @sielakos. Mein Plünderer hat seinen Zweck verfehlt, um das fehlgeschlagene Verhalten hervorzuheben, ich habe es mit dem Arbeitsfall aktualisiert, um die Dinge klarer zu machen. – Mic

+0

Über Ihren zweiten Punkt @sielakos, wenn die Objekteigenschaften, die iteriert werden, keine Objekte sind, ersetzt der Filter das Nicht-Objekt durch ein neues Objekt der Form: {$ key: key, $ value: value}. Sie sagen, dass es eine schlechte Idee ist, einen Filter in diesem Fall zu verwenden, aber das Angular Doc schlägt explizit den toArrayFilter vor, wenn wir orderBy verwenden müssen, wenn wir ng-repeat und ein Objekt verwenden. Welche Alternative schlagen Sie vor? – Mic

+0

Transformieren Sie Ihre Daten in Controller/Service auf diese Weise müssen Sie nicht sehr viel Zeit Digest Zyklusläufe zu transformieren, werden Sie das nur einmal tun. Außerdem können Sie Probleme mit dem unendlichen Digest-Zyklus vermeiden. – sielakos