最新最全的
KendoUI技术文章

Kendo UI开发教程(3): 初始化Data 属性

admin阅读(1978)评论(0)

Contents 1配置 2事件 3数据源 4模板 前面在介绍准备Kendo UI开发环境时我们使用jQuery的方法将一个HTML元素转换成一个Kendo UI控件: $(?#datepicker?).kendoDatePicker(); 除了使用jQuery插件的方法来初始化方

前面在介绍准备Kendo UI开发环境时我们使用jQuery的方法将一个HTML元素转换成一个Kendo UI控件: $(?#datepicker?).kendoDatePicker();
除了使用jQuery插件的方法来初始化方法外,每个Kendo 控件还可以通过data属性来初始化,此时你需要设置data的role属性,然后调用kendo.init方法。
使用初始化Data属性的方法在页面上包含有大量Kendo UI控件时非常便利。 首先, 组件的配置包含在目标元素中,第二无需首先查找每个元素然后调用jQuery方法,你只需调用一次kendo.init()方法。
Kendo UI Mobile应用通常使用Data属性来初始化。

如下例使用data 属性来初始化一个UI组件

  1. <div id=“container”>
  2. <input data-role=“numerictextbox” />
  3. </div>
  4. <script>
  5. kendo.init($(“#container”));
  6. </script>
复制

20130612001

其中方法kendo.init($(?#container?)) 会查找所有包含有data-role属性的元素,然后初始化这些Kendo UI组件。 每个kendo UI组件的role的值为该UI组件名称的小写名字,比如?autocomplete?或?dropdownlist?。

缺省情况下,kendo.init 只会初始化Kendo UI Web组件和Kendo UI DataViz组件(按这个顺序)。 而Kendo UIMobile应用 首先初始化Kendo UI Mobile组件,然后是Kendo UI Web组件,最后是Kendo UI DataViz组件。 这意味着data-role=?listview? 在Mobile应用中会缺省初始化为 Kendo UI Mobile Listview。 然而可以通过指明组件全称的方法在修改这个缺省初始化顺序。
比如:在Mobile应用中 指明使用Kendo UI Web的listview

  1. <div data-role=“view”>
  2. <!– specify the Kendo UI Web ListView widget –>
  3. <div data-role=“kendo.ui.ListView”></div>
  4. </div>
  5. <script>
  6. var app = new kendo.mobile.Application();
  7. </script>
复制

配置

每个组件可以通过Data属性来进行配置,对于配置的属性,只需在属性名前加上data-前缀就可以做为目标元素的属性进行配置。比如 data-delay=?100?。 对于一些使用Camel-cased 的属性则是通过添加“-” ,比如AutoComplete的ignoreCase 的属性可以通过 data-ignore-case来设置。而对于一些已经是使用data前缀的属性则无需再添加data-前缀。比如dataTextField属性可以通过data-text-field属性来配置,dataSource属性可以通过data-source属性来配置。对于一些复杂的配置可以通过JavaScript 对象字面量来配置,比如:data-source=?{data: [{name: ?John Doe?},{name: ?Jane Doe?]}?.

如下例:

  1. <div id=“container”>
  2. <input data-role=“autocomplete”
  3. data-ignore-case=“true”
  4. data-text-field=“name”
  5. data-source=“{data: [{name: ‘John Doe’},{name: ‘Jane Doe’}]}”
  6. />
  7. </div>
  8. <script>
  9. kendo.init($(“#container”));
  10.  
  11. </script>
复制

20130612002

事件

你也可以通过data属性添加对Kendo UI组件的事件处理,属性的值被当成一个JavaScript函数,其作用域为全局。

如下例:

  1. <div id=“container”>
  2. <input data-role=“numerictextbox” data-change=“numerictextbox_change” />
  3. </div>
  4. <script>
  5. function numerictextbox_change(e) {
  6. // Handle the “change” event
  7. }
  8. kendo.init($(“#container”));
  9. </script>
复制

事件处理函数也可以为一个成员函数,比如 foo.bar 可以看出为foo 对象的 bar 方法。

例如:

  1. <div id=“container”>
  2. <input data-role=“numerictextbox” data-change=“handler.numerictextbox_change” />
  3. </div>
  4. <script>
  5. var handler = {
  6. numerictextbox_change: function (e) {
  7. // Handle the “change” event
  8. }
  9. };
  10. kendo.init($(“#container”));
  11. </script>
复制

数据源

支持数据绑定的UI组件的数据源也可以通过data-source 属性来指定。 这个属性可以为一个JavaScript对象,一个数组或是一个全局变量。

例如:

使用JavaScript对象作为数据源.

  1. <div id=“container”>
  2. <input data-role=“autocomplete” data-source=“{data:[‘One’, ‘Two’]}” />
  3. </div>
  4. <script>
  5. kendo.init($(“#container”));
  6. </script>
复制

使用JavaScript数组作为数据源。

  1. <div id=“container”>
  2. <input data-role=“autocomplete” data-source=“[‘One’, ‘Two’]” />
  3. </div>
  4. <script>
  5. kendo.init($(“#container”));
  6. </script>
复制

使用一个可以全局访问的变量作为数据源。

  1. <div id=“container”>
  2. <input data-role=“autocomplete” data-source=“dataSource” />
  3. </div>
  4. <script>
  5. var dataSource = new kendo.data.DataSource( {
  6. data: [ “One”, “Two” ]
  7. });
  8. kendo.init($(“#container”));
  9. </script>
复制

模板

  1. 模板也可以通过Data属性来设置,属性的值代表用来定义模板的Script元素的Id。比如:
  2.  
    1. <div id=“container”>
    复制
  3.     <input data-role="autocomplete"
    复制
  4.            data-source="[{firstName:'John', lastName: 'Doe'}, {firstName:'Jane', lastName: 'Doe'}]"
    复制
  5.            data-text-field="firstName"
    复制
  6.            data-template="template" />
    复制
  7. </div>
    复制
  8. <script id="template" type="text/x-kendo-template">
    复制
  9.     <span>#: firstName # #: lastName #</span>
    复制
  10. </script>
    复制
  11. <script>
    复制
  12. kendo.init($("#container"));
    复制
  13. </script>
    复制
  14.  

Kendo UI开发教程(2):准备Kendo UI开发环境

admin阅读(2276)评论(0)

Contents 1 Kendo UI Web 2Kendo UI DataViz 3Kendo UI Mobile 首先你需要从Telerik网站下载试用版开发包,注意需要注册后才能下载,或者从本站下载 (18M) 下载后直接解压后包含下面几个文件和目录: /example

首先你需要从Telerik网站下载试用版开发包,注意需要注册后才能下载,或者从本站下载 (18M)

下载后直接解压后包含下面几个文件和目录:

  • /examples ? 示例.
  • /js ? minified 化后的JavaScript库.
  • /vsdoc JavaScript Intellisense 支持文件
  • /styles ? minified后的CSS及主题资源.
  • changelog.html ? Kendo UI 发布文件.

如果你下载服务器端支持(比如ASP.NET,PHP等)还可能包含

  • wrappers 目录,支持服务器端UI组件的封装。

本教程侧重于直接使用JavaScript,服务器端支持只是使用PHP,Net等服务器端API生产这些客户端代码(主要是UI组件的配置),Kendo UI应用不需要这些服务器端封装就可以运行。

这里我们使用Visual Studio 2012 IDE作为开发环境,你可以使用你自己熟悉的开发工具,或者直接使用NotePad都可以开发基于Kendo UI的Web应用。

下面就可以使用Keudo UI 来开发Web应用了。首先使用Visual Studio 创建一个空的 Web Site ,然后及Kendo UI的 js和 styles 目录拷贝到这个新创建的Website 应用中。你如果直接使用Notepad作为开发工具,可以创建一个开发目录,然后把js,和Styles目录拷贝过来也是一样的。使用Visual Studio的一个好处是支持Intelisense ,帮助编写JavaScript代码,这是就需要把vsdoc的内容拷贝到js目录下。

然后添加三个 HTML 文档用来测试。

  • index.html     Web应用测试页
  • mobile.html  移动应用测试页
  • dataviz.html  数据显示测试页

20130609002

 Kendo UI Web

编写基于桌面系统的Web应用,使用KendoUI WEB Javascript库,在Html的Head部分添加对应的CSS和JavaScrpt,这里我们使用一个DataPicker 控件做为示例,完整代码如下:

  1. <!doctype html>
  2. <html>
  3. <head>
  4. <title>Kendo UI Web</title>
  5. <link href=“styles/kendo.common.min.css” rel=“stylesheet” />
  6. <link href=“styles/kendo.default.min.css” rel=“stylesheet” />
  7. <script src=“js/jquery.min.js”></script>
  8. <script src=“js/kendo.web.min.js”></script>
  9. </head>
  10. <body>
  11. <input id=“datepicker” />
  12. <script>
  13. $(function () {
  14. $(“#datepicker”).kendoDatePicker();
  15. });
  16. </script>
  17. </body>
  18. </html>
复制

20130609003

如果能够正确显示dataPicker控件,就表示Kendo UI Web开发环境已经正确设置好了。

Kendo UI DataViz

如果需要开发数据显示控件的Web页面(比如DataGrid,表格等),在页面添加DataViz库和CSS的应用,如下例显示一个仪表盘:

  1. <!doctype html>
  2. <html>
  3. <head>
  4. <title>Kendo UI DataViz</title>
  5. <link href=“styles/kendo.dataviz.min.css” rel=“stylesheet” />
  6. <script src=“js/jquery.min.js”></script>
  7. <script src=“js/kendo.dataviz.min.js”></script>
  8. </head>
  9. <body>
  10. <div id=“gauge”></div>
  11. <script>
  12. $(function () {
  13. $(“#gauge”).kendoRadialGauge();
  14. });
  15. </script>
  16. </body>
  17. </html>
复制

20130609004

SpringMVC + MyBatis + KendoUI Grid 前后台功能流程介绍

admin阅读(2825)评论(1)

 

KendoUI Grid 的文档很全,但是怎么和Java后台结合,尤其是SpringMVC + MyBatis 结合,官方没有介绍,很多刚开始用KendoUI的开发者一开始就会碰到这个问题。光用Grid渲染数据可能还要,但是Grid牵涉到翻页啊,算页的总数啊,这些细节一深入,估计很难倒不少新手了,在这里我做一个系统的前后台介绍,希望能起到抛砖引玉的作用。

前端HTML代码:

<div id="example" style="margin: 0 auto ;width: 1000px;padding: 10px;">
    <div id="grid"></div>
</div>

简单处理,用一个DIV占位符来渲染 KendoUI Grid

前端Javascript代码:

$("#grid").kendoGrid({
    dataSource: {
        transport: {
            read: {
                url:"/api/grid",
                dataType: "json"
            }
        },
        pageSize: 10,
        serverPaging: true,
        schema: {
            data: function (d) { return d.data; }, // 在这里,也可以用  data: "data" 表示
            total: function (d) { return d.count; } // 在这里,也可以用 total: "count" 表示
        }
    },
    pageable: true,
    columns: [
        {
            field: "companyCode",
            title: "公司代码"
        },
        {
            field: "companyName",
            title: "公司名称"
        }
    ]
});

dataType:数据传输格式为 json 格式

pageSize:为每页展示数量,设置为10

serverPaging::设置服务器端翻页

schema:主要用来描述服务端请求的数据模型,schema 内置有8个属性,在这里根据需要,我们描述2个属性使用

schema.data:告诉datasource,服务端返回的json数据中,用于渲染表格的数据(一般是一个数组)是存放到返回数据的哪个key中,本例中,表格的数据存放到返回值的 data 这个key里。注意 schema 的data属性 和 返回值中 data 这个key的区别。

schema.total:告诉datasource表格渲染的记录总数存放在服务端返回值的哪个key中。本例是存放在返回值的 count 这个key中。

pageable:告诉Grid需要翻页栏

 

以上是前端相关的代码


 

后端Java代码

后端代码起始主要是SpringMVC Rest 接口这块的逻辑。

GridRestController.java ,内容参考如下:

package com.demo.grid.api;

import com.google.common.collect.Maps;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/grid")
public class GridRestController{

    @Autowired
    private GridService gridService;

    public static final String OFFSEET = "skip";
    public static final String LIMIT = "pageSize";
    public static final int DEFAULT_OFFSET = 0;
    public static final int DEFAULT_LIMIT = 10;

    @RequestMapping( value = {""}, method = {RequestMethod.GET}, produces = {"application/json"})
    public Map selectByMapper( @RequestParam Map<String,Object> params ){

        Map resultMap = Maps.newHashMap();

        // 读取记录数起始位,前端Datasource根据当前Grid页数和每页展示数量计算得知
        int offset = getOffset( params );

        // 每页获取个数,和前端 pageSize 对应
        int limit = getLimit(params);
        RowBounds rowBounds = new RowBounds(offset, limit);
        
        List grids = gridService.selectByMap(params, rowBounds);
        int count = gridService.countByMap(params);

        resultMap.put( "data", grids );
        resultMap.put( "count", count );

        return resultMap;
    }

    private int getOffset(Map params) {
        Object offset = params.get(OFFSEET);
        if(!StringUtils.isEmpty(offset)) {
            try {
                return Integer.parseInt(offset.toString());
            } catch (NumberFormatException var3) {
                return DEFAULT_OFFSET;
            }
        } else {
            return DEFAULT_OFFSET;
        }
    }

    private int getLimit(Map params) {
        Object limit = params.get(LIMIT);
        if(!StringUtils.isEmpty(limit)) {
            try {
                return Integer.parseInt(limit.toString());
            } catch (NumberFormatException var3) {
                return DEFAULT_LIMIT;
            }
        } else {
            return DEFAULT_LIMIT;
        }
    }
}

Grid翻页时,Datasource 会带上Grid翻页时所用到的 skip、pageSize 等参数附加到 read 的url参数后面,然后通过 SpringMVC后端,通过参数注解的方式,获取Request中的参数,,然后在程序中取出使用即可。

 

以上流程边完成了一个比较简单的 SpringMVC + MyBatis + KendoUI Grid 前后台调用过程。

转载请注明注明来自: KendoUI中文网 http://www.kendoui.io

KendoUI:Grid控件的使用

admin阅读(2034)评论(0)

1.创建和基本选项配置

有两种创建grid的方式,我这里使用已存在的html div标签,然后再将div元素kendo化.

<div id=”grid”></div>

<script th:inline=”javascript”>
$(function(){
    
  $('#grid') .kendoGrid({
    dataSource : dataSource, //数据源加载
     pageable : {   //分页信息选项设置
    input : true, 
    numeric : false, 
    refresh: true, 
              pageSizes: true, 
              buttonCount: 5 
    }, 
    sortable : true, //可排序
    height : 430, //表格高度设置
    toolbar : [ //工具条,可使用模板自定义
    { 
 		name : "create", 
 		text : "添加" 
 		}, 
             { 
    template :
          kendo.template($("#pageStyleSkinTemplAddTemplate").html()) 
             }, 
             { 
    template : 
          kendo.template($("#pageStyleSkinQueryTemplate").html()) 
    } 
  ], 
  columns : [ //表格列设置
            { 
               field: "fileName", //dataSource中与data对应的域(field)的名称
               title: "风格名称", //表头名称
               width: 200   //列宽
           }, 
           { 
               field: "updaterId", 
               title: "更新人", 
               width: 100 
           }, 
           { 
               field: "updateTime", 
               title: "上传时间", 
               width: 200, 
               format: "{0: yyyy-MM-dd HH:mm:ss}" //格式化时间
           }, 
          { 
    command : [  //对行数据的操作
          { 
            text:"编辑", //名称
            click: editFunction //自定义点击事件
          }, 
          { 
            text:"下载", 
            click: loadFunction 
          }, 
          { 
            name : "destroy", //调用dataSource中的删除方法
            text : "删除" 
          } 
        ], 
        title : "操作", //表头名称
        width : "250px" //列宽
      } 
          ], 
          editable : 
     { 
        mode : "popup", //弹出窗口的编辑模式(行内编辑:”inline”)
     }, 
          messages : //分页条部分显示中文信息的设置
     { 
      display : "Showing {0}-{1} from {2} data items", 
      empty : "No data" 
     } 
  
});


});
</script>

2.基本CRUD操作

(1)假设数据来源为ajax请求,我这里不使用kendo封装好的ajax请求,使用灵活的自己写的ajax请求.

var codeGridSource = new kendo.data.DataSource(
  {
    transport : {
    read : function(options) {
      var map = {};
        if (options.data.take)
          map.take = options.data.take;
      if (options.data.skip)
        map.skip = options.data.skip;
      if (options.data.page)
        map.page = options.data.page;
      if (options.data.pageSize)
        map.pageSize = options.data.pageSize;
      if (!options.data.filter){
      } 
      else 
      {
        options.data.filter = {
            logic : "and",
            filters : [
          {
            field : "codeName",
            value : $("#codeName").val()
          },
          {
            field : "codeType",
            value : $("#codeType").val()
          },
          {
            field : "codeTypeName",
            value : $("#codeTypeName").val()
          },
          {
            field : "codeCode",
            value : $("#codeCode").val()
          }
          ]};
        var fi1 = {};
        var fi2 = [];
        var j = 0;
        $.each(options.data.filter.filters, function(i,element) {
          if (options.data.filter.filters[i].value) 
          {
            fi2[j] = options.data.filter.filters[i];
            j++;
          }
        });
        if (fi2.length > 0) 
        {
          fi1.filters = fi2;
          fi1.logic = options.data.filter.logic;
          map.filter = fi1;
          }
  }

      //排序
      if (!options.data.sort) 
      {
      } 
      else 
      {
        options.data.sort = [
        {
          field : $("#codeOrder0").val(),
          dir : $("#codeDir0").val()
        },
        {
          field : $("#codeOrder1").val(),
          dir : $("#codeDir1").val()
        } 
        ];
        var fi3 = [];
        var j = 0;
        $.each(options.data.sort, function(i,element){
          if (options.data.sort[i].field) {
            fi3[j] = options.data.sort[i];
            j++;
          }
        });
        if (fi3.length > 0) 
        {
          map.sort = fi3;
        }
      }

          $.ajax({
            url : "code/single-list.json",
            dataType: "json", 
            data:{
          	  models : kendo.stringify(map)
            },
            type:"POST",
            success: function(result) {
    options.success(result);
            },
            error: function(result) {
    options.error(result);
            }
          });
      
     },
    update : function(options) {
          $.ajax({
            url : "code/single-update.json",
            dataType: "json", 
            data:{
          	models : kendo.stringify(options.data.models)
            },
            type:"POST",
            success: function(result) {
    options.success(result);
            },
            error: function(result) {
    options.error(result);
            }
          });
    },
    destroy : function(options) {
          $.ajax({
            url : "code/delete.json",
            dataType: "json", 
            data:{
          	models : kendo.stringify(options.data.models)
            },
            type:"POST",
            success: function(result) {
    options.success(result);
            },
            error: function(result) {
    options.error(result);
            }
          });
    },
    create : function(options) {
          $.ajax({
            url : "code/single-create.json",
            dataType: "json", 
            data:{
          	models : kendo.stringify(options.data.models)
            },
            type:"POST",
            success: function(result) {
    options.success(result);
            },
            error: function(result) {
    options.error(result);
            }
          });
      
    }
    },
    batch : true,
    pageSize : 8,
    serverPaging : true,
    serverSorting : true,
    serverFiltering : true,
    schema : {
      errors: function(response) 
      {
        return response.error; 
      },
      data : "list",
      total : "total",
      model : {
        id : "id",
        fields : 
        {
          codeIndex:
          {
            editable : true,
            type:"number",
              defaultValue: 0,
              validation:{
              required:true,
              min:0
            }
          },
            codeCode : 
            {
              editable : true,
              type:"string",
              validation:
              {
                codeCodevalidation: function (input) 
                {
              if (input.is("[name=codeCode]") && $.trim(input.val()) == "" )
              {
              		 input.attr("data-codeCodevalidation-msg", "请输入业务代码!");
              		 input.css("border-color","red");
             return false;
              }
              else{
            		input.css("border-color"," #94C0D2");
            	}
              return true;
          }
              }
          },
          codeName : 
          {
            editable : true,
            type:"string"
          },
          codeType : 
          {
            editable : true,
            type:"string",
            validation:
            {
              codeTypevalidation: function (input) 
              {
            if (input.is("[name=codeType]") && $.trim(input.val()) == "")
            {
            		 input.attr("data-codeTypevalidation-msg", "请输入代码类型!");
            		 input.css("border-color","red");
           return false;
            }
            else{
        		input.css("border-color"," #94C0D2");
        	}
            return true;
        }
            }
          },
          codeTypeName: 
          {
            editable : true,
            type:"string"
          }
        }
      }
    },
    error: function(e) {
      alert(e.errors);  // displays "Invalid query"
      codeGridSource.cancelChanges();
    }
  });

(2)使用kendo自带的封装好的ajax请求来实现.

var dataSource = new kendo.data.DataSource( 
  { 
    transport : { 
    read : { 
      url : "xxx.json", //定义查询url
      type : "POST" 
      }, 
    create : { 
      url : "xxx.json", //定义新增url
      type : "POST" 
      }, 
                          update : { 
      url : "xxx.json", //定义修改url
      type : "POST" 
      }, 
    destroy : { 
      url : "xxx.json", //定义删除url
      type : "POST" 
      }, 
    parameterMap : function(options,operation) { //定义提交给后台携带的参数
      var map = {}; 
      if (operation !== "read") { 
        return { 
        models : kendo.stringify(options.models) //查询操作时返回的参数
        }; 
      }; 

      if (options.take) 
          map.take = options.take; 
      if (options.skip) 
        map.skip = options.skip; 
      if (options.page) 
        map.page = options.page; 
      if (options.pageSize) 
        map.pageSize = options.pageSize; 
      if (!options.filter) { 
      } 
      else 
      { 
                                                  //设置查询条件和连接符
        options.filter = { 
            logic : "and", //定义查询条件间的连接符
            filters : [ 
          { 
            field : "startTime", 
            value : $("#startTime").val() //查询条件的值的取值
          }, 
          { 
            field : "endTime", 
            value : $("#endTime").val() 
          }, 
          { 
            field : "fileName", 
            value : $("#fileName").val() 
          }, 
           
           
          ]}; 
        var fi1 = {}; 
        var fi2 = []; 
        var j = 0; 
        $.each(options.filter.filters, function(i,element) { 
          if (options.filter.filters[i].value) 
          { 
            fi2[j] = options.filter.filters[i]; 
            j++; 
          } 
        }); 
        if (fi2.length > 0) 
        { 
          fi1.filters = fi2; 
          fi1.logic = options.filter.logic; 
          map.filter = fi1; 
          } 
                                     } 
      if (!options.sort) 
      { } 
      else 
      { 
  //排序 选项的设置
        options.sort = [ 
        { 
          field : $("#pageStyleSkinOrder0").val(), 
          dir : $("#pageStyleSkinDir0").val() 
        }, 
        { 
          field : $("#pageStyleSkinOrder1").val(), 
          dir : $("#pageStyleSkinDir1").val() 
        } 
        ]; 
        var fi3 = []; 
        var j = 0; 
        $.each(options.sort, function(i,element){ 
          if (options.sort[i].field) { 
            fi3[j] = options.sort[i]; 
            j++; 
          } 
        }); 
        if (fi3.length > 0) 
        { 
          map.sort = fi3; 
        } 
      } 

      //操作为查询时提交给后台的参数 
      if (operation === "read") 
      { 
        return { 
          models : kendo.stringify(map) 
        }; 
      } 

     } 
    }, 
    batch : true, //可批量操作
    pageSize : 8, //每页显示条数设置
    serverPaging : true, //支持分页功能
    serverSorting : true,//支持排序功能 
    serverFiltering : true, //支持查询功能 
    schema : { 
      errors: function(response) 
      { 
        return response.error; //错误信息显示
      }, 
      data : "list", //定义数据来源
      total : "total", //页码总数
      model : { 
        id : "id", //id设置
        fields : 
        { 
               //根据data中对象的字段来获取要获取的字段的值
          fileName : 
              { 
               editable : true, //设置为可编辑
               validation : //校验:不能为空
              { 
                required : true 
              } 
              }, 
          updateTime: 
            { 
               type:"date" //设置字段类型
            } 
           
        } 
      } 
    }, 
    error: function(e) { //显示error信息
      alert(e.errors);  
      dataSource.cancelChanges(); 
    } 
                     
  });
转:http://www.tuicool.com/articles/vArqayN

KendoUI Grid 结合表单 Form 一起使用

admin阅读(2331)评论(0)

The KndoUI grid (http://demos.kendoui.com/web/grid/index.html) is defiantly proving it’s self to be one of the best javascript grid systems I have worked with.  That being said they realy have missed the mark on a few things.  One big one is no exposed on row click event that I explored and showed you how to work around here : http://sympletech.com/adding-on-row-click-to-the-kendoui-grid/.  Another which I will dive into today is the lack of an easy way to bind the grid to an on-page form.

For everything I love about the grid – it’s built in filtering and editing is just weak and an unacceptable solution for any type of grown up application.

As another pre-cursor before we get started here – this solution is setting everything up to be based on server side paging, however I’m not going to be demonstrating any back end code.  If you want to see my solution on how to get backend server side paging for the KendoUI Grid set up you can check out this post here : http://sympletech.com/hacking-on-the-kendo-ui-grid-enabling-server-side-sorting-and-paging-in-asp-net-mvc/

And with that let’s get started.  Below you will find a basic kendoUI Grid backed by server side data source.  This is where we left off here : http://sympletech.com/hacking-on-the-kendo-ui-grid-enabling-server-side-sorting-and-paging-in-asp-net-mvc/ with the addition of a form we want to use for searching our grid.

<!DOCTYPEhtml><html><head><metaname="viewport"content="width=device-width"/><title>KendoGrid </title><linkrel="stylesheet"type="text/css"href="/Content/kendo/2012.2.710/kendo.common.min.css"/><linkrel="stylesheet"type="text/css"href="/Content/kendo/2012.2.710/kendo.metro.min.css"/><scripttype="text/javascript"src="/Scripts/kendo/2012.2.710/jquery.min.js"></script>
    <script type="text/javascript" src="/Scripts/kendo/2012.2.710/kendo.web.min.js"></script>
    
    <script type="text/javascript">
        $(function () {
            var gridDataSource = new kendo.data.DataSource({
                transport: {
                    read: {
                        url: '/Home/GridData/',
                        type: "POST"
                    }
                },
                schema: {
                    data: function (data) {
                        return data.Items;
                    },
                    total: function (data) {
                        return data.TotalCount;
                    }
                },
                serverSorting: true,
                serverFiltering: true,
                serverPaging: true,
                pageSize: 5
            });

            $("#kGrid").kendoGrid({
                dataSource: gridDataSource,
                pageable: {
                    refresh: true,
                    pageSize: 5
                }
            });
        });
    </script></head><body><div><divid="kGrid"></div></div><formid="frmSearch">
        Search For : <inputname="searchTerm"/><br/>
        Some Checkbox : <inputname="somecheckbox"type="checkbox"/><br/>
        Some DropDownList : 
            <selectname="somedropdown"><option>va1 1</option><option>Val 2</option></select><inputtype="submit"/></form></body></html>

So the first thing to get our head around is that we don’t want to just try and submit the form and somehow push the results over to the grid’s data source.  This was my initial attack plan and once I got it working I found that as soon as you would page or sort the grid it would revert back to the base data source with none of the form params included in the paging and sorting posts.

What we need to do is to marry  the form to the kendoUI Grid’s data source so that every time it makes a call out to the server to change the page or to sort it includes all of the form fields in that request.  Also as we set up this relationship, it’s not good enough to just set the data source params (ie.  param1 = $(“#searchTerm”).val()) as that is only a one time lookup – we need to bind a function to the param so that every time it’s going to query the data source it recheck the param.

Ok have I lost you yet?

Lets look at some code I think it will make more sense.

//Lookup the form and serialize itvar $form = $("#frmSearch");
            var formData = $form.serialize().split('&');

            //Iterate over each form element and add it to an object collectionvar formParams = {};
            $(formData).each(function () {
                var nvp = this.split('=');

                //Instead of setting a value to the param we set up a function to get the value
                formParams[nvp[0]] = function () {
                    var $inputEl = $form.find('*name=[' + nvp[0] + ']').first();
                    return $inputEl.val();
                };
            });

 

And now to link our new form param data source provider we simply have to add it to the grid datasource.  (also as a note of clarity – the above code needs to come BEFORE the kendo grid definition.  (The complete code will be posted at the bottom)

var gridDataSource = new kendo.data.DataSource({
                transport: {
                    read: {
                        url: '/Home/GridData/',
                        type: "POST",
                        data: formParams
                    }
                },
                ....

If you refresh the page now you will see your form params are now being sent every time the grid calls out for its data source – and they change to match the value in the form with each call.

However if you hit the submit button on the form it does a standard post back and you end up on your page with a long get in the url.

The final piece of our little project is to wire up the onSubmit to tell the KendoUI Grid to go out and reload it’s data source.  We do this part AFTER the the kendo grid definition.  And we need to work against the variable returned by the $(“#kGrid”).kendoGrid() jquery extension method.

This part is pretty easy and looks like this:

var kGrid = $("#kGrid").kendoGrid({
                dataSource: gridDataSource,
                pageable: {
                    refresh: true,
                    pageSize: 5
                }
            });

            $("#frmSearch").submit(function (e) {
                e.preventDefault();

                gData.dataSource.page(1);

                kGrid.data("kendoGrid").dataSource.read();
            });

And with that we can hit the submit button and it will reload the grid.

Here is a full copy of the code:

<!DOCTYPEhtml><html><head><metaname="viewport"content="width=device-width"/><title>KendoGrid </title><linkrel="stylesheet"type="text/css"href="/Content/kendo/2012.2.710/kendo.common.min.css"/><linkrel="stylesheet"type="text/css"href="/Content/kendo/2012.2.710/kendo.metro.min.css"/><scripttype="text/javascript"src="/Scripts/kendo/2012.2.710/jquery.min.js"></script>
    <script type="text/javascript" src="/Scripts/kendo/2012.2.710/kendo.web.min.js"></script>
    
    <script type="text/javascript">
        $(function () {

            //Lookup the form and serialize itvar $form = $("#frmSearch");
            var formData = $form.serialize().split('&');

            //Iterate over each form element and add it to an object collectionvar formParams = {};
            $(formData).each(function () {
                var nvp = this.split('=');

                //Instead of setting a value to the param we set up a function to get the value
                formParams[nvp[0]] = function () {
                    var $inputEl = $form.find('*[name=' + nvp[0] + ']').first();
                    return $inputEl.val();
                };
            });



            var gridDataSource = new kendo.data.DataSource({
                transport: {
                    read: {
                        url: '/Home/GridData/',
                        type: "POST",
                        data: formParams
                    }
                },
                schema: {
                    data: function (data) {
                        return data.Items;
                    },
                    total: function (data) {
                        return data.TotalCount;
                    }
                },
                serverSorting: true,
                serverFiltering: true,
                serverPaging: true,
                pageSize: 5
            });

            var kGrid = $("#kGrid").kendoGrid({
                dataSource: gridDataSource,
                pageable: {
                    refresh: true,
                    pageSize: 5
                }
            });

            $("#frmSearch").submit(function (e) {
                e.preventDefault();
                gData.dataSource.page(1);
                kGrid.data("kendoGrid").dataSource.read();
            });
        });
    </script></head><body><div><divid="kGrid"></div></div><formid="frmSearch">
        Search For : <inputname="searchTerm"/><br/>
        Some Checkbox : <inputname="somecheckbox"type="checkbox"/><br/>
        Some DropDownList : 
            <selectname="somedropdown"><option>va1 1</option><option>Val 2</option></select><inputtype="submit"/></form></body></html>

If you like this functionality it’s all baked into my ever growing SympleLib Library you can find over on GIT Hub here : https://github.com/sympletech/SympleLib

Question, Comments, And Suggestions are always welcome!

KendoUI Grid 前后端(Java) 完整案例之查询翻页

admin阅读(6024)评论(0)

KendoUI Grid 前后端(Java 代码参考)(以下案例基于springmvc + freemarker + MyBatis + RequireJS )

前端:demo.js


require(['lib/domReady!'],     function () {

    kendo.culture("zh-CN");

    $("#grid").kendoGrid({
        dataSource: {
            transport: {
                read: {
                    url: CONTEXT_PATH + "/api/teedm01",
                    dataType: "json"
                }
            },
            pageSize: 10,
            serverPaging: true,
            serverSorting: true,
            serverFiltering: true,
            schema: {
                data: function (d) { return d.data; },
                total: function (d) { return d.count; }
            }
        },
        height: 300,
        selectable: "multiple cell",
        pageable: true,
        sortable: true,
        columns: [
            {
                field: "companyCode",
                title: "公司代码"
            },
            {
                field: "companyName",
                title: "公司名称"
            },
            {
                field: "companyTel",
                title: "公司电话"
            },
            {
                field: "companyAddr",
                title: "公司地址"
            },
            {
                field: "countryCode",
                title: "国家代码"
            },
            {
                field: "companyDate",
                title: "公司成立日期"
            }
        ]
    });

});

前端: demo.ftl

<!DOCTYPE html>
<html>
<head>
    <title>Grid单表展示</title>
    <#import "spring.ftl" as spring />
    <link rel="stylesheet" type="text/css" href="<@spring.url '/avatar/plugins/kendoui/styles/kendo.common.min.css'/>"/>
<link rel="stylesheet" type="text/css" href="<@spring.url '/avatar/plugins/kendoui/styles/kendo.blueopal.min.css'/>"/>
<link rel="stylesheet" type="text/css" href="<@spring.url '/avatar/styles/default/css/style.css'/>">
<link rel="stylesheet" type="text/css" href="<@spring.url '/avatar/styles/base.css'/>">

</head>
<body>
    <div id="example" style="margin: 0 auto ;width: 1000px;padding: 10px;">
        <div id="grid"></div>
    </div>

    <script data-main="<@spring.url '/avatar/demo/grid/basic/app.js'/>" src="<@spring.url '/avatar/js/lib/require.js'/>" ></script>
</body>
</html>

Java后端控制器:DemoController.java

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/grid")
public class DemoController{

   @RequestMapping(value="/basic", method=RequestMethod.GET)
   public String show(ModelMap model) {
      return "demo.ftl";
   }
}

Java后端Rest接口:DemoApi.java

import com.kedacom.avatar.common.entity.PageResultEntity;
import com.kedacom.avatar.common.entity.ResultEntity;
import com.kedacom.avatar.core.anotation.mapping.*;
import com.kedacom.avatar.core.base.BaseResource;
import com.kedacom.avatar.core.dao.mapper.MapperExample;
import com.kedacom.avatar.core.web.Query;
import com.kedacom.avatar.demo.grid.model.Teedm01;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.WebRequest;

import java.util.Map;

@RestController
@RequestMapping("/api/teedm01")
public class Teedm01Api extends BaseResource<Teedm01> {

    @GetManyRequestMapping
    public PageResultEntity<Teedm01> selectByMapper( @RequestParam Map<String,Object> params ){

        int offset = Query.getOffset( params );
        int limit = Query.getLimit(params);

        return super.selectByMap( params, offset, limit);
    }

    @CountRequestMapping
    private ResponseEntity count( WebRequest webRequest ){

        return super.countByExample(new MapperExample());
    }

    @GetOneRequestMapping
    public Teedm01 selectByKey( @PathVariable("id") String id  ){
        return super.selectByKey( id );
    }

    @PutRequestMapping
    public ResponseEntity<ResultEntity> update( @RequestBody Teedm01 t ){
        return super.update( t );
    }

    @PostRequestMapping
    public ResponseEntity<ResultEntity> insert( Teedm01 t ){

        return super.insert( t );
    }

    @DeleteRequestMapping
    public ResponseEntity<ResultEntity> delete( @PathVariable("id") String id ){

        return super.delete( id );
    }
}

Java后端工具类:Query.java

import org.springframework.util.StringUtils;

import java.util.Map;

public class Query {

    public static final String OFFSEET = "skip";

    public static final String LIMIT = "pageSize";

    public static final int DEFAULT_OFFSET = 0;

    public static final int DEFAULT_LIMIT = 10;

    public static int getOffset( Map params ){

        Object offset = params.get( OFFSEET );
        if(!StringUtils.isEmpty( offset )){

            try {
                return Integer.parseInt(offset.toString());
            }catch ( NumberFormatException e ){
                return DEFAULT_OFFSET;
            }
        }
        return DEFAULT_OFFSET;
    }

    public static int getLimit( Map params ){

        Object limit = params.get( LIMIT );
        if(!StringUtils.isEmpty( limit )){

            try {
                return Integer.parseInt(limit.toString());
            }catch ( NumberFormatException e ){
                return DEFAULT_LIMIT;
            }
        }
        return DEFAULT_LIMIT;
    }

}

Java后端Rest集成基类:BaseResource.java

import com.kedacom.avatar.common.ResultStatus;
import com.kedacom.avatar.common.entity.PageResultEntity;
import com.kedacom.avatar.common.entity.ResultEntity;
import com.kedacom.avatar.common.entity.ResultEntityBuilder;
import com.kedacom.avatar.core.dao.mapper.MapperExample;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.context.request.WebRequest;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public abstract class BaseResource<T> {

    @Autowired
    protected BaseService<T> baseService;

    public PageResultEntity<T> selectByExample(MapperExample example, int skip, int pageSize){

        RowBounds rowBounds = new RowBounds(skip, pageSize);

        List<T> ts = baseService.selectByExample(example, rowBounds);
        int count = baseService.countByExample(example);

        PageResultEntity<T> pageResultEntity = new PageResultEntity<T>();
        pageResultEntity.setData( ts );
        pageResultEntity.setCount( count );

        return pageResultEntity;
    }

    public PageResultEntity<T> selectByMap(Map<String, Object> params, int skip, int pageSize){

        PageResultEntity<T> pageResultEntity = getPageResultEntity(params, skip, pageSize);
        return pageResultEntity;
    }

    protected PageResultEntity<T> getPageResultEntity(Map<String, Object> params, int skip, int pageSize) {
        RowBounds rowBounds = new RowBounds(skip, pageSize);

        List<T> ts = baseService.selectByMap(params, rowBounds);
        int count = baseService.countByMap(params);

        PageResultEntity<T> pageResultEntity = new PageResultEntity<T>();
        pageResultEntity.setData( ts );
        pageResultEntity.setCount( count );
        return pageResultEntity;
    }

    public PageResultEntity<T> select(WebRequest request,int skip, int pageSize  ) {
        HashMap params = new HashMap();
        Iterator<String> it = request.getParameterNames();
        while (it.hasNext())
        {
            String key = it.next();
            if(!key.equals("take")&&!key.equals("page")&&!key.equals("pageSize")&&!key.equals("skip"))
                params.put(key,request.getParameter(key));
        }

        PageResultEntity<T> pageResultEntity = getPageResultEntity(params, skip, pageSize);
        return pageResultEntity;
    }


    public ResponseEntity<ResultEntity> countByExample(MapperExample example){

        int count = baseService.countByExample(example);
        return new ResponseEntity<ResultEntity>(ResultEntityBuilder.build().result( String.valueOf( count ) ), HttpStatus.OK);
    }

    public T selectByKey( String id  ){
        T t =baseService.selectByKey( id );
        return t;
    }

    public ResponseEntity<ResultEntity> update( T t ){
        baseService.updateByKey( t );
        ResultEntity resultEntity = ResultEntityBuilder.build().status(ResultStatus.SUCCESS).msg( "更新操作成功." );
        ResponseEntity<ResultEntity> responseEntity = new ResponseEntity<ResultEntity>( resultEntity, HttpStatus.OK);
        return responseEntity;
    }

    public ResponseEntity<ResultEntity> insert( T t ){
        baseService.insert(t);

        ResultEntity resultEntity = ResultEntityBuilder.build().status(ResultStatus.SUCCESS).msg( "新增操作成功." );
        ResponseEntity<ResultEntity> responseEntity = new ResponseEntity<ResultEntity>(resultEntity, HttpStatus.OK);
        return responseEntity;
    }

    public ResponseEntity<ResultEntity> insertPatch( List<T> t ){
        baseService.insertPatch(t);

        ResultEntity resultEntity = ResultEntityBuilder.build().status(ResultStatus.SUCCESS).msg( "批量新增操作成功." );
        ResponseEntity<ResultEntity> responseEntity = new ResponseEntity<ResultEntity>(resultEntity, HttpStatus.OK);
        return responseEntity;
    }

    public ResponseEntity<ResultEntity> delete( String id ){

        baseService.deleteByKey(id);

        ResultEntity resultEntity = ResultEntityBuilder.build().status(ResultStatus.SUCCESS).msg( "删除操作成功." );
        ResponseEntity<ResultEntity> responseEntity = new ResponseEntity<ResultEntity>( resultEntity, HttpStatus.OK);
        return responseEntity;
    }
}

Java后端业务逻辑Service:DemoService.java

import com.kedacom.avatar.core.base.BaseService;
import com.kedacom.avatar.demo.grid.model.Teedm01;
import com.kedacom.avatar.logging.AvatarLogger;
import com.kedacom.avatar.logging.AvatarLoggerFactory;
import org.apache.ibatis.session.RowBounds;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service
public class DemoService extends BaseService<Demo> {

    @Override
    public Demo selectByKey( Object key ){


        return super.selectByKey( key);
    }

    @Override
    public  List<Demo> selectByMap(Map<String, Object> params, RowBounds rowBounds)
    {
        return super.selectByMap(params, rowBounds);
    }

    @Override
    public int updateByKey( Demo teedm01 )
    {
        return super.updateByKey( teedm01 );
    }

    @Override
    public int deleteByKey(Object key){

        return super.deleteByKey( key );
    }
}