javascript - examples - Suscribirse a la matriz observable solo para entradas nuevas o eliminadas
que es map en javascript (6)
A partir de KnockoutJS 3.0, hay una opción de suscripción de arrayChange en ko.observableArray.
var myArray = ko.observableArray(["Alpha", "Beta", "Gamma"]);
myArray.subscribe(function(changes) {
// For this example, we''ll just print out the change info
console.log(changes);
}, null, "arrayChange");
myArray.push("newitem!");
En la devolución de llamada anterior, el argumento de cambios será una matriz de objetos de cambio como este:
[
{
index: 3,
status: ''added'',
value: ''newitem!''
}
]
Para su problema específico, quiere recibir notificaciones sobre artículos nuevos o eliminados . Para implementar eso usando Knockout 3, se vería así:
myArray.subscribe(function(changes) {
changes.forEach(function(change) {
if (change.status === ''added'' || change.status === ''deleted'') {
console.log("Added or removed! The added/removed element is:", change.value);
}
});
}, null, "arrayChange");
Entonces sí, puedo suscribirme a una matriz observable:
vm.myArray = ko.observableArray();
vm.myArray.subscribe(function(newVal){...});
El problema es que la newVal
pasada a la función es toda la matriz. ¿De todos modos puedo obtener solo la parte delta? ¿Dice el elemento agregado o eliminado ?
Como no pude encontrar ninguna información sobre esto en otro lugar, agregaré una respuesta sobre cómo usar esto con TypeScript.
La clave aquí fue utilizar la interfaz KnockoutArrayChange como TEvent para suscribirse. Si no lo hace, intentará utilizar la otra suscripción (no genérica) y se quejará de que el estado, el índice y el valor no existen.
class ZoneDefinition {
Name: KnockoutObservable<String>;
}
class DefinitionContainer
{
ZoneDefinitions: KnockoutObservableArray<ZoneDefinition>;
constructor(zoneDefinitions?: ZoneDefinition[]){
this.ZoneDefinitions = ko.observableArray(zoneDefinitions);
// you''ll get an error if you don''t use the generic version of subscribe
// and you need to use the KnockoutArrayChange<T> interface as T
this.ZoneDefinitions.subscribe<KnockoutArrayChange<ZoneDefinition>[]>(function (changes) {
changes.forEach(function (change) {
if (change.status === ''added'') {
// do something with the added value
// can use change.value to get the added item
// or change.index to get the index of where it was added
} else if (change.status === ''deleted'') {
// do something with the deleted value
// can use change.value to get the deleted item
// or change.index to get the index of where it was before deletion
}
});
}, null, "arrayChange");
}
Estoy usando un enfoque similar pero diferente, realice un seguimiento de si un elemento ha sido instrumentado en el elemento en sí:
myArray.subscribe(function(array){
$.each(array, function(id, el) {
if (!el.instrumented) {
el.instrumented = true;
el.displayName = ko.computed(function(){
var fn = $.trim(el.firstName()), ln = $.trim(el.lastName());
if (fn || ln) {
return fn ? (fn + (ln ? " " + ln : "")) : ln;
} else {
return el.email();
}
})
}
});
})
Pero es realmente tedioso y el patrón se repite en mi código
Ninguno que yo sepa ¿Quieres saber lo que hago? Uso una variable anterior para mantener el valor, algo llamado selectedItem
vm.selectedItem = ko.observable({});
function addToArray(item) { vm.selectedItem(item); vm.myArray.push(item); }
Entonces, cuando algo le sucede a mi matriz observable, sé qué elemento se agregó.
vm.myArray.subscribe(function(newArray) { var addedItem = vm.selectedItem(item); ... }
Esto es realmente detallado, y suponiendo que su matriz contiene muchos tipos de datos, necesitaría tener algún tipo de indicador que lo ayude a saber qué hacer con sus variables guardadas ...
vm.myArray.subscribe(function(newArray) {
if ( wasUpdated )
// do something with selectedItem
else
// do whatever you whenever your array is updated
}
Una cosa importante de notar es que usted puede saber qué elemento se agregó si sabe si se utilizó push
o unshift
. Simplemente busque el último elemento de la matriz o el primero y listo.
Para detectar solo los eventos push()
y remove()
, y no mover elementos, pongo un envoltorio alrededor de estas funciones de matriz observables.
var trackPush = function(array) {
var push = array.push;
return function() {
console.log(arguments[0]);
push.apply(this,arguments);
}
}
var list = ko.observableArray();
list.push = trackPush(list);
La función de inserción original se almacena en un cierre, luego se superpone con un envoltorio que me permite hacer todo lo que quiero con el elemento empujado antes o después de que se inserta en el arreglo.
Patrón similar para remove()
.
Pruebe vm.myArray().arrayChanged.subscribe(function(eventArgs))
Eso tiene el valor agregado cuando se agrega un artículo, y el valor eliminado cuando se elimina un elemento.