ko-Validation "onlyIf" frozen
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-debug.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.2/knockout.validation.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
<h4>
<ol>
<li>Click the "Edit/Add" button</li>
<li>Enter a value in a Serial Number column's field.</li>
<li>See wrong behaviour - the field in the Type column will be valid!</li>
</ol>
<div>The correct behaviour will be seen by clicking the "Edit / Add (Dirty Workaround!)" button</div>
</h4>
<div>
Why this stuff.<br/>
We should have subtle separate logic and validations for new added items/rows. (existing rows was omitted in this example.)
</div>
<hr/>
<table data-bind="visible: UnitGenerators().length"
class="responsive table table-striped">
<tr>
<th>Type</th>
<th>Serial Number</th>
</tr>
<!-- ko foreach: UnitGenerators -->
<!-- ko ifnot: $root.UnitsEditMode -->
<tr>
<td><span data-bind="text: type"></span></td>
<td><span data-bind="text: serial_number"></span></td>
</tr>
<!-- /ko -->
<!-- ko if: $root.UnitsEditMode -->
<tr>
<td><input data-bind="textInput: type" placeholder="Type" type="text" class="form-control"/></td>
<td><input data-bind="textInput: serial_number" placeholder="Serial Number" type="text" class="form-control"/></td>
</tr>
<!-- /ko -->
<!-- /ko -->
</table>
<hr/>
<table data-bind="visible: UnitCompressors().length"
class="responsive table table-striped">
<tr>
<th>Type</th>
<th>Serial Number</th>
</tr>
<!-- ko foreach: UnitCompressors -->
<!-- ko ifnot: $root.UnitsEditMode -->
<tr>
<td data-bind="text: type"></td>
<td class="innerTableHolder">
<table class="table innerTable">
<tr>
...
CSS
.validationElement {border-color: red; color: red;}
.validationMessage {color: red;}
JavaScript
var unitTypeId = {
generator : '1',
compressor: '2'
};
var equipmentViewModel = function () {
var self = this;
// States.
var validateObservableOptions = {deep: true, live: true};
var dependencyHint = ko.observable();
// Data. Units.
self.UnitGenerators = ko.observableArray([]);
self.UnitCompressors = ko.observableArray([]);
self.UnitsTracker = ko.observable(new ko.changeTracker({}));
self.UnitsEditMode = ko.observable(false);
var unitsEditCancelState;
var unitValidator;
// Utils.
var unitMapByCtor = function (rawObj) {
return new unitCtor(rawObj);
};
var unitsMap = function (units) {
return _.map(units, unitMapByCtor);
};
var unitsUpdate = function(obj){
if(obj){
self.UnitGenerators(unitsMap(obj.Generators));
self.UnitCompressors(unitsMap(obj.Compressors));
}else{
self.UnitGenerators([]);
self.UnitCompressors([]);
}
};
var unitLoad = function(){
// ... some AJAX ...
//.done(unitsUpdate);
unitsUpdate();
};
var unitsToJS = function () {
return {
Generators: ko.toJS(self.UnitGenerators),
Compressors: ko.toJS(self.UnitCompressors)
};
};
var unitOrNewChanged = function (el) {
if(el.newObjManager === undefined){
return true;
}
var changed = el.newObjManager.changed();
return changed;
};
// Objects.
var unitCtor = function (rawObj, equipmentUnitTypeId) {
var selfUnit = this;
var isNew = !rawObj;
var initing = true;
selfUnit.id = ko.observable(rawObj ? rawObj.id : '-1');
selfUnit.equipment_unit_type_id = ko.observable(rawObj ? rawObj.equipment_unit_type_id : equipmentUnitTypeId);
selfUnit.type = ko.observable(rawObj ? rawObj.type : '')
.extend({required: {onlyIf: function () {
//...