Click here to Skip to main content
Click here to Skip to main content

Customer KnockoutJS Validation

, 19 Jul 2012
Rate this:
Please Sign up or sign in to vote.
A KnockoutJS plug-in for model and property validation that is named Knockout validation.

This article is the second on KnockoutJS series I am writing. The first article was introductory: Customer KnockoutJS and MVC demo using JSON.

Now I am going to focus on KnockoutJS and validation. I am going to use a KnockoutJS plug-in for model and property validation that is named Knockout Validation. You can download it from here.

The ASP.NET MVC Controller has the actions to Get and Add a customer. This example has a new customer property: the country. This property allows to add an input type select to KnockoutJS and validation.

namespace KnockoutDemo.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "";

            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public JsonResult Get(int customerID)
        {
            // Get the customer ...
            Customer customer = new Customer {CustomerID = customerID, 
                                              FirstName = "John", 
                                              LastName = "Doe", 
                                              IsMale = true, 
                                              CountryID = 1 };
            return Json(customer);
        }

        [HttpPost]
        public JsonResult Add(Customer customer)
        {
            // Save the customer ...

            // return status message 
            var message = string.Format("Customer: {0} {1} Added. IsMale: {2} Age:{3}  CountryID: {4} ",
                                        customer.FirstName, customer.LastName, customer.IsMale.ToString(), 
                                        customer.Age.ToString(), customer.CountryID.ToString());
            return Json(message);
        }

    }
}

The ASP.NET MVC model is the customer with the new property:

namespace KnockoutDemo.Models
{
    public class Customer
    {

        public int CustomerID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public bool IsMale { get; set; }
        public int Age { get; set; }
        public int CountryID { get; set; }
    }
}

The ASP.NET MVC Layout includes the new knockout validation plugin:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/knockout.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/json2.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/knockout.validation.js")" type="text/javascript"></script>
</head>
<body>
    <div class="page">
        <header>
            <div id="title">
                <h1>Knockout Demo</h1>
            </div>
            <div> </div>
        </header>
        <div> </div>
        <div> </div>
        <section id="main">
            @RenderBody()
        </section>
        <footer>
        </footer>
    </div>
</body>
</html>

And the ASP.NET MVC view has the KnockoutJS and validation specifics:

@{
    ViewBag.Title = "Add Customer";
}
<!-- This should go to a css file-->
<style type="text/css">
.errorFill
{
    border:1px solid red;
    background-color: #fdd;
}
</style>

<h2>@ViewBag.Message</h2>

<form method="post" action="">

    <b>Customer Number: </b> <span data-bind="text: CustomerID" ></span><br /><br />
    <b>First Name: </b><input type="text" data-bind="value: FirstName" style="width:200px" /> <br /><br />
    <b>Last Name: </b><input type="text" data-bind="value: LastName" style="width:200px" /> <br /><br />
    <b>Age: </b><input type="text" data-bind="value: Age" style="width:200px" /> <br /><br />
    <input type="checkbox" data-bind="checked: IsMale" /><b>Male</b><br /><br />
    <b>Country: </b><select data-bind="options: CountryOptions, optionsValue: 'CountryID', 
          optionsText: 'Name', value:CountryID, optionsCaption:'-- Country --'"></select> <br /><br />
    <br />
    <input type="button" data-bind="click: KnockoutDemoNamespace.addCustomer" value="Add Customer" />
    <br />
    <div id="message"></div>
</form>


<script type="text/javascript">
// Initialized the namespace
var KnockoutDemoNamespace = {};

// View model declaration
KnockoutDemoNamespace.initViewModel = function (customer, countries) {
    var customerViewModel = ko.validatedObservable({
        CustomerID: ko.observable(customer.CustomerID),
        FirstName: ko.observable(customer.FirstName).extend({ required: true }),
        LastName: ko.observable(customer.LastName).extend({ required: true }),
        IsMale: ko.observable(customer.IsMale),
        Age: ko.observable(customer.Age).extend({ required: true }).extend({ number: true }),
        CountryID: ko.observable(customer.CountryID).extend({ required: true }),
        CountryOptions: ko.observableArray(countries)
    });

    var validationOptions = 
      { insertMessages: true, decorateElement: true, errorElementClass: 'errorFill' };
    ko.validation.init(validationOptions);

    return customerViewModel;
}


