Wie kann ein Element in einem beobachtbaren Array bedingt verschoben werden?


103

Ich möchte pusheinen neuen Artikel auf einen observableArray, aber nur wenn der Artikel noch nicht vorhanden ist. Gibt es eine "Such" -Funktion oder ein empfohlenes Muster, um dies in KnockoutJS zu erreichen?

Ich habe festgestellt, dass die removeFunktion auf einem observableArrayeine Funktion zum Übergeben einer Bedingung empfangen kann. Ich möchte fast die gleiche Funktionalität, aber nur, wenn die übergebene Bedingung wahr ist oder nicht.

Antworten:


223

Ein ObservableArray macht eine indexOfFunktion verfügbar (Wrapper für ko.utils.arrayIndexOf). Dies ermöglicht Ihnen Folgendes:

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

Wenn die beiden nicht tatsächlich auf dasselbe Objekt verweisen und Sie eine benutzerdefinierte Vergleichslogik ausführen möchten, können Sie Folgendes verwenden ko.utils.arrayFirst:

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

if (!match) {
  myObservableArray.push(itemToAdd);
}

Führt dies einen Vergleich aller Eigenschaften von itemToAdd durch? Ich muss nur auf eine ID-Eigenschaft testen.
Jaffa

5
Dadurch wird überprüft, ob es sich bei beiden um genau dasselbe Objekt handelt. Wenn Sie nach einzelnen Eigenschaften suchen müssen, können Sie verwenden ko.utils.arrayFirst. Ich werde der Antwort ein Beispiel hinzufügen.
RP Niemeyer

4
Ausgezeichneter Tipp, aber ich musste itemToAdd.id === item.id in itemToAdd.id () === item.id () ändern. Ich habe meinen Code in der nächsten Antwort gepostet.
Rake36

1
@ Rake36 Dies hängt davon ab, ob Sie glauben, dass sich Ihre Artikel-IDs jemals ändern werden und beobachtbar sein müssen.
Louis

1
@spaceman - welches Problem hast du ===? Hast du eine Probe? Vergleichen Sie Zeichenfolgen mit Zahlen oder so?
RP Niemeyer

11

Danke RP. Hier ist ein Beispiel für die Verwendung Ihres Vorschlags, um die Eigenschaft 'name' über die Eigenschaft 'id' des Objekts aus meinem Ansichtsmodell zurückzugeben.

    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;
    };

In HTML habe ich Folgendes ($ parent ist darauf zurückzuführen, dass es sich in einer Tabellenzeilenschleife befindet):

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

0

Suchen Sie ein Objekt in einem 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/


0

Ich würde "valueWillMutate ()" vor Änderungen und "valueHasMutated ()" nach ihnen hinzufügen.

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();
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.