javascript - index - ng-repeat group by
¿Qué es "track by" en AngularJS y cómo funciona? (3)
Realmente no entiendo cómo funciona la track by
y lo que hace.
Mi objetivo principal es usarlo con ng-repeat
para agregar algo de precisión.
Usando track by
para rastrear cadenas y valores duplicados
Normalmente ng-repeat
rastrea cada elemento por el propio elemento. Para la matriz dada objs = [ ''one'', ''one'', 2, ''five'', ''string'', ''foo'']
, ng-repeat
intenta hacer un seguimiento de los cambios realizados por cada objeto en ng-repeat="obj in objs"
. El problema es que tenemos valores duplicados y angular arrojará un error. Una forma de resolverlo es tener un seguimiento angular de los objetos por otros medios. Para cadenas, track by $index
es una buena solución ya que realmente no tiene otros medios para rastrear una cadena.
track by
y activando un resumen y los enfoques de entrada
Usted alude al hecho de que es algo nuevo para angular. Un ciclo de digestión se produce cuando angular realiza una comprobación exhaustiva de cada propiedad observada para reflejar cualquier cambio en la vista correspondiente; A menudo, durante un ciclo de resumen, sucede que su código modifica otras propiedades observadas, por lo que el procedimiento debe realizarse nuevamente hasta que el ángulo no detecte más cambios.
Por ejemplo: hace clic en un botón para actualizar un modelo mediante ng-click
, luego hace algunas cosas (es decir, las cosas que escribió en la devolución de llamada para realizar cuando un usuario hace clic), y luego el ciclo de resumen del disparador angular para actualizar la vista. No soy muy elocuente para explicar eso, así que deberías investigar más si eso no aclara las cosas.
Así que volvemos a la track by
. Vamos a usar un ejemplo:
- llamar a un servicio para devolver una matriz de objetos
- actualizar un objeto dentro de la matriz y guardar objeto
- después de guardar el servicio, dependiendo de lo que devuelva la API, puede:
- reemplazar todo el objeto o
- actualizar un valor en el objeto existente
- reflejar el cambio en la interfaz de usuario de
ng-repeat
La forma en que rastree este objeto determinará cómo la interfaz de usuario refleja el cambio.
Una de las UX más molestas que he experimentado es esta. Supongamos que tiene una tabla de objetos, cada celda tiene una entrada donde desea editar en línea las propiedades de esos objetos. Quiero cambiar el valor, luego on-blur
, guardar ese objeto mientras me muevo a la siguiente celda para editar mientras podría estar esperando la respuesta. Así que esto es una cosa del tipo de autoguardado. Dependiendo de cómo configure su track by
declaración, puede perder el enfoque actual (por ejemplo, el campo que está editando actualmente) cuando la respuesta se vuelve a escribir en su matriz de objetos.
Cuando agrega una track by
, básicamente le dice a angular que genere un único elemento DOM por objeto de datos en la colección dada.
Puede track by $index
si su fuente de datos tiene identificadores duplicados.
Si necesita repetir elementos duplicados, puede sustituir el comportamiento de seguimiento predeterminado con el suyo utilizando la pista por expresión.
Ejemplo:
[{id:1,name:''one''}, {id:1,name:''one too''}, {id:2,name:''two''}]
Intente usar los valores duplicados en ng-repeat
, obtendrá un error como:
Error: ngRepeat: duplica la clave duplicada en el repetidor
Para evitar este tipo de problemas, debe utilizar track by $index
. Por ejemplo:
<ul>
<li ng-repeat="item in [1, 2, 3, 3] track by $index">
{{ item }}
</li>
</ul>
Aquí es cómo obtendría $index
en ng-repeat
anidada:
<div ng-repeat="row in matrix">
<div ng-repeat="column in row">
<span>outer: {{$parent.$index}} inner: {{$index}}</span>
</div>
</div>
Aquí hay algunos recursos que pueden ayudarte:
Solo debe usar track by
si necesita ir en contra del comportamiento predeterminado de ng-repeat
que es eliminar elementos duplicados.
Puede hacer un seguimiento de los elementos utilizando la propiedad de alcance $index
o especificando una función personalizada.
Por ejemplo:
<div ng-repeat="x in [42, 42, 43, 43] track by $index">
{{x}}
</div>
Mostrar todos los valores de la matriz (42 se muestra dos veces).
Para referencia: https://docs.angularjs.org/api/ng/directive/ngRepeat