JSFiddle - React, Tailwind, and code Playground
by idavidcastellanos
HTML
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout-validation/1.0.2/knockout.validation.min.js"></script>
<table data-bind="visible: jointholders().length > 0">
<thead>
<tr>
<th>Title</th>
<th>Other title</th>
<th>Forename</th>
<th>Surname</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: jointholders">
<tr>
<td>
<select data-bind="options: $parent.titles, value: title, optionsText: 'title', optionsValue: 'title', optionsCaption: 'Select...'"></select></td>
<td>
<input type="text" data-bind="enable: title() === 'Other', value: otherTitle, valueUpdate: 'afterkeydown'" /></td>
<td>
<input type="text" data-bind="value: forename, valueUpdate: 'afterkeydown', validationElement: forename" />
</td>
<td>
<input type="text" data-bind="value: surname, valueUpdate: 'afterkeydown'" /></td>
<td>
<button data-bind="click: $parent.removeJointHolder">Remove</button></td>
</tr>
</tbody>
</table>
<pre name="taJointHolders" style="width: 50%" rows="5" data-bind="text: ko.toJSON(jointholders)"></pre><br />
<button data-bind="click: addJointHolder, enable: jointholders().length < 5">Add Joint Holder</button>
<div data-bind="foreach:AllErrors">
JointHolder:
<div data-bind="foreach:Errors">
<span data-bind="text:Property" ></span>:
<span data-bind="text:Error" ></span><br />
</div>
</div>
<script type="text/html" id="vmTemplate">
<span class="alert" data-bind="if: field.isModified() && !field.isValid(),
attr: { title: field.error }">*</span>
</script>
CSS
.alert {
color: red;
}
JavaScript
$(function () {
var my = my || {};
my.JointHolder = function () {
var self = this;
self.title = ko.observable(null).extend({
required: {message: 'This is a required field.'}
});
self.otherTitle = ko.observable(null).extend({
required: {
onlyIf: function () {
return self.title() == "Other";
},
message: 'This is a required field.'
},
maxLength: 20,
pattern: {
message: 'This field must only contain letters and numbers.',
params: '^[a-zA-Z0-9]+$'
}
});
self.forename = ko.observable(null).extend({
required: true,
maxLength: 70,
pattern: {
message: 'This field must only contain letters and numbers.',
params: '^[a-zA-Z0-9]+$'
}
});
self.surname = ko.observable(null).extend({
required: true,
maxLength: 40,
pattern: {
message: 'This field must only contain letters and numbers.',
params: '^[a-zA-Z0-9]+$'
}
});
self.Errors = ko.computed(function() {
var errs = [];
for(var p in self) {
if(self.hasOwnProperty(p)) {
var pObj = self[p];
console.info("validating");
if(!!!ko.validation.utils.isValidatable(self[p])) {
console.info("ope, nvm");
} else {
if(!ko.validation.validateObservable(pObj)) {
...