Home > DeveloperSection > Forums > How to use Knockout.js for CURD opration in MVC.
Ankit Singh

Total Post:341

Points:2389
Posted on    September-30-2015 7:21 AM

 .NET C#  Mvc5  Controller 
Ratings:


 1 Reply(s)
 609  View(s)
Rate this:
Please help me how to use Knockout.js for insert update delete  Record in mvc.


aditya kumar Patel

Total Post:242

Points:1722
Posted on    September-30-2015 7:29 AM

Product.js
/// <reference path="knockout.validation.js" /> 
/// <reference path="knockout-3.1.0.js" />
/// <reference path="jquery-2.1.4.js" />
ko.validation.rules.pattern.message = 'Invalid.';
function Product(data) {
    this.Id = ko.observable(data.Id);
    this.ProductId = ko.observable(data.ProductId);
    this.CategotyName = ko.observable(data.CategotyName);
    this.ProductName = ko.observable(data.ProductName);
    this.Price = ko.observable(data.Price);
    this.CategotyId = ko.observable(data.CategotyId);
    this.Quantity = ko.observable(data.Quantity)
    this.TotalAmount = ko.observable(data.TotalAmount);
}
 
function ProductViewModel() {
    //Make the self as 'this' reference
    var self = this;
    self.Id = ko.observable();
    self.ProductId = ko.observable().extend({ required: true });
    self.CategotyName = ko.observable();
    self.ProductName = ko.observable();
    self.Price = ko.observable(0).extend({ required: true });
    self.CategotyId = ko.observable().extend({ required: true });
    self.Quantity = ko.observable().extend({ required: true});
    self.TotalAmount = ko.computed(function () {
        return this.Quantity() * this.Price();
    }, this);
    self.Products = ko.observableArray();
    self.ProductList = ko.observableArray();
    self.CategoryList = ko.observableArray();
    self.CustomerProducts = ko.observableArray();

    self.errors = ko.validation.group(this, { deep: true, observable: false });
    $.getJSON("/Home/GetCategoty", function (data) {   
        self.CategoryList(data);
    });

    self.ChangeCategory = function () {
        $.getJSON("/Home/GetProduct", { categoryId: self.CategotyId }, function (data) {
            self.ProductList(data);
        });
    }
   
    self.ProductCategory = function () {
        $.getJSON("/Home/GetProductDetails", { ProductId: self.ProductId }, function (data) {            
            self.Price(data[0].Price);
            self.ProductName(data[0].ProductName);
            self.CategotyName(data[0].CategoryName);
        });
    }

    // Calculate Total of Price After Initialization
    self.Total = ko.computed(function () {
        var sum = 0;
        var arr = self.Products();
        for (var i = 0; i < arr.length; i++) {
            sum += arr[i].Price();
        }
        return sum;
    });
    self.Save = function () {
        var data = ko.toJSON(self.Products());
        $.ajax({
            url: '/Home/Insert',
            cache: false,
            type: 'POST',
            contentType: 'application/json; charset=utf-8',
            data: data,
            success: function (data) {
                self.Products.removeAll();
                self.errors.showAllMessages(false);
                $('#AddNewModel').modal('hide');
                $('#datatable').DataTable().ajax.reload();
            }
        }).fail(
 function (xhr, textStatus, err) {
     alert(err);
 });

    }
    //Add New Item
    self.Insert = function () {
       
        if (self.errors().length > 0) {          
            self.errors.showAllMessages();
            return;
        }       
        self.Products.push(new Product({
            Id: self.Id(),
            ProductId: self.ProductId(),
            ProductName: self.ProductName(),
            CategotyName: self.CategotyName(),
            CategotyId: self.CategotyId(),
            Price: self.Price(),
            Quantity: self.Quantity(),
            TotalAmount: self.TotalAmount()
        }));
        self.Id(null);
        self.ProductId(null);
        self.CategotyName(null);
        self.ProductName(null);
        self.Price(null);
        self.CategotyId(null);
        self.Quantity(null);
        self.errors.showAllMessages(false);
    }

    // Delete product details
    self.delete = function (Product) {
        if (confirm('Are you sure to Delete "' + Product.ProductName() + '" product ??')) {
            self.Products.remove(Product);
        }
    }

    // Delete product details
    self.Close = function () {
        self.Products.removeAll();
        self.errors.showAllMessages(false);
        $('#AddNewModel').modal('hide');
    }

    // Edit product details
    self.edit = function (Product) {
        self.ProductId(Product.ProductId());
        self.CategotyName(Product.CategotyName());
        self.ProductName(Product.ProductName());
        self.Price(Product.Price());
        self.CategotyId(Product.CategotyId());
        self.Quantity(Product.Quantity());
        self.TotalAmount(Product.TotalAmount());
    }
}

