0
votes

I've seen some similar questions asked on this subject, but none of them have really helped. I wanted to post this here first before opening a ticket on the GitHub project for the validation plugin in case this is a PEBKAC issue. :)

The issue is simple. I have an object that I populate from JSON and then attach validation to fields. The problem is that if I use the mapping plugin, the validationMessage binding breaks. However, if I explicitly declare every observable, it works fine. You can see a fiddle here. It's pretty self-explanatory, just check the console window when using the breaking code and you can see the error message.

Here are the basic bits of code. First, my Knockout code:

var data = {
    Name: 'test'
};

ko.validation.configure({
    registerExtenders: true,
    messagesOnModified: false,
    insertMessages: false,
    parseInputAttributes: false,
    messageTemplate: null
});

var ns = ns || {}; // namespace

ns.ViewModel = function () {
    var itemToBind = {},
        init = function (json) {
            // Uncomment to break;
            itemToBind = ko.mapping.fromJS(json, {}, itemToBind);

            // Uncomment to make it work
            //itemToBind.Name = ko.observable(json.Name);

            itemToBind.Name.extend({ required: { message: 'Required' } });
        };

    return {
        itemToBind: itemToBind,
        init: init
    };
}();

ns.ViewModel.init(data);
ko.applyBindings(ns.ViewModel);

And then my HTML:

<label>Name: </label>
<input type="text" data-bind="value: itemToBind.Name" />
<div class="validation-section">
    <strong>*</strong>
    <span data-bind="validationMessage: itemToBind.Name"></span>
</div>

I at first thought that my usage of the revealing module pattern was screwing things up somehow, but since it all works if I explicitly declare each observable, I threw that thought out the window.

I have seen some suggestions such as this answer about creating a validation mapping. This would be fine if my models only had a few fields, but some of my forms have upwards of 100 fields, so while that might work, it isn't feasible. And it would actually be less code to just declare each observable.

Hoping someone can either shed some light on a fix or at least confirm that this is a bug with the validation plugin, and then I can head to the GitHub project and work with the creator. Thanks.

1
Maybe I don't undarstand your problem, but in your fiddle if I delete test text the Required message does show up as it should... (using Chrome and FF) - nemesv
And y'know, I just noticed that as well and was doing some work with my production code and got pulled into a quick discussion. Gonna toy around with this and see if I inadvertently fixed something. :) Thanks. - James McConnell
Yup, I changed the mapping function. I had "ko.mapping.fromJS(itemToBind)" and changed it to "ko.mapping.fromJS(json, {}, itemToBind);" as I saw that in another example somewhere, and that seemed to fix it. So not a validation plugin issue, but how I was mapping. - James McConnell
James, it also works using this way of mapping, not sure if that helps any - using 'this' to reference the itemToBind: jsfiddle.net/jiggle/49MMS - John Lucas
Yeah, I eventually came around to that as well. Thanks for the info. :) - James McConnell

1 Answers

1
votes

Yeah, yeah, I know, you shouldn't answer your own question, but in case this comes up in a search for someone else, this is what I did to fix it. I initially had this to map my JSON:

ko.mapping.fromJS(json);

I happened to change this line to another way of mapping I saw somewhere else (not entirely sure why I changed it, TBH), and it started working:

ko.mapping.fromJS(json, {}, itemToBind)

I'm not sure why this works, I haven't had time to dig into the details of the different method calls, but this works. So if anyone else is having this issue, there ya go!