// Bind the customer
KnockoutDemoNamespace.bindData = function (customer) {
    // get the country list
    KnockoutDemoNamespace.getCountries();
    
    // Create the view model
    KnockoutDemoNamespace.viewModel = 
      KnockoutDemoNamespace.initViewModel(customer, KnockoutDemoNamespace.countries);
    ko.applyBindings(this.viewModel);
}


KnockoutDemoNamespace.getCountries = function () {
    $.ajax({
        url: "/Country/",
        type: 'post',
        contentType: 'application/json',
        cache: false,
        async: false,
        success: function (result) {
            KnockoutDemoNamespace.countries = result;
        },
        error: function (jqXHR, textStatus, errorThrown) {
            var errorMessage = '';
            $('#message').html(jqXHR.responseText);
        }
    });
}

KnockoutDemoNamespace.getCustomer = function (customerID) {
    $.ajax({
        url: "/Home/Get/",
        type: 'post',
        data: "{'customerID':'1' }",
        contentType: 'application/json',
        cache: false,
        success: function (result) {            
            KnockoutDemoNamespace.bindData(result);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            var errorMessage = '';
            $('#message').html(jqXHR.responseText);
        }
    });
}

KnockoutDemoNamespace.addCustomer = function () {
    
    if (KnockoutDemoNamespace.viewModel.isValid()) {
        $.ajax({
            url: "/Home/Add/",
            type: 'post',
            data: ko.toJSON(this),
            contentType: 'application/json',
            success: function (result) {
                $('#message').html(result);
            }
        });
    }
}


$(document).ready(function () {
    KnockoutDemoNamespace.getCustomer(1);

});

</script>

The KnockoutJS now has a observableArray of countries in the ViewModel, that is bind to the country select. Note the data-bind options of the select:

  • options: controls what options should appear in a drop-down lis
  • optionsValue: The name of the ViewModel property to bind to the option value
  • optionsText: The name of the ViewModel property to bind to the option text
  • value: The name of the ViewModel property to bind to the selected value
  • optionsCaption: The option that is used to make the user select a value on the select list

There is also the validation plug-in specifics in the ViewModel declaration:

  • The extend is used to extend the observables with the validation rules (you can read about all of them here)

In the example, I am using the required  (required: true) and number (number: true) validation rules.

  • validatedObservable in the view model declaration
  • isValid() - Before saving the data validate that the model is valid
  • validation.init - Used to configure the validation engine

In the example the invalid inputs are painted in red, that is where the CSS class is used by the validation.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Rui Inacio
Team Leader
Portugal Portugal
I am an Experienced Senior Microsoft Consultant responsible for developing and defining architectures for various projects in a Microsoft environment, using a Service-Oriented Architecture (SOA) and web based applications.
I am also a project manager using agile methodologies and SCRUM.
Software Quality Assurance is a mandatory in every project I am responsible.
As someone said:
“Anyone can program, but not everyone is a programmer...”
Follow on   Twitter

Comments and Discussions

 
GeneralMy vote of 5 PinmemberHemant G. Kumar30-Jul-12 4:17 
SuggestionWhat about dependent validation PinmemberHemant G. Kumar30-Jul-12 4:15 
GeneralRe: What about dependent validation PinmemberRui Inacio30-Jul-12 5:38 
GeneralRe: What about dependent validation PinmemberHemant G. Kumar30-Jul-12 19:09 
GeneralRe: What about dependent validation PinmemberRui Inacio31-Jul-12 3:26 
GeneralToo little explanation PinmemberTim Corey19-Jul-12 8:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 19 Jul 2012
Article Copyright 2012 by Rui Inacio
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid