Validation plugin with jQuery UI Dialog only firing validation once

I have an ASP.NET Web Form with fields bound to a data model using KnockoutJS. I am using the Knockout validation plugin to validate.

The user has the ability to add multiple phone numbers to their application and I am using UI dialog to prompt them. My problem is that when validation is triggered it lets the user know: "must enter more than 2 digits", which I applied the max property on my model for phone number. Validation is only triggered once though and the user can bypass by just hitting accept twice.

I have attached a jsfiddle to display the problem.

<h3>Phone Number</h3>

<input type="button" value="Add New Phone" data-bind="click: AddPhone" />
<table>
<thead>
    <tr>
        <th>Type</th>
        <th>Number</th>
        <th></th>
        <th></th>
    </tr>
</thead>
<tbody data-bind="foreach: PhoneNumbers">
    <tr>
        <td data-bind="text: PhoneNumber_PhoneTypeName"></td>
        <td data-bind="text: PhoneNumber_Number"></td>
        <td data-bind="click: $root.EditPhone">Edit</td>
        <td data-bind="click: $root.DeletePhone">Delete</td>
    </tr>
</tbody>
</table>
<div data-bind="jqDialog: { autoOpen: false, resizable: false, modal: true, title:      'Phone Number' },
                template: { name: 'addPhoneNumberDialog', data: EdittingPhone, 'if':    EdittingPhone },
                openDialog: EdittingPhone"></div>


<script id="addPhoneNumberDialog" type="text/html">
    <div class="addPhoneNumberDialog">                    
    <p><span>Type:</span> <asp:DropDownList runat="server" ID="ddlApplicantPhoneType"    data-bind="value: PhoneNumber_PhoneTypeID, selectedText: PhoneNumber_PhoneTypeName">   </asp:DropDownList></p> 
    <p><span>Number:</span> <input id="txtApplicantPhone" data-bind="value: PhoneNumber_Number" class="required phoneUS" /></p>                    
    <input type="button" class="acceptButton" value="Accept" data-bind="jqButton: {}, click: $root.OnAcceptPhoneEdit" />
    <input type="button" value="Cancel" data-bind="jqButton: {}, click: $root.OnCancelPhoneEdit" />
    </div>
</script>

//custom binding to initialize a jQuery UI dialog
ko.bindingHandlers.jqDialog = {
init: function (element, valueAccessor) {
    var options = ko.utils.unwrapObservable(valueAccessor()) || {};

    //handle disposal
    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
        $(element).dialog("destroy");
    });

    $(element).dialog(options);
}
};

//custom binding handler that opens/closes the dialog
ko.bindingHandlers.openDialog = {
update: function (element, valueAccessor) {
    var value = ko.utils.unwrapObservable(valueAccessor());
    if (value) {
        $(element).dialog({
            appendTo: $('form:first'),
            open: function () {
                $('.datepicker').datepicker();
            }
        });
        $(element).dialog('open');
    } else {
        $(element).dialog("close");
    }
}
};

var Application = function () {
var self = this;
this.Application_USCitizen = ko.observable(false);
this.Application_FirstName = ko.observable('').extend({
    required: true
});
this.Application_MiddleName = ko.observable('');
this.Application_LastName = ko.observable('');

this.PhoneNumbers = ko.observableArray([]);

this.SelectedPhone = undefined;
this.EdittingPhone = ko.observable();
this.AddPhone = function () {
    self.EdittingPhone(new PhoneNumber());
}
this.EditPhone = function (phone) {
    self.SelectedPhone = phone;
    self.EdittingPhone(new PhoneNumber().Copy(phone));
}
this.DeletePhone = function (phone) {
    self.PhoneNumbers.remove(phone);
}
this.OnAcceptPhoneEdit = function () {
    var editted = self.EdittingPhone();
    if (self.SelectedPhone != undefined) {
        self.SelectedPhone.Copy(editted);
    } else {
        self.PhoneNumbers.push(editted);
    }

    self.SelectedPhone = undefined;
    self.EdittingPhone(undefined);
}
this.OnCancelPhoneEdit = function () {
    self.SelectedPhone = undefined;
    self.EdittingPhone(undefined);
}
};

var PhoneNumber = function () {
var self = this;
this.PhoneNumber_PhoneTypeID = ko.observable(0);
this.PhoneNumber_PhoneTypeName = ko.observable('');
this.PhoneNumber_Number = ko.observable('').extend({
    max: 2
});

this.Copy = function (phone) {
    self.PhoneNumber_PhoneTypeID(phone.PhoneNumber_PhoneTypeID())
    self.PhoneNumber_PhoneTypeName(phone.PhoneNumber_PhoneTypeName())
    self.PhoneNumber_Number(phone.PhoneNumber_Number());

    return self;
}
};

var vm = new Application();
ko.applyBindings(vm);

http://jsfiddle.net/bjk964/wc7Vf/

Answers


The validation lib does not automatic stop your buttons from firing, you need to use ko.validation.group and check if there are any validation errors from your click handler

http://jsfiddle.net/wc7Vf/1/

var PhoneNumber = function () {
    var self = this;
    this.PhoneNumber_PhoneTypeID = ko.observable(0);
    this.PhoneNumber_PhoneTypeName = ko.observable('');
    this.PhoneNumber_Number = ko.observable('').extend({
        max: 2
    });

    this.Copy = function (phone) {
        self.PhoneNumber_PhoneTypeID(phone.PhoneNumber_PhoneTypeID())
        self.PhoneNumber_PhoneTypeName(phone.PhoneNumber_PhoneTypeName())
        self.PhoneNumber_Number(phone.PhoneNumber_Number());

        return self;
    }

    this.errors = ko.validation.group(this);
};

Need Your Help

Why don;t the height and the width of this frame increase?

animation swift height width coordinates

I am currently using this code to animate an UIButton and an UIImage:

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.