I have a scenario where a user enters different users with details. I have text boxes for different fields for each user. I need to let user save the details if at least one field must be filled by user rather than all the fields for each row. No row should be completely empty. Here is a fiddle i am trying
on save i just need to ask user to enter only one value per row.Instead of asking for all the fields required. http://jsfiddle.net/KHFn8/7161/
var NameModel = function(names) {
var self = this;
self.names = ko.observableArray(names);
self.addName = function() {
self.names.push(new xyz());
};
self.removeName = function(name) {
self.names.remove(name);
};
if (names != null)
self.names(names);
};
var xyz = function() {
var self = this;
self.FirstName = ko.observable().extend({
required: true
});
self.MiddleName = ko.observable().extend({
required: true
});
self.LastName = ko.observable().extend({
required: true
});
self.Gender = ko.observable().extend({
required: true
});
self.NameSuffix = ko.observable().extend({
required: true
});
};
ko.validation.init({
grouping: { deep: true, observable: true, live: true },
messagesOnModified: false
});
ViewModel = function() {
this.nameModel = new NameModel();
this.save = function() {
if (
this.errors().length == 0)
alert('Everything is valid, we can save!');
else if (
!this.nameModel.isValid())
alert('You must have at least one valid item ');
}
};
ko.applyBindings(new ViewModel());
<div data-bind="with: nameModel" class="panel-body">
<table class="table table-hover table-responsive">
<thead>
<tr>
<th>FirstName</th>
<th>MiddleName</th>
<th>LastName</th>
<th>Gender</th>
<th>NameSuffix</th>
</tr>
</thead>
<tbody data-bind="foreach: names">
<tr>
<td>
<input class="form-control" data-bind="value: FirstName" />
</td>
<td>
<input class="form-control" data-bind="value: MiddleName" />
</td>
<td>
<input class="form-control" data-bind="value: LastName" />
</td>
<td>
<input class="form-control" data-bind="value: Gender" />
</td>
<td>
<input class="form-control" data-bind="value: NameSuffix" />
</td>
<td style="vertical-align: inherit;"><a href="#" data-bind="click:$parent.removeName.bind($data)">Delete</a></td>
</tr>
</tbody>
</table>
<button class="btn btn-success btn-sm" data-bind="click: addName.bind($data)">Add Name</button>
</div>
<button id="saveButton" type="button" class="btn btn-primary btn-company pull-left" data-bind="click: save">
Save
<span class="glyphicon glyphicon-download-alt"> </span>
</button>
There are some user-contributed KO-validation rules here:
https://github.com/Knockout-Contrib/Knockout-Validation/wiki/User-Contributed-Rules
This includes a rule for 'requires One Of', which will do what you want. However, I found the latest version on that page to be a bit buggy so I used a version from a project a did a while ago and applied it to your fiddle. The result is here:
http://jsfiddle.net/4f8s93k4/1/
The plugin is at the top of the JS and looks like:
ko.validation.rules['requiresOneOf'] = {
getValue: function (o) {
return (typeof o === 'function' ? o() : o);
},
validator: function (val, fields) {
var self = this;
var result = false;
ko.utils.arrayForEach(fields, function (field) {
var val = self.getValue(field);
if (val) {
result = true;
}
});
return result;
},
message: 'You must fill in at least one of these fields'
};
Rather than apply it to every one of your observables, I applied it using a single validation message, just to reduce code a bit:
self.requiresOneValidation = ko.observable().extend({
requiresOneOf: [self.FirstName, self.MiddleName, self.LastName, self.Gender, self.NameSuffix]
})
This then appears in your HTML like this:
<tr>
<td colspan="6">
<span data-bind="validationMessage: requiresOneValidation"></span>
</td>
</tr>