0

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.

Tom Schreck
  • 5,177
  • 12
  • 68
  • 122
  • 1
    Could you wrap the setting of the observables in a null reference check inside `mapDataFromJson` ? – Jamie Dixon Nov 15 '13 at 17:06
  • 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 Nov 15 '13 at 17:13
  • 1
    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 Nov 15 '13 at 17:17
  • @TomSchreck can you put that in an answer and mark it as answered so other people can see that its solved – Jared Nov 15 '13 at 17:26

1 Answers1

0

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();
    }
};
Tom Schreck
  • 5,177
  • 12
  • 68
  • 122