$(function () {
    var productViewModel = new ProductViewModel();
    ko.applyBindings(productViewModel, $('tblProductList')[0]);
});
HTML CODE
MY LIST PAGE

@{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } <link href="~/Content/bootstrap.css" rel="stylesheet" /> <link href="~/Content/jquery.dataTables.css" rel="st ylesheet" /> @Html.Partial("_Confirmation") @Html.Partial("_NewProduct") <div class="container-fuill"> <div class="panel panel-default"> <!--k Default panel contents --> <div class="panel-heading ui-widget-header"> <h3 class="panel-title pull-left">Produc t Order List</h3> <input id="btnadd" type="button"

value="Add New" class="btn btn-info pull-right AddDialog"/> <div class="clearfix"></div> </div> <!-- Table --> <div class="table-responsive"> <table class="table" id="datatable"> <thead id="header"> <tr> <th>ProductId</th> <th>Product Name</th> <th>Category</th> <th>Price</th> <th>Quantity</th> <th>Amount</th> <th>Action</th> </tr> </thead> <tbody> </tbody> </table> </div> </div> </div> <script src="~/Scripts/jquery-2.1.4.js"></script> <script src="~/Scripts/jquery.dataTables.js"></script> <script src="~/Scripts/knockout-3.3.0.js"></script> <script src="~/Scripts/knockout.validation.js"></script> <script src="~/Scripts/bootstrap.min.js"></script> <script src="~/Scripts/ProductList.js"></script> <script src="~/Scripts/Product.js"></script>


Add New Product Page

<style> label { display: block; } .validationMessage { color: Red; } .customMessage { color: Orange; } </style> <div class="modal fade" id="AddNewModel" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog modal-lg"

role="document"> <div class="modal-content" id="model-confirmation-content"> <div class="modal-header"> <button type="button"

class="close" data-dismiss="modal"

aria-label="Close">

<span aria-hidden="true">&times;</span></button> <h4 class="modal-title">Add New Product</h4> </div> <div class="modal-body"> <div class="form-horizontal"> <div class="form-group"> <label for="concept"

class="col-sm-3 control-label">Category</label> <div class="col-sm-9"> <select class="form-control" id="category" data-bind="options:CategoryList, optionsText:'CategoryName',optionsValue:'CategoryId', value:CategotyId , optionsCaption: 'Choose...', event:{ change: ChangeCategory}"> </select> </div> </div> <div class="form-group"> <label for="description" class="col-sm-3 control-label">Product Name</label> <div class="col-sm-9"> <select class="form-control" data-bind="options: ProductList, optionsText: 'ProductName', optionsValue: 'ProductId', value: ProductId, optionsCaption: 'Choose...',event:{ change: ProductCategory}"> </select> </div> </div> <div class="form-group"> <label for="amount" class="col-sm-3 control-label">Price</label> <div class="col-sm-9"> <input type="text" class="form-control" data-bind="value:Price" readonly id="price" name="Price"> </div> </div> <div class="form-group"> <label for="status" class="col-sm-3 control-label">Quntity</label> <div class="col-sm-9"> <input type="number" id="Qty" class="form-control" data-bind="value: Quantity" name="Quntity" required"> </div> </div> <div class="form-group"> <label for="date" class="col-sm-3 control-label">Amount</label> <div class="col-sm-9"> <input type="text" class="form-control" data-bind="value: TotalAmount" readonly id="amount" name="amount"> </div> </div> <div class="form-group"> <div class="col-sm-12 text-right"> <button type="button" class="btn btn-default preview-add-button" data-bind="click: $root.Insert"> <span class="glyphicon glyphicon-plus"></span>Add </button> </div> </div> </div> <div class="table-responsive"> <table class="table table-hover"> <thead> <tr> <th>ProductId</th> <th>Product Name</th> <th>Category</th> <th>Price</th> <th>Quantity</th> <th>Amount</th> </tr> </thead> <tbody data-bind="foreach: Products"> <tr> <td data-bind="text: ProductId"></td> <td data-bind="text: ProductName"></td> <td data-bind="text: CategotyName"></td> <td data-bind="text: Price"></td> <td data-bind="text: Quantity"></td> <td data-bind="text: TotalAmount"></td> <td> <button data-bind="click: $root.delete" class="btn btn-danger">Delete</button> </td> </tr> </tbody> <!-- preview content goes here--> </table> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-primary " data-bind="event:{ click:Save}, enable:Products().length >0">Save</button>&nbsp;&nbsp; <button type="button" class="btn btn-danger " data-bind="event:{ click:Close}">Close</button> </div> </div> </div> </div>

MY Controller
 [Authorize]
    public class HomeController : BaseController
    {

        public ActionResult Index()
        {
            return View();
        }
        public JsonResult GetCategoty()
        {
            var Result = Uow.CategotyMaster.GetAll();
            return Json(Result, JsonRequestBehavior.AllowGet);
        }
        [HttpPost]
        public ActionResult Delete(CustomerProduct obj)
        {
            Uow.CustomerProduct.Delete(obj.Id);
            SaveChanges();
            return new EmptyResult();
        }
        public ActionResult GetProduct(int categoryId = 0)
        {
            var result = (from a in Uow.ProductMaster.GetAll().ToList()
                          where a.CategoryId == categoryId
                          select new
                          {
                              a.ProductId,
                              a.ProductName
                          });
            return Json(result, JsonRequestBehavior.AllowGet);
        }
        public ActionResult GetProductDetails(int ProductId = 0)
        {
            var result = (from a in Uow.ProductMaster.GetAll().ToList()
                          join b in Uow.CategotyMaster.GetAll().ToList() on a.CategoryId equals b.CategoryId
                          where a.ProductId == ProductId
                          select new
                          {
                              a.ProductId,
                              a.ProductName,
                              a.Price,
                              b.CategoryId,
                              b.CategoryName
                          });
            return Json(result, JsonRequestBehavior.AllowGet);
        }
        [HttpPost]
        public JsonResult DataHandler(ReposityPattern.Models.DataTableViewModel.DTParameters param)
        {
            try
            {
                var dtsource = new List<ViewModel>();
                dtsource = Uow.CustomerProduct.GetAll().Select(z => new ViewModel { CategotyName = z.ProductMaster.CategotyMaster.CategoryName, Price = z.Price, Id = z.Id, ProductName = z.ProductMaster.ProductName, TotalAmount = z.TotalAmount, ProductId = z.ProductId, Quantity = z.Quantity }).ToList();
                List<String> columnSearch = new List<string>();
                if (param != null && param.Columns != null)
                {
                    foreach (var col in param.Columns)
                    {
                        columnSearch.Add(col.Search.Value);
                    }
                }
                List<ViewModel> data = new ResultSet().GetResult(param.Search.Value, param.SortOrder, param.Start, param.Length, dtsource, columnSearch);
                int count = new ResultSet().Count(param.Search.Value, dtsource, columnSearch);
                ReposityPattern.Models.DataTableViewModel.DTResult<ViewModel> result = new ReposityPattern.Models.DataTableViewModel.DTResult<ViewModel>
                {
                    draw = param.Draw,
                    data = data,
                    recordsFiltered = count,
                    recordsTotal = count
                };
                return Json(result, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                return Json(new { error = ex.Message }, JsonRequestBehavior.AllowGet);
            }
        }
        public void Insert(IList<CustomerProduct> obj)
        {
            foreach (CustomerProduct o in obj)
            {
                Uow.CustomerProduct.Add(o);
            }
        }

    }
List Page Datatable.Js
$(function () {    
    var oTable = $('#datatable').DataTable({
        "serverSide": true,
        "responsive": true,
        "pageLength": 10,
        "pagingType": "full_numbers",
        "ajax": {
            "type": "POST",
            "url": '/Home/DataHandler',
            "contentType": 'application/json; charset=utf-8',
            'data': function (data) {
                return data = JSON.stringify(data);
            }
        },
        "processing": true,
        "paging": true,
        "deferRender": true,
        "columns": [
       { "data": "ProductId" },
       { "data": "ProductName" },
       { "data": "CategotyName" },
       { "data": "Price" },
       { "data": "Quantity" },
       { "data": "TotalAmount" },
       {
           data: "Id", "bSearchable": false,
           bSortable: false,
           mRender: function (data, type, full) {
               return '<a href="Home/Delete/' + data + '"" Class="btn btn-default btn-danger deleteDialog" >Delete</a>'
           }
       }
        ],
        "order": [1, "asc"],
    });

    $(document).on('click', '.AddDialog', function (e) {
        e.preventDefault();       
        $('#AddNewModel').modal('show');        
    });


    $(document).on('click', '.deleteDialog', function (e) {
        e.preventDefault();
        $('.DeleleConfirm').attr("href", $(this).attr("href"));
        $('#modelProduct').modal('show');
    });

    $(document).on('click', '.DeleleConfirm', function (e) {
        e.preventDefault();
        $.post("/" + $(this).attr("href"), function (response) {
            $('#modelProduct').modal('hide');
            $('#datatable').DataTable().ajax.reload();
        });
    });

});
DataTable Filter Class
    public class DataTableViewModel
        {
            public class DTResult<T>
            {
                /// <summary>
                /// The draw counter that this object is a response to - from the draw parameter sent as part of the data request.
                /// Note that it is strongly recommended for security reasons that you cast this parameter to an integer, rather than simply echoing back to the client what it sent in the draw parameter, in order to prevent Cross Site Scripting (XSS) attacks.
                /// </summary>
                public int draw { get; set; }

                /// <summary>
                /// Total records, before filtering (i.e. the total number of records in the database)
                /// </summary>
                public int recordsTotal { get; set; }

                /// <summary>
                /// Total records, after filtering (i.e. the total number of records after filtering has been applied - not just the number of records being returned for this page of data).
                /// </summary>
                public int recordsFiltered { get; set; }

                /// <summary>
                /// The data to be displayed in the table.
                /// This is an array of data source objects, one for each row, which will be used by DataTables.
                /// Note that this parameter's name can be changed using the ajaxDT option's dataSrc property.
                /// </summary>
                public List<T> data { get; set; }
            }

            /// <summary>
            /// The additional columns that you can send to jQuery DataTables for automatic processing.
            /// </summary>
            public abstract class DTRow
            {
                /// <summary>
                /// Set the ID property of the dt-tag tr node to this value
                /// </summary>
                public virtual string DT_RowId
                {
                    get { return null; }
                }

                /// <summary>
                /// Add this class to the dt-tag tr node
                /// </summary>
                public virtual string DT_RowClass
                {
                    get { return null; }
                }

                /// <summary>
                /// Add this data property to the row's dt-tag tr node allowing abstract data to be added to the node, using the HTML5 data-* attributes.
                /// This uses the jQuery data() method to set the data, which can also then be used for later retrieval (for example on a click event).
                /// </summary>
                public virtual object DT_RowData
                {
                    get { return null; }
                }
            }

            /// <summary>
            /// The parameters sent by jQuery DataTables in AJAX queries.
            /// </summary>
            public class DTParameters
            {
                /// <summary>
                /// Draw counter.
                /// This is used by DataTables to ensure that the Ajax returns from server-side processing requests are drawn in sequence by DataTables (Ajax requests are asynchronous and thus can return out of sequence).
                /// This is used as part of the draw return parameter (see below).
                /// </summary>
                public int Draw { get; set; }

                /// <summary>
                /// An array defining all columns in the table.
                /// </summary>
                public DTColumn[] Columns { get; set; }

                /// <summary>
                /// An array defining how many columns are being ordering upon - i.e. if the array length is 1, then a single column sort is being performed, otherwise a multi-column sort is being performed.
                /// </summary>
                public DTOrder[] Order { get; set; }

                /// <summary>
                /// Paging first record indicator.
                /// This is the start point in the current data set (0 index based - i.e. 0 is the first record).
                /// </summary>
                public int Start { get; set; }

                /// <summary>
                /// Number of records that the table can display in the current draw.
                /// It is expected that the number of records returned will be equal to this number, unless the server has fewer records to return.
                /// Note that this can be -1 to indicate that all records should be returned (although that negates any benefits of server-side processing!)
                /// </summary>
                public int Length { get; set; }

                /// <summary>
                /// Global search value. To be applied to all columns which have searchable as true.
                /// </summary>
                public DTSearch Search { get; set; }

                /// <summary>
                /// Custom column that is used to further sort on the first Order column.
                /// </summary>
                public string SortOrder
                {
                    get
                    {
                        return Columns != null && Order != null && Order.Length > 0
                            ? (Columns[Order[0].Column].Data + (Order[0].Dir == DTOrderDir.DESC ? " " + Order[0].Dir : string.Empty))
                            : null;
                    }
                }

            }

            /// <summary>
            /// A jQuery DataTables column.
            /// </summary>
            public class DTColumn
            {
                /// <summary>
                /// Column's data source, as defined by columns.data.
                /// </summary>
                public string Data { get; set; }

                /// <summary>
                /// Column's name, as defined by columns.name.
                /// </summary>
                public string Name { get; set; }

                /// <summary>
                /// Flag to indicate if this column is searchable (true) or not (false). This is controlled by columns.searchable.
                /// </summary>
                public bool Searchable { get; set; }

                /// <summary>
                /// Flag to indicate if this column is orderable (true) or not (false). This is controlled by columns.orderable.
                /// </summary>
                public bool Orderable { get; set; }

                /// <summary>
                /// Specific search value.
                /// </summary>
                public DTSearch Search { get; set; }
            }

            /// <summary>
            /// An order, as sent by jQuery DataTables when doing AJAX queries.
            /// </summary>
            public class DTOrder
            {
                /// <summary>
                /// Column to which ordering should be applied.
                /// This is an index reference to the columns array of information that is also submitted to the server.
                /// </summary>
                public int Column { get; set; }

                /// <summary>
                /// Ordering direction for this column.
                /// It will be dt-string asc or dt-string desc to indicate ascending ordering or descending ordering, respectively.
                /// </summary>
                public DTOrderDir Dir { get; set; }
            }

            /// <summary>
            /// Sort orders of jQuery DataTables.
            /// </summary>
            public enum DTOrderDir
            {
                ASC,
                DESC
            }

            /// <summary>
            /// A search, as sent by jQuery DataTables when doing AJAX queries.
            /// </summary>
            public class DTSearch
            {
                /// <summary>
                /// Global search value. To be applied to all columns which have searchable as true.
                /// </summary>
                public string Value { get; set; }

                /// <summary>
                /// true if the global filter should be treated as a regular expression for advanced searching, false otherwise.
                /// Note that normally server-side processing scripts will not perform regular expression searching for performance reasons on large data sets, but it is technically possible and at the discretion of your script.
                /// </summary>
                public bool Regex { get; set; }
            }
        }
  public class ResultSet
    {
        public List<ViewModel> GetResult(string search, string sortOrder, int start, int length, List<ViewModel> dtResult, List<string> columnFilters)
        {
            return FilterResult(search, dtResult, columnFilters).SortBy(sortOrder).Skip(start).Take(length).ToList();
        }

        public int Count(string search, List<ViewModel> dtResult, List<string> columnFilters)
        {
            return FilterResult(search, dtResult, columnFilters).Count();
        }

        private IQueryable<ViewModel> FilterResult(string search, List<ViewModel> dtResult, List<string> columnFilters)
        {
            IQueryable<ViewModel> results = dtResult.AsQueryable();
            var res = results.Where(p => (search == null || (p.Id != null && p.Id.ToString().Contains(search.ToLower()) ||
                p.ProductName != null && p.ProductName.ToLower().Contains(search.ToLower())
                || p.CategotyName != null && p.CategotyName.ToLower().Contains(search.ToLower())
                || p.Price != null && p.Price.ToString().Contains(search.ToLower())
                || p.Quantity != null && p.Quantity.ToString().Contains(search.ToLower())
                || p.TotalAmount != null && p.TotalAmount.ToString().Contains(search.ToLower())
                )
              )).Select(x => new ViewModel { Id = x.Id, TotalAmount = x.TotalAmount, ProductId = x.ProductId, ProductName = x.ProductName, CategotyName = x.CategotyName, Price = x.Price, Quantity = x.Quantity });
            return res;
             
        }

      
    }

Modified On Sep-30-2015 11:02:38 PM

Don't want to miss updates? Please click the below button!

Follow MindStick