Knockout Unique Name Validation
Awesome validataor that checks whether an array element has duplicate values
by Dejan Vasic
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout-validation/1.0.2/knockout.validation.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>
<div data-bind="foreach: items">
<input type="text" data-bind="value: word" />
<br />
</div>
JavaScript
var listItemVm = function (data) {
var self = this;
self.parent = data.parent;
self.word = ko.observable(data.word).extend({
validation: {
validator: function (name, params) {
console.log("validating " + name);
//return true; // uncommenting this line causes the behaviour I expect
// word we are editing must be different from all other words
var allWords = params.parent.items.peek();
// exclude current view model we are editing
var otherWordViewModels = _.filter(allWords, function (row) {
return row !== params.currentRow;
});
var otherWords = _.map(otherWordViewModels, function (item) {
return item.word.peek();
});
return !_.contains(otherWords, name);
},
message: 'Must be unique',
params: {
currentRow: self,
parent: self.parent
}
}
});
};
var vm = function (data) {
var self = this;
self.items = ko.observableArray();
_.each(data.words, function (word) {
self.items.push(new listItemVm({parent: self, word: word.word}));
});
};
var data = {
words: [
{ word: "hello" },
{ word: "world" },
]
};
ko.applyBindings(new vm(data));