0

I've implemented a fairly common scenario in knockout.js, duplicating a form. The user fills out a "contact" form, and they are given the option to use the same values on a "billing" form by clicking a checkbox. That uses jQuery to iterate through the contact form, and set the billing form inputs of the same name to the same value.

Here's a stripped-down fiddle that shows the problem; try filling out the contact form, and then click the "Same as Contact Information" checkbox. The billing form will fill, but you'll see when you click the "Validate Billing" button that each field in the billing form fails validation. If you manually type values into the form, the validation succeeds.

The question I have is, why doesn't knockout-validation detect that the values in the billing form have been set after they have been copied from the contact form? After copying, despite having values, the required fields fail validation. How can I have knockout-validation detect that the field values have changed?

My models are using the baked in knockout-validation rules:

self.errors = ko.validation.group(this, {
    deep: true,
    observable: false
});

self.firstName = ko.observable().extend({
    required: true
});

Values are set via jQuery's val():

$(":input[name]", contactForm).each(function () {
    $("[name=" + $(this).attr("name") + "]", billingForm).val($(this).val());
});

The button to test validation is simple:

self.validateBilling = function () {
    self.errors.showAllMessages();
    if (self.errors().length == 0) {
        alert("No billing validation errors.");
    }
};
Nick Silberstein
  • 833
  • 2
  • 8
  • 24
  • Did you try to set the values using the observable properties of your viewmodel ? – Skyp Jul 11 '13 at 21:02
  • I did not; I'm new to knockoutjs and am used to doing things in a certain way. It's a hard habit to break. I found that knockout-validation must expect a change event, and using .val() does not trigger a change event. I posted an answer a few minutes ago that addresses my use case. – Nick Silberstein Jul 11 '13 at 21:11

1 Answers1

0

Found the problem; setting the input values with .val() wasn't causing onchange() to fire. Triggering change when setting the value solves the problem.

    $.fn.changeVal = function (v) {
        return $(this).val(v).trigger("change");
    };

    $(":input[name]", contactForm).each(function () {
        $("[name=" + $(this).attr("name") + "]", billingForm).changeVal($(this).val());
    });

(Credit for above)

Community
  • 1
  • 1
Nick Silberstein
  • 833
  • 2
  • 8
  • 24