Bagaimana cara mendorong item secara kondisional dalam array yang dapat diamati?

103

Saya ingin pushmenambahkan item baru observableArray, tetapi hanya jika item tersebut belum ada. Apakah ada fungsi "temukan" atau pola yang direkomendasikan untuk mencapai ini di KnockoutJS?

Saya perhatikan bahwa removefungsi pada observableArraydapat menerima fungsi untuk meneruskan suatu kondisi. Saya hampir menginginkan fungsionalitas yang sama, tetapi hanya mendorongnya jika kondisi yang diteruskan benar atau tidak.

jaffa
sumber

Jawaban:

223

Sebuah observableArray mengekspos sebuah indexOffungsi (pembungkus ke ko.utils.arrayIndexOf). Ini memungkinkan Anda untuk melakukan:

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

Jika keduanya sebenarnya bukan merupakan referensi ke objek yang sama dan Anda ingin menjalankan logika perbandingan kustom, Anda dapat menggunakan ko.utils.arrayFirstseperti:

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

if (!match) {
  myObservableArray.push(itemToAdd);
}
RP Niemeyer
sumber
Apakah ini melakukan perbandingan semua properti di itemToAdd? Saya hanya perlu menguji properti Id.
jaffa
5
Ini akan memeriksa bahwa keduanya adalah objek yang sama persis. Jika Anda perlu memeriksa properti individu, maka Anda dapat menggunakan ko.utils.arrayFirst. Saya akan menambahkan sampel ke jawabannya.
RP Niemeyer
4
Tip yang sangat bagus, tetapi saya harus mengubah itemToAdd.id === item.id menjadi itemToAdd.id () === item.id (). Saya memposting kode saya di jawaban berikutnya.
Rake36
1
@ Rake36 ini akan tergantung pada apakah menurut Anda id item Anda akan pernah berubah dan perlu diamati.
Louis
1
@spaceman - masalah apa yang Anda alami ===? Apakah Anda punya sampel? Apakah Anda membandingkan string dengan angka atau sesuatu?
RP Niemeyer
11

Terima kasih RP. Berikut adalah contoh penggunaan saran Anda untuk mengembalikan properti 'nama' melalui properti 'id' objek dari dalam model tampilan saya.

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

Dalam HTML, saya memiliki yang berikut ($ parent karena ini berada di dalam loop baris tabel):

<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>
Rake 36
sumber
0

mencari objek di 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
sumber
0

Saya akan menambahkan "valueWillMutate ()" sebelum perubahan dan "valueHasMutated ()" setelahnya.

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
sumber