Check duplicate using ko.observableArray

2019-07-31 01:31发布

问题:

How can I check the duplicate signatures before adding. In the below scenario, I wanted add signature if no signature found the list.

    var Signature = function (name, interestDeclared) {
        this.Name = ko.observable(name);
       this.RelevantInterest = ko.observable(interestDeclared);
    } 

   viewModel = {

    signatures: ko.observableArray([]),

    addSignature: function () {
        var name = $('#signatureName').val();
        var intd = $('#interest').is(':checked');

        this.signatures.push(new Signature(name, intd));

    },
    deleteSignature: function (signature) {
        this.signatures.remove(signature);
     },

    insertWitness: function (signature, position) {
        this.signatures.splice(position, 0, signature);
      }
};

ko.applyBindings(viewModel, document.getElementById("signatories"));

Thanks, -Naren

回答1:

Using jQuery's grep function:

addSignature: function () {
    var name = $('#signatureName').val();
    var intd = $('#interest').is(':checked');
    if($.grep(this.signatures(), function(el){return el.Name() === name;}).length === 0){
        this.signatures.push(new Signature(name, intd));
    }
}


回答2:

You could also use some built in utility functions in the KO framework. I've solved this problem with this technique in the past:

var name = $('#signatureName').val(),
    intd = $('#interest').is(':checked'),
    match = ko.utils.arrayFirst(this.signatures(), function (item) {
    if (item.Name() === name) {
         return selectedCounsel;
    }
});

if (!match) {
    // This means it wasn't already in our array, so we'll add it.
    this.signatures.push(new Signature(name, intd));
}

I also agree with @madcapnmckay, don't use jQuery to find the values from input, update your model so that signatureName and interest are bound to your model and use those values.



回答3:

You can use a array utility function like this.

if (!Array.prototype.findIndexOf) {
    Array.prototype.findIndexOf = function (search) {
        var len = this.length, i, item;
        if (typeof search != "function") {
            throw new TypeError();
        }

        for (i = 0; i < len; i += 1) {
            item = this[i];
            if (search.apply(this, [item])) {
                return i;
            }
        }
        return -1;
    };
}

Then update your addSignature method like so.

addSignature: function () {
   var name = $('#signatureName').val();
   var intd = $('#interest').is(':checked');

   var found = this.signatures().findIndexOf(function(s) { return s.Name() === name; });
   if (found == -1) {
      this.signatures.push(new Signature(name, intd));
   }
}

Here's a great resource for all things js array related.

FYI. You shouldn't be getting the name/interest values via a jquery selector. Instead use KO's value/checked bindings respectively to bind the value to your viewModel. That way your addSignature method can be completely decoupled from the markup.

Hope this helps.