¿Cómo empujar condicionalmente un elemento en una matriz observable?

103

Me gustaría colocar pushun nuevo artículo en un observableArray, pero solo si el artículo aún no está presente. ¿Existe alguna función de "búsqueda" o patrón recomendado para lograr esto en KnockoutJS?

He notado que la removefunción en un observableArraypuede recibir una función para pasar una condición. Casi quiero la misma funcionalidad, pero solo presionarla si la condición pasada es verdadera o no.

jaffa
fuente

Respuestas:

223

Un observableArray expone una indexOffunción (envoltorio a ko.utils.arrayIndexOf). Esto le permite hacer:

if (myObservableArray.indexOf(itemToAdd) < 0) {
  myObservableArray.push(itemToAdd);
}

Si los dos no son en realidad una referencia al mismo objeto y desea ejecutar una lógica de comparación personalizada, puede usar ko.utils.arrayFirstcomo:

var match = ko.utils.arrayFirst(myObservableArray(), function(item) {
    return itemToAdd.id === item.id;
});

if (!match) {
  myObservableArray.push(itemToAdd);
}
RP Niemeyer
fuente
¿Esto hace una comparación de todas las propiedades en itemToAdd? Solo necesito probar una propiedad de identificación.
Jaffa
5
Esto comprobará que los dos sean exactamente el mismo objeto. Si necesita verificar propiedades individuales, puede usar ko.utils.arrayFirst. Agregaré una muestra a la respuesta.
RP Niemeyer
4
Excelente consejo, pero tuve que cambiar itemToAdd.id === item.id a itemToAdd.id () === item.id (). Publiqué mi código en la siguiente respuesta.
Rake36
1
@ Rake36 esto dependería de si cree que la identificación de su artículo alguna vez cambiará y debe ser observable.
Louis
1
@spaceman: ¿qué problema tienes ===? Tienes una muestra? ¿Estás comparando cadenas con números o algo así?
RP Niemeyer
11

Gracias RP. Aquí hay un ejemplo del uso de su sugerencia para devolver la propiedad 'nombre' a través de la propiedad 'id' del objeto desde mi modelo de vista.

    self.jobroles = ko.observableArray([]);

    self.jobroleName = function (id)
    {
        var match = ko.utils.arrayFirst(self.jobroles(), function (item)
        {
            return item.id() === id();  //note the ()
        });
        if (!match)
            return 'error';
        else
            return match.name;
    };

En HTML, tengo lo siguiente ($ parent se debe a que está dentro de un bucle de fila de tabla):

<select data-bind="visible: editing, hasfocus: editing, options: $parent.jobroles, optionsText: 'name', optionsValue: 'id', value: jobroleId, optionsCaption: '-- Select --'">
                            </select>
<span data-bind="visible: !editing(), text: $parent.jobroleName(jobroleId), click: edit"></span></td>
Rake36
fuente
0

buscar un objeto en un ko.observableArray

function data(id,val) 
{ var self = this;
self.id = ko.observable(id);
self.valuee = ko.observable(val);  }

var o1=new data(1,"kamran");
var o2=new data(2,"paul");
var o3=new data(3,"dave");
var mysel=ko.observable();
var combo = ko.observableArray();

combo.push(o1);
combo.push(o2);
combo.push(o3);
function find()
 { 
      var ide=document.getElementById("vid").value;    
      findandset(Number(ide),mysel);
 }

function indx()
{
    var x=document.getElementById("kam").selectedIndex;
    alert(x);
}

function getsel()
{ 
    alert(mysel().valuee());
}


function findandset(id,selected)
 {  
    var obj = ko.utils.arrayFirst(combo(), function(item) {
    return  id=== item.id();
});   
     selected(obj);
 }

findandset(1,mysel);
ko.applyBindings(combo);


<select id="kam" data-bind="options: combo,
                   optionsText: 'valuee', 
                   value: mysel, 
                   optionsCaption: 'select a value'">

                   </select>
<span data-bind="text: mysel().valuee"></span>
<button onclick="getsel()">Selected</button>
<button onclick="indx">Sel Index</button>
<input id="vid" />
<button onclick="find()">Set by id</button>

http://jsfiddle.net/rathore_gee/Y4wcJ/

Kamran
fuente
0

Agregaría "valueWillMutate ()" antes de los cambios y "valueHasMutated ()" después de ellos.

for (var i = 0; i < data.length; i++) {
    var needChange = false;
    var itemToAdd = data[i];
    var match = ko.utils.arrayFirst(MyArray(), function (item) {
        return (itemToAdd.Code === item.Code);
    });
    if (!match && !needChange) {
        MyArray.valueWillMutate();
        needChange = true;
    }
    if (!match) {
        MyArray.push(itemToAdd);
    }
}
if (needChange) {
    MyArray.valueHasMutated();
}
Pavel Babiy
fuente