Knockout-Contrib / Knockout-Contrib/Knockout-Validation
isValid reporting incorrectly when bound inside ko.foreach
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 1k
- Forks
- 366
- PR merge metrics
- No merged PRs in 30d
Description
When using knockout.validation the isValid property will incorrectly report its status but only when it is "inside" a ko.foreach.
Using the code snippet below, if you run and enter the following values (q,z,10) in the same textbox,you will get the following output:
- self.InvoiceAmount is q and self.InvoiceAmount.isValid is true
- self.InvoiceAmount is z and self.InvoiceAmount.isValid is false
- self.InvoiceAmount is 10 and self.InvoiceAmount.isValid is false
As you can see, the validation rule is for a number and q should not report true as well as 10 should not report false.
It appears the order of execution is messed up because InvoiceAmount.subcribe is executed prior to InvoiceAmount.isValid.subscribe.
When the view model is just a simple property, the results are as expected:
- self.item is q and self.item.isValid is false
- self.item is z and self.item.isValid is false
- self.item is 10 and self.item.isValid is true
ko.bindingHandlers.numeral = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = ko.utils.unwrapObservable(valueAccessor()),
format = ko.utils.unwrapObservable(allBindingsAccessor().format) || ko.bindingHandlers.numeral.defaultFormat,
formattedValue = Number(value) ? numeral(value).format(format) : value;
$(element).val(formattedValue);
},
defaultFormat: "0,0.00"
};
var viewModel = function(param) {
var self = this;
self.item = ko.observable().extend({ number: true });
self.item.subscribe(function(value) {
$("#log").append("<p>self.item is " + value + " and self.item.isValid is " + self.item.isValid() + "</p>");
});
self.items = ko.mapping.fromJS([]);
ko.mapping.fromJS(param, {
key: function(data) {
return data.CustomerId;
},
create: function(options) {
return new itemViewModel(options.data);
}
}, self.items);
};
var itemViewModel = function(item) {
var self = this;
ko.mapping.fromJS(item, {}, self);
self.InvoiceAmount.extend({ number: true });
self.InvoiceAmount.subscribe(function(value) {
$("#log").append("<p>self.InvoiceAmount is " + value + " and self.InvoiceAmount.isValid is " + self.InvoiceAmount.isValid() + "</p>");
});
}
$(function() {
var vm = new viewModel([{ "InvoiceAmount": 10 }, { "InvoiceAmount": 20 }, { "InvoiceAmount": 30 }, { "InvoiceAmount": 40 }]);
ko.applyBindings(vm);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/numeral.js/1.5.3/numeral.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.3/knockout.validation.js"></script>
<div>
single item:<br/>
<input type="text" data-bind="numeral: item"/>
</div>
<div>
foreach:<br/>
<table>
<tbody data-bind="foreach: items">
<tr>
<td><input type="text" data-bind="numeral: InvoiceAmount"/></td>
</tr>
</tbody>
</table>
</div>
<div id="log"></div>
I also submitted this to stack overflow hoping someone could help me out and there is a working snippet:
Thanks!
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the supplied JavaScript and HTML reproduction, comparing the standalone item with InvoiceAmount inside ko.foreach. Trace the order of InvoiceAmount and isValid subscriptions while entering q, z, and 10. Done means the validation state matches the number rule in both cases and the regression is covered by a reproducible test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100