This project is read-only.

Classic page with knockout MVVM


In this example you have a classic web page that use the jquery plugin "zPageGrid2.js". In this page linq is enabled with paging size 10. You have a detail template and a edit/modify template. In the query projection method "applyTempKo(mapKnock)", you have specified a callback function "mapKnock(data)" that it will create the viewmodel. On the main template "temp1" you can see some html attribute: jcustomaction, jdeleteaction, jdetailaction, jmodifyaction. These tell the the plugin that there are some action that need to be registred. The tcustomCallBack, tdeleteCallBack actions will be specified by the plugin properties: tcustomCallBack, tdeleteCallBack. They will be raised when you clik on the link. When you click on the jdetailaction, jmodifyaction action link, will be opened a popup and will be applied the template. The template is specified inside the associated panel. You can declare this panel by the plugin properties: tdetailPanel, tdetailContainer, tmodifyPanel, tmodifyContainer.As you can see, inside the modify panel, there are two html attribute: jupdateaction, data-jcancelaction. When you click on the link will be called the callback function. You can specify those function by the plugin properties: tupdateCallBack, tcancelCallBack. If you click on tcancelCallBack the popup will be closed automaticaly. If you click on tupdateCallBack the popup will not be closed automaticaly. You can close it calling the methods closeModifyDialogFeilure() / closeModifyDialogSuccess().

@using JQueryLinq
@model Application1.CustomerViewModel2

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

@section header{
   ...
}

<h2>Index - Page08</h2>

<div>
   <input id="gbutton1" type="button" value="Search" />&nbsp;
   <input id="gbutton2" type="button" value="MoveF"  />&nbsp;
   <input id="gbutton3" type="button" value="MoveP"  />&nbsp;
   <input id="gbutton4" type="button" value="MoveN"  />&nbsp;
   <input id="gbutton5" type="button" value="MoveL"  />&nbsp;
</div>

<br /><br />

<div id="gpane1" style="display:none">
  <div>
    <table class="viewmodel">    
    <tr>
      <td>City: </td>
      <td><input id="text1" data-bind="value: city" /></td>
    </tr>  
    <tr>
      <td>Country: </td>
      <td><input id="text2" data-bind="value: country" /></td>
    </tr> 
    </table>
    <br /><br />
    <input id="gbutton6" type="button" value="Find" />
  </div>
</div>

<div id="gpane2" style="display:none">
  <table id="jtable">
  <tr>
    <td colspan="4"> &nbsp; </td>
    <td data-sort="CustomerID"> CustomerID </td>
    <td data-sort="CompanyName"> CompanyName </td>
    <td data-sort="Address"> Address </td>
    <td data-sort="City"> City </td>
    <td data-sort="City"> Value1 </td>
    <td data-sort="City"> Value2 </td>
    <td data-sort="City"> Total </td>
  </tr>
  <tbody id="jlist" 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> ${CustomerID} </td>
    <td> ${CompanyName} </td>
    <td> ${Address} </td>
    <td> ${City} </td>
    <td> ${Value1} </td>
    <td> ${Value2} </td>
    <td> ${Total} </td>
  <tr>
</script>

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

<script id="jmodifyTemplate" type="text/x-jquery-tmpl">
@using (Html.BeginForm()) {
<div> 
  <p>
    <b>CustomerID: </b>@Html.KoTextBoxStrFor(model => model.CustomerID)<br>
    @Html.ValidationMessageFor(model => model.CustomerID)
  </p>
  <p>
    <b>CompanyName: </b>@Html.KoTextBoxStrFor(model => model.CompanyName)<br>
    @Html.ValidationMessageFor(model => model.CompanyName)
  </p> 
  <p>
    <b>City: </b>@Html.KoTextBoxStrFor(model => model.City)
    @Html.ValidationMessageFor(model => model.City)
  </p>
  <p>
    <b>Value1: </b>@Html.KoTextBoxIntFor(model => model.Value1)
  </p>
  <p>
    <b>Value2: </b>@Html.KoTextBoxIntFor(model => model.Value2)
  </p>    
  <h3><b>Total: </b><span data-bind="text: Total"></span></h3>
</div>
}
</script>


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

$(document).ready(function () {
    var settings = {
        tpane1: 'gpane1',
        tpane2: 'gpane2',
        tcontainer: "jlist",
        tformViewModel: function () {
            return {
                city: ko.observable(""),
                country: ko.observable("")
            };
        },
        tcustomCallBack: function (obj) {
            customfrm(obj);
        },
        tdeleteCallBack: function (obj) {
            deletefrm(obj);
        },
        tupdateCallBack: function (obj) {
            updatefrm(obj);
        },
        tcancelCallBack: function (obj) {
            cancelfrm(obj);
        },
        tcacheEnabled: false,
        tdetailPanel: "gdialog1",
        tdetailContainer: "jlist1",
        tmodifyPanel: "gdialog2",
        tmodifyContainer: "jlist2",
        tknockoutValidation: true,
        tlinqEnabled: true,
        ttype: "2"
    };
    $("#gpane2").gridTemplate(settings, searchfrm).
      bind('popupdetail', function (event) {
          //alert("databound");
      }).
      bind('popupmodify', function (event) {
          //alert("databound");
      }).
      bind('databound', function (event) {
          //alert("databound");
      });
});

function searchfrm(context) {
    context.clearSearch();

    var r = context.koWhereObjectAnd();

    context.from("/Grid4/GetDataJson2").pagingWithSize(10).where(r.value, 
       r.param).orderBy("Country,City desc").applyTempKo(mapKnock);
};

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.Address = ko.observable(item.Address);
    this.City = ko.observable(item.City);
    this.Value1 = ko.observable(0);
    this.Value2 = ko.observable(0);
    this.Total = ko.observable(0);

    this.Value1.subscribe(function (value) {
        var ret = that.Value1() + that.Value2();
        that.Total(ret);
    });

    this.Value2.subscribe(function (value) {
        var ret = that.Value1() + that.Value2();
        that.Total(ret);
    });
};

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

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

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

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


In this way you can create a MVC jquery knockoutjs/MVVM grid with paging, filter and sort functions.

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 Apr 25, 2012 at 12:01 AM by mastefano64, version 46

Comments

No comments yet.