0
votes

I'm trying to implement Knockout Validation and Knockout Mapping. I have an ASP.Net MVC WebAPI that sends JSON data to my client where I'm mapping JSON to observables in my model:

ViewModel:

ko.validation.rules.pattern.message = 'Invalid.';

ko.validation.configure({
    registerExtenders: true,
    messagesOnModified: true,
    insertMessages: true,
    parseInputAttributes: true,
    messageTemplate: null,
    decorateElement: true,
    errorClass: 'error'
});
var MakePaymentViewModel = function ()
{
    var mapDataFromJson = function (jsonFromServer)
    {
        var model = ko.mapping.fromJS(jsonFromServer);
        self.PaymentAmount(model.PaymentAmount());
        self.MakePaymentTo(model.MakePaymentTo());
        self.MakePaymentOn(model.MakePaymentOn());
    };

    var self = this;

    /* MAKE PAYMENT MODEL*/
    self.PaymentAmount = ko.observable().extend({ required: { message: 'required'}});
    self.MakePaymentTo = ko.observable().extend({ required: { message: 'required'}});   
    self.MakePaymentOn = ko.observable().extend({ required: { message: 'required' }});  
    self.Errors = ko.validation.group(self);

    self.MapDataFromServer = function (jsonFromServer)
    {
        mapDataFromJson(jsonFromServer);
    };

    self.DoPaymentConfirmation = function ()
    {
        console.log('error count: ' + self.Errors().length);
    };
};

Here's My View:

<form id="MakePaymentForm" autocomplete="off">
<div class="input-wrapper">
    <label for="SendingAmount" class="text-left">I am sending <small>*</small></label>
    <input id="PaymentAmount" type="text" data-bind="value: PaymentAmount"/>
</div>

<div class="input-wrapper">
    <label for="MakePaymentTo" class="text-left">to <small>*</small></label>
    <input id="MakePaymentTo" type="text" data-bind="value: MakePaymentTo"/>
</div>

<div class="input-wrapper">
    <label for="MakePaymentOn" class="text-left">on <small>*</small></label>
    <input name="MakePaymentOn" id="MakePaymentOn" type="text" data-bind="value: MakePaymentOn"/>
</div>
<button type="submit" class="small radius" data-bind="click: DoPaymentConfirmation">Send</button>
</form>

I think what's happening is the first time I get data from the server, the JSON's data is null:

{"PaymentAmount":null,"MakePaymentTo":null,"MakePaymentOn":null}

So, the mapDataFromJson function is populating the observables with null data and triggering the validation rules and consequently the UI shows the error messages immediately before the user can enter any data.

Any ideas on how to fix this? I'm new to Knockout, so I may not be doing this correctly. Thanks for your time.

1
Could you wrap the setting of the observables in a null reference check inside mapDataFromJson ?Jamie Dixon
I tried that and the validation does not show immediately, however, when I press the submit button, I can console.log('error count: ' + self.Errors().length) to see there are errors but now none of the error messages show in the UI. It must be opposite day.Tom Schreck
I figured it out. Opposite day was last Tuesday. I forgot to use self.Errors.showAllMessages(); It's working as it's supposed to. Thanks for your help.Tom Schreck
@TomSchreck can you put that in an answer and mark it as answered so other people can see that its solvedJared

1 Answers

0
votes

Thanks Jamie for pointing me in the right direction. Here's what I did to solve the problem:

    var mapDataFromJson = function (jsonFromServer)
{
    var model = ko.mapping.fromJS(jsonFromServer);

    if (model.PaymentAmount() != null)
    {
        self.PaymentAmount(model.PaymentAmount());  
    }

    if (model.MakePaymentTo() != null)
    {
        self.MakePaymentTo(model.MakePaymentTo());  
    }

    if (model.MakePaymentOn() != null)
    {
        self.MakePaymentOn(model.MakePaymentOn());  
    }
};

Then in the function that's bound to the submit button I do this:

    self.DoPaymentConfirmation = function ()
{
    if (self.Errors().length == 0)
    {           
        //POST TO SERVER
    }
    else
    {
        self.Errors.showAllMessages();
    }
};