Click here to Skip to main content
15,867,939 members
Articles / Web Development / ASP.NET

Customer KnockoutJS Validation

Rate me:
Please Sign up or sign in to vote.
4.75/5 (6 votes)
19 Jul 2012CPOL2 min read 53K   17   6
A KnockoutJS plug-in for model and property validation that is named Knockout validation

This article is the second on the 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.

C#
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:

C#
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 plug in:

XML
<!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:

XML
@{
    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 list
  • 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.

This article was originally posted at http://xprog.blogspot.com/feeds/posts/default

License

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


Written By
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...”

Comments and Discussions

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

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

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