Knockoutjs and LINQ for JavaScript


At javascript level there are two layer. So you can use only the inner object "PagingBase". The framework can create a knockoutjs grid using data returned from an ajax call, but you can also populate a grid using data that are already within the browser (localStorage, sessionStorage, application offline, indexDB ... etc). In this case you use only the projection method showGridKo(data, callBackMapKnock, callBackTemplate) . Where data it is the collection that you already have. If you need to filter the data, you can use the library LINQ for JavaScript

@using JQueryLinq
@model Commons.Customer

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@section header{
    ...
}

<h2>Index - Page01</h2>

<br /><br />

<div> 
  <input id="button1" type="button" value="Load-Data" />&nbsp;
  <input id="button2" type="button" value="Find-1" />&nbsp;
  <input id="button3" type="button" value="Find-2" />&nbsp;
  <input id="button4" type="button" value="Find-3" />&nbsp;
</div>

<br /><br />

<div id="panel1">
  <table>
  <tr>
    <td colspan="4"> &nbsp; </td>
    <td data-sort="CustomerID"> CustomerID </td>
    <td data-sort="CompanyName"> CompanyName </td>
    <td data-sort="ContactName"> ContactName </td>
    <td data-sort="Address"> Address </td>
    <td data-sort="City"> City </td>
    <td data-sort="Country"> Country </td>
  </tr>
  <tbody id="result1" data-bind="template: {name: 'temp1', foreach: $data}"></tbody>
  </table>   
</div>

<div id="gdialog1" style="display:none;height:100px">
  <div id="jlist1" data-bind="template:'jdetailTemplate'"></div>
</div>

<div id="gdialog2" style="display:none;height:100px">
  <div id="jlist2" data-bind="template:'jmodifyTemplate'"></div> 
  <div>
    <a href="#" data-jupdateaction>Update</a>&nbsp;
    <a href="#" data-jcancelaction>Cancel</a>&nbsp;
  </div>
</div>

<script id="temp1" type="text/html">
  <tr class="pagingbase-ui-selected-ou"> 
    <td><a href="#" data-jcustomaction>Custom</a></td>
    <td><a href="#" data-jdeleteaction>Delete</a></td>
    <td><a href="#" data-jdetailaction>Detail</a></td>
    <td><a href="#" data-jmodifyaction>Modify</a></td>
    <td><span data-bind="text: CustomerID" /></td>
    <td><span data-bind="text: CompanyName" /></td>
    <td><span data-bind="text: ContactName" /></td>
    <td><span data-bind="text: Address" /></td>
    <td><span data-bind="text: City" /></td>
    <td><span data-bind="text: Country" /></td>
  <tr>
</script>

<script id="jmodifyTemplate" type="text/x-jquery-tmpl">
@using (Html.BeginForm()) {
<div>
  <p>
    <b>CustomerID: </b>@Html.KoTextBoxFor(model => model.CustomerID)<br>
    @Html.ValidationMessageFor(model => model.CustomerID)
  </p>
  <p>
    <b>CompanyName: </b>@Html.KoTextBoxFor(model => model.CompanyName)<br>
    @Html.ValidationMessageFor(model => model.CompanyName)
  </p>
  <p>
    <b>ContactName: </b>@Html.KoTextBoxFor(model => model.ContactName)<br>
    @Html.ValidationMessageFor(model => model.ContactName)
  </p>
  <p>
    <b>Address: </b>@Html.KoTextBoxFor(model => model.Address)
    @Html.ValidationMessageFor(model => model.Address)
  </p>
  <p>
    <b>City: </b>@Html.KoTextBoxFor(model => model.City)
    @Html.ValidationMessageFor(model => model.City)
  </p>
  <p>
    <b>Country: </b>@Html.KoTextBoxFor(model => model.Country)
    @Html.ValidationMessageFor(model => model.Country)
  </p>
</div>
}
</script>

<script id="jdetailTemplate" type="text/x-jquery-tmpl">
  <b>CustomerID: </b><span data-bind="text: CustomerID" /><br>
  <b>CompanyName: </b><span data-bind="text: CompanyName" /><br>
  <b>ContactName: </b><span data-bind="text: ContactName" /><br>
  <b>City: </b><span data-bind="text: City" /><br>
  <b>Country: </b><span data-bind="text: Country" /><br>
</script>


/// <reference path="jquery-1.5.1.js" />
/// <reference path="knockout-2.0.0.js" />

var undefined;
var key = "*key1*";
var data = undefined;
var context = {};

$(document).ready(function () {
    context = new PagingBase();
    context.container = "result1";
    context.mainpane = "panel1";
    context.customCallBack = function (obj) {
        customfrm(obj);
    };
    context.deleteCallBack = function (obj) {
        deletefrm(obj);
    };
    context.updateCallBack = function (obj) {
        updatefrm(obj);
    };
    context.cancelCallBack = function (obj) {
        cancelfrm(obj);
    };
    context.cacheEnabled = false;
    context.detailPanel = "gdialog1";
    context.detailContainer = "jlist1";
    context.modifyPanel = "gdialog2";
    context.modifyContainer = "jlist2";
    context.knockoutValidation = true;
    context.initPagingBase();
    //
    $("#button1").click(function (e) {
        startsearch1(context);
    });
    $("#button2").click(function (e) {
        startsearch2(context);
    });
    $("#button3").click(function (e) {
        startsearch3(context);
    });
    $("#button4").click(function (e) {
        startsearch4(context);
    });
    getPageData();
});

// ---------------------------------------------------------------

function startsearch1(context) {
    loadListData();
};

function startsearch2(context) {
    if (data == undefined) {
        alert("Data not found !!!");
        return;
    }
    context.clearSearch();
    context.showGridKo(data.ToArray());
};

function startsearch3(context) {
    if (data == undefined) {
        alert("Data not found !!!");
        return;
    }
    context.clearSearch();
    var result = data.Where("$.Country == 'Germany'");
    context.showGridKo(result.ToArray());
};

function startsearch4(context) {
    if (data == undefined) {
        alert("Data not found !!!");
        return;
    }
    context.clearSearch();
    var result = data.Where( "$.Country == 'Spain'" );
    context.showGridKo(result.ToArray());
};

function mapKnock(data) {
    return ko.observableArray(ko.utils.arrayMap(data, function (item) {
        return new dataItem(item);
    })
    );
};

function dataItem(item) {
    var that = this;
    this.CustomerID = ko.observable(item.CustomerID);
    this.CompanyName = ko.observable(item.CompanyName);
    this.ContactName = ko.observable(item.ContactName);
    this.Address = ko.observable(item.Address);
    this.City = ko.observable(item.City);
    this.Country = ko.observable(item.Country);
};

// ---------------------------------------------------------------

function deletefrm(obj) {
    $.ajax({ url: "/Grid5/DeleteViewModel/", type: 'post',
        data: ko.toJSON(obj.dataitemJs),
        contentType: 'application/json',
        error: function (request, state, error) {
            alert("Ajax error:" + error);
        },
        success: function (result) {
            //obj.context.refresh();
            alert(result);
        }
    });
};

function updatefrm(obj) {
    $.ajax({ url: "/Grid5/UpdateViewModel/", type: 'post',
        data: ko.toJSON(obj.dataitemJs),
        contentType: 'application/json',
        error: function (request, state, error) {
            //context.refresh();
            context.closeModifyDialogFeilure();
            alert("Ajax error: " + error);
        },
        success: function (result) {
            //context.refresh();
            context.closeModifyDialogSuccess();
            alert(result);
        }
    });
};

function customfrm(obj) {
    alert("custom:" + obj.dataitemJs.CustomerID);
};

function cancelfrm(obj) {
    alert("cancel:" + obj.dataitemJs.CustomerID);
};

// ---------------------------------------------------------------

function loadListData() {
    $.ajax({ url: "/Grid5/GetDataJson/", type: 'get',
        contentType: 'application/json',
        error: function (request, state, error) {
            alert("Ajax error:" + error);
        },
        success: function (result) {
            data = Enumerable.From(result);
            sessionStorage.setItem(key, data);
        }
    });
};

function getPageData() {
    sessionStorage.storage.getItem(key)
};


 [HttpPost]
 [OutputCache(Duration = 0, VaryByParam = "*")]
 public JsonResult UpdateViewModel(Customer entity)
 {
     var message = "Update1 error: " + entity.CustomerID;
     if (ModelState.IsValid == true)
     {
         if (entity.City == "pippo")
             throw new Exception("pippo");
         message = "Update1 ok: " + entity.CustomerID;
     }
     return Json(message);
 }

 [HttpPost]
 [OutputCache(Duration = 0, VaryByParam = "*")]
 public JsonResult DeleteViewModel(Customer entity)
 {
     var message = "Delete1 error: " + entity.CustomerID;
     if (ModelState.IsValid == true)
     {
         if (entity.City == "pippo")
             throw new Exception("pippo");
         message = "Delete1 ok: " + entity.CustomerID;
     }
    return Json(message);
}


Local knockoutjs grid with MVVM pattern (LINQ for JavaScript).

Classic page with knockout MVVM
jQuery mobile page with knockout MVVM
CRUD knockoutjs grid and MVVM pattern
jQuery mobile dynamic content with a knockoutjs template and MVC
Create a PhoneGap application using html5/javascript
How using RavenDB in a html5/javascript application
Knockoutjs and LINQ for JavaScript

Last edited Mar 17, 2012 at 7:53 PM by mastefano64, version 15

Comments

No comments yet.