Reputation: 325
I'm building a mechanism to automatically display validation messages in a form field and would like to discuss about this.
I have an observable array with the error message and its respective properties.
How can I bind an element of the observable array to its respective form field?
The observable has the following data (i.e):
messages = ko.observableArray();
- Property: Reference, Message: Already exists a product with this reference.
- Property: Name, Message: The product's name is mandatory.
- Property: Bar Code, Message: The Bars Code does not matches the EAN13 format.
- ...
My form fields' IDs have the same names of the properties in the array:
<div class="s13">
<label for="Reference">Reference</label>
<input class="text-box single-line" id="Reference" name="Reference" type="text" value="" data-bind="value: selected().Reference" />
<span id="vReference"></span>
</div>
<div class="s13">
<label for="Name">Name</label>
<input class="text-box single-line" id="Name" name="Name" type="text" value="" data-bind="value: selected().Name" />
<span id="vName"></span>
</div>
<div class="s13">
<label for="BarCode">Bars Code (EAN13)</label>
<input class="text-box single-line" id="BarCode" name="BarCode" type="text" value="" data-bind="value: selected().BarCode" />
<span id="vBarCode"></span>
</div>
I'm very new to Knockout.js but I think that I'll need to use a ´computed observable´, which returns the respective message for each span.
What you say?
/// UPDATE ////////////////////////////////////////////////////
The Products View Model:
function mainmodel(baseUri) {
var m = this;
m.baseUri = baseUri;
/// PRODUCTS VIEW MODEL ******************************************* *
m.products = new function () {
var p = this;
p.baseUri = baseUri;
p.items = ko.observableArray();
p.selected = ko.observable();
p.messages = ko.observableArray([]);
The Products Loading
/// LIST
p.list = function () {
$.getJSON(p.baseUri + "/list" + "?page=" + p.currentpage(), p.items);
}
The Product Creation (where the validation messages are loaded)
/// CREATE
p.create = function (formElement) {
//$.post(p.baseUri + "/create", $(formElement).serialize(), null, "json")
$.ajax({
type: 'POST',
url: p.baseUri + "/create",
data: $(formElement).serialize(),
success: null,
dataType: "json",
statusCode: {
400: function (o) {
p.messages($.parseJSON(o.responseText));
}
}
});
}
Running this, p.messages contains validation messages for each of the product's properties.
Upvotes: 1
Views: 278
Reputation: 114792
I think that there are a couple of approaches that you could use for this one. If you are receiving these validation messages back from a request to the server, then you could loop through them and populate observables directly based on the results.
A nice way to do this is to create a "sub" observable to hold the validation message like:
this.myObservable = ko.observable();
this.myObservable.validationMessage = ko.observable();
Now you can bind against myObservable
and myObservable.validationMessage
.
So, if you received an array of messages back you could loop through them and apply the messages like:
var messages = [
{ Property: "Reference", Message: "Can't find a reference to this reference" },
{ Property: "Name", Message: "Pick a better name" },
{ Property: "BarCode", Message: "Not a valid code" }
];
//apply messages to each observable
ko.utils.arrayForEach(messages, function(message) {
if (ko.isObservable(self[message.Property])) {
self[message.Property].error(message.Message);
}
});
I don't know your application flow, but you might want to clear the errors first.
Here is a sample: http://jsfiddle.net/rniemeyer/mk2Ed/
Here is an alternate that uses computed observables (the first would be slightly more efficient): http://jsfiddle.net/rniemeyer/R6mL8/
Upvotes: 0