<!DOCTYPE html>
<html>

  <head>
    <script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery-mockjax/1.6.2/jquery.mockjax.min.js"></script>
   
   
    <script src="http://cdn.syncfusion.com/js/assets/external/jquery.easing.1.3.min.js"></script>
    <script src="http://cdn.syncfusion.com/js/assets/external/jsrender.min.js"></script>
    <script src="http://cdn.syncfusion.com/js/assets/external/jquery.globalize.min.js"></script>
    <script src="http://cdn.syncfusion.com/13.2.0.29/js/web/ej.web.all.min.js"></script>
    <script src="http://cdn.syncfusion.com/13.2.0.29/js/common/ej.widget.ko.min.js"></script>

    <link rel="stylesheet" href="style.css" />
    <link rel="stylesheet" href="http://cdn.syncfusion.com/13.2.0.29/js/web/flat-azure/ej.web.all.min.css" />
  </head>

  <body>
    <div id="main">
      <!-- ko component: {
           name: "sample-screen"
      } -->
      <!-- /ko -->
    </div>
    <script id="tmpl-sample-screen" type="text/html">
      <div id="sample-screen">
          <div id="grid" data-bind="ejGrid: $data.gridConfig"></div>
      </div>
    </script>
    
    <script id="tmplgrid" type="text/x-jsrender">
      <tr role="row">
         <td>
            <p data-bind="text: $data.code"></p>
          </td>
          <td>
            <p data-bind="text: $data.description"></p>
          </td>
          <td>
           <p data-bind="text: $data.category"></p>
          </td>
          <td>
           <p data-bind="text: $data.dateCreate"></p>
          </td>
          <td>
            <p data-bind="text: $data.isActive"></p>
          </td>
          <td>
            <p data-bind="text: $data.sellPrice"></p>
          </td>
          <td> 
            <p data-bind="text: $data.onHand"></p>
          </td>
      </tr>
    </script>
    

    <script src="sample-screen.model.js"></script>
    <script src="sample-screen.repository.js"></script>
    <script src="sample-screen.mocks.js"></script>
    <script src="sample-screen.viewmodel.js"></script>
    <script src="sample-screen.bindings.js"></script>
    <script src="script.js"></script>
  </body>
</html>
'use strict';

function SampleScreen(options) {
  
  var self = this,
      defaults = {
        products: [],
        gridConfig: {
          rowTemplate: "#tmplgrid",
          dataSource: [],
          editSettings: { 
            allowEditing: true, 
            allowAdding: false, 
            allowDeleting: false 
          },
          allowPaging: true,
          allowSorting: true,
          allowFiltering: true,
          filterSettings: {
              filterType: 'excel'
          },
          pageSettings: {
              pageSize: 50
          },
          columns: [{
              field: 'code', headerText: 'Code', type: "number", allowEditing: false
          }, {
              field: 'description', headerText: 'Description', type: "string", editType: ej.Grid.EditingType.String
          }, {
              field: 'category.code', headerText: 'Category', type: "number"
          }, {
              field: 'dateCreated', headerText: 'Date Created', type: "date", format: "{0:MM/dd/yyyy}", editType: ej.Grid.EditingType.DateTimePicker
          }, {
              field: 'isActive', headerText: 'Is Active', type: "boolean", editType: ej.Grid.EditingType.Boolean
          }, {
              field: 'sellPrice', headerText: 'Sell Price', type: "number", format: "{0:n4}", editType:ej.Grid.EditingType.Numeric
          }, {
              field: 'onHand', headerText: 'On Hand', type: "number", format: "{0:n2}", editType:ej.Grid.EditingType.Numeric
          }]
        }
      };

  var currentValue = {};
  $.extend(currentValue, defaults, options);

  self.products = ko.observableArray(currentValue.products);
  self.gridConfig = currentValue.gridConfig;
  self.gridConfig.dataSource = self.products;
  
  self.load = function () {

    return $.when(GetProducts())
            .done(function (result) {
    
                self.map(result);
            });
  };
  
  self.map = function (data) {

    self.products.removeAll();
    self.products(ko.utils.arrayMap(data, function (product) {
        return new Product(product);
    }));
  };
}
/* Styles go here */

Syncfusion
==========

Issues
------

Templating doesn't support Knockout binding
'use strict';

function Product (options) {
    
  var self = this,
      defaults = {
        code: 0,
        description: "",
        category: new Category(options.category || {}),
        dateCreated: new Date(),
        isActive: true,
        sellPrice: 0.0,
        onHand: 0
      };

  var currentValue = {};
  $.extend(currentValue, defaults, options);
  
  
  self.code = ko.observable(currentValue.code);
  self.description = ko.observable(currentValue.description);
  self.category = ko.observable(currentValue.category);
  self.dateCreated = ko.observable(currentValue.dateCreated);
  self.isActive = ko.observable(currentValue.isActive);
  self.sellPrice = ko.observable(currentValue.sellPrice);
  self.onHand = ko.observable(currentValue.onHand);
}

function Category (options) {
    
  var self = this,
      defaults = {
        code: false,
        description: false,
      };

  var currentValue = {};
  $.extend(currentValue, defaults, options);
  
  
  self.code = ko.observable(currentValue.code);
  self.description = ko.observable(currentValue.description);
}
'use strict';

ko.components.register('sample-screen', {
    viewModel: {
        createViewModel: function (params, componentInfo) {

            var vm = new SampleScreen();
            vm.load();
            
            
            return vm;
        }
    },
    template: { element: "tmpl-sample-screen" }
});
'use strict';

var latency = 750;
var productMock = [];

for(var i = 0; i <= 500; i++)
{
    productMock.push({
        code: i,
        description: "prod-" + i,
        category: {
          code: i,
          description: "cat-" + i
        },
        dateCreated: new Date(),
        isActive: false,
        sellPrice: 1000.101 + i,
        onHand: 1000 + i
    });
}



$.mockjax({
    url: "http://localhost/api/product",
    responseTime: latency,
    contentType: "application/json",
    dataType: "json",
    responseText: productMock
});
'use strict';

// GET
function GetProducts() {
    return $.ajax({
        method: "GET",
        url: "http://localhost/api/product"
    });
}

// http://stackoverflow.com/questions/30700490/updating-individual-fields-in-an-ejgrid-with-knockout-js
var oldToString = Function.prototype.toString;
 
Function.prototype.toString = function() {
    if(ko.isObservable(this))
        return this();
    return oldToString.call(this);
}

ko.applyBindings({});