2
votes

I'm struggling with how to update my bound viewmodel from an ajax call whilst using a validatedObservable.

Previously I get the initial data from an ajax call and intially bound like this:

self.quote = ko.mapping.fromJS(result.data, self.quoteMapping);

ko.applyBindings(self);

and when a user changed something in the 'quote', I'd make another ajax call passing the changes and the return from the ajax call would be the complete 'quote' (and I do need to bring the whole 'quote', as a change to one item on the quote can server-side affect other items and also other properties in the top level which therefore need to be updated in the client-side view model) which I would update the bound view model with (using the other signature of fromJS), thusly:

ko.mapping.fromJS(result.data, self.quote);

However, now I want the view model to be a validatedObservable. For the inital load this is pretty straightforward:

self.quote = ko.validatedObservable(ko.mapping.fromJS(result.data, self.quoteMapping));

ko.applyBindings(self);

but I'm stuck on how to update the view model with a validated observable

I can't use ko.mapping.fromJS(result.data, self.quote); because that will update self.quote with a plain observable not a validated observable and unsurpisingly that doesn't work.

Here are a couple of very simplified fiddles to illustrate the problem.

Plain Observable (which works): https://jsfiddle.net/stevedavey/1tup0agt/

Validated Observable (which doesn't): https://jsfiddle.net/stevedavey/yh233wht/

I'd appreciate any clue as to what I need to do to be able to get an amended 'quote' from an ajax call and update my validated observable using ko mapping.

I suspect I'm misunderstanding something fundamental.

1

1 Answers

1
votes

I can't use ko.mapping.fromJS(result.data, self.quote); because that will update self.quote with a plain observable not a validated observable and unsurpisingly that doesn't work.

You can use ko.mapping.fromJS, you're just doing it wrong. Take the time to read the documentation of the mapping plugin - it's only one page and not even a long one.

You can define additional behavior by passing an options object. In this case you want to customize object creation using create - like returning a validated observable.

I'm citing the documentation example with one change:

var mapping = {
    'children': {
        create: function(options) {
            return ko.validatedObservable(options.data);
        }
    }
}
var viewModel = ko.mapping.fromJS(data, mapping);

Of course you can use create at the root level of the mapping options, too, but the mapping plugin also allows you to be more specific.

Side note: Try to re-use the same function to initialize and to update your viewmodel. There is no real reason to keep two different pieces of code around that update the same observable.