Bootstrap嵌入jqGrid,使你的table牛逼起来

Bootstrap原生的table组件只能满足简单的数据展示,满足不了更富有操作性的要求。当然了,你可以找到一款叫做“DataTables-1.10.11”的基于bootstrap的table组件,但如果你对API看得不甚了解的话,用起来可就痛苦了,但是如果你选择使用jqGrid,那么本篇教程就给你带来了解决这种富操作性table的解决方案。

一、效果展示

OK,就展示这一张图片,相信你已经爱上了bootstrap版的jqGrid,和bootstrap很兼容,简直完美,当然了,这需要我们在缘由的jqGrid上进行一些改动,同时对组件进行一定的封装。

二、资源下载

我反正挺热爱分享的,关于jqGrid的组件代码,你可以从jqGrid的官网上下载,但是下载下来需要一些改动,那么我直接将改动后的jqGrid上传到了git,你只需要把提供的文件导入到你对应的项目即可。

另外,你还需要下载一个jquery-ui-1.10.0.custom.css,我就不提供下载地址了,不过我相信,你肯定会找得到,就算是用频出事故的度娘,你也可以找得到。

三、本篇都讲一些什么

自从建了QQ群后,“络绎不绝”的有同学加入到群中,但我也发现,进群的一步人直接来找我要demo,或者项目代码,这个我可不喜欢,自己动手做一做,去实现以下,改造一下,才会是你自己的东西,完全照搬我的代码显然你得不到更多的帮助,希望以上同学学习的时候再主动一些。

说完上面这点小废话后,我们言归正传,来说说我们本篇博客主要来讲些什么,什么才是在bootstrap中嵌入jqGrid的关键所在,我总结有如下:

  1. jqGrid在bootstrap中的布局方案
  2. jqGrid自身的构造化参数
  3. jqGrid在bootstrap中的模块化
  4. jqGrid的数据操作

暂定分为以上部分来说明,但必须注意,限于篇幅,博客中只提供思路和部分代码。

①、 jqGrid在bootstrap中的布局方案

<!DOCTYPE html>
<html lang="zh-CN">

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ include file="/components/common/taglib.jsp"%>
<%@ include file="/components/common/csslib.jsp"%>

<head>
<link type="text/css" rel="stylesheet" href="${ctx}/css/deal/my_pay_list.css" />
</head>
<body>
    <div class="container">
        <form class="form-horizontal" id="jqgridForm" role="form" action="${ctx}/deal/datablePayDealOrdersList"
        method="post">
        <div class="form-group">
            <div class="col-sm-12">
                <label for="name" class="control-label pull-left">项目名称:</label>
                <div class="col-sm-3">
                    <input type="text" name="name" class="form-control" id="name" placeholder="请输入项目名称" value="" />
                </div>
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-12">
                <button type="button" class="btn btn-primary pull-right" id="searchBtn">检索</button>
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-12">
                <table id="pageGrid" rel="jqgridForm" class="jqgrid"></table>
                <div id="pageGridPager"></div>
            </div>
        </div>
    </form>
</div>
<%@ include file="/components/common/jslib.jsp"%>
<script type="text/javascript" src="${ctx}/js/deal/my_pay_list.js"></script>
</body>
</html>

介于每个人的项目千差万别,列出的代码中我们只关注jqGrid部分:

  1. id="jqgridForm",此处我们为jqGrid包含一层检索条件的form表单,也就是效果图上列出的search部分,当点击检索按钮时,就把form表单域的查询条件提交到controller,进而获取的数据。
  2. id="searchBtn",定义检索按钮,后面讲模块化会用得到。
  3. <table id="pageGrid" rel="jqgridForm" class="jqgrid"></table> <div id="pageGridPager"></div>定义jqGrid的table元素和jqGrid的footer元素,使用的规则我的项目暂时约定这种规则,你也可以有你自己的规则。通过rel指定form的id,可以更便捷的使用table的检索form。

②、 jqGrid自身的构造化参数

构造化参数,我把他提取到了①中的my_pay_list.js中。

$(function() {
    var jqOption = {
        datatype : "xml",
        mtype : "POST",
        shrinkToFit : true,
        viewrecords : false,
        rownumbers : false,
        autowidth : true,
        height : "100%",
        colNames : [ ‘id‘, ‘status‘, ‘项目信息‘, ‘项目状态‘, ‘订单号‘, ‘项目名称‘, ‘下单时间‘, ‘支付金额‘, ‘支持数量‘, ‘订单状态‘, ‘操作‘ ],
        colModel : [
                {
                    name : ‘id‘,
                    index : ‘id‘,
                    hidden : true
                },
                {
                    name : ‘status‘,
                    index : ‘status‘,
                    hidden : true
                },
                {
                    name : ‘image_str‘,
                    index : ‘image_str‘,
                    width : 140,
                    resizable : false,
                    sortable : false,
                    formatter : function(cellvalue, options, rowObject) {
                        if (cellvalue == ‘支付总花费:‘) {
                            return cellvalue;
                        }

                    },
                    align : ‘left‘
                }, {
                    name : ‘oper‘,
                    index : ‘oper‘,
                    width : 90,
                    resizable : false,
                    sortable : false,
                    align : ‘center‘,
                    formatter : function(cellvalue, options, rowObject) {
                        var status = parseInt($(rowObject).find("status").text());
                        var id = $(rowObject).find("id").text();
                        if (status == 0) {
                            return ‘<a class="color0088cc" width="700" target="dialog" href="‘ + common.ctx + ‘/deal/initPayg/‘ + id + ‘">去支付</a>‘;
                        }

                        if (status == 1 || status == 3) {
                            return ‘<a class="color0088cc" target="_blank"  href="‘ + common.ctx + ‘/deal/showDealOr/‘ + id + ‘">查看详情</a>‘;
                        }

                        if (status == 2) {
                            return ‘<a class="color0088cc" target="ajaxTodo" href="‘ + common.ctx + ‘/deal/receivder/‘ + id + ‘">确认收货</a>‘;
                        }

                    },
                } ],
        xmlReader : {
            repeatitems : false,
            root : "PageGrid",
            row : "map",
            page : ‘page‘,
            total : ‘total‘,
            records : ‘records‘,
            id : ‘ID‘
        },
        rowNum : 50,
        rowList : [ 50, 100, 200, 300 ],
        pager : "#pageGridPager",
        footerrow : true,
        loadError : YUNM.ajaxError,
        gridComplete : function() {
            var $form = $("#" + $("#pageGrid").attr("rel"));
            $.ajax({
                type : $form.method || ‘POST‘,
                url : common.ctx + "/deal/getAllOrded",
                data : $form.serializeArray(),
                dataType : "json",
                cache : false,
                success : function(json) {
                    $("#pageGrid").footerData("set", {
                        image_str : "支付总花费:",
                        order_price : json.message
                    });
                },
                error : YUNM.ajaxError
            });

            if ($.fn.ajaxTodo) {
                $("a[target=ajaxTodo]", $("#pageGrid")).ajaxTodo();
            }

            // dialog
            if ($.fn.ajaxTodialog) {
                $("a[target=dialog]", $("#pageGrid")).ajaxTodialog();
            }
        },
    };
    initEnv(jqOption);
});

一点都不熟悉jqGrid的同学,建议先看jqGrid的demo,以及jqGrid的官方文档,当然了,对于已经熟悉jqGrid的同学,doc和demo肯定是必看的。

以上文件列出的属性非常多,对于jqGrid,我不做过多的介绍,本篇的主旨主要来介绍如何将jqGrid嵌入到bootstrap,那么重点就不在于介绍jqGrid上,我只介绍几个关键点:

  1. formatter: function(cellvalue, options, rowObject) {,formatter还是很经常要使用的,那么对于如何获得对应单元格的值就很重要,我的jqGrid使用的是xml(datatype : “xml”)数据格式,那么可通过$(rowObject).find("deal_id").text()找到对应deal_id列的值。
  2. xmlReader : { repeatitems : false, root : "PageGrid",,注意xmlReader中的参数值,在接下来介绍④jqGrid的数据操作会细节介绍,和后台的xml数据封装有关系。
  3. $("#pageGrid").footerData("set", {image_str : "支付总花费:", order_price : json.message});,关于footerData方法,使用起来也很方便,效果可参照效果图。
  4. initEnv(jqOption);方法,在页面onload后,我们将jqGrid的初始化参数传递给initEnv方法,后续③jqGrid在bootstrap中的模块化会介绍initEnv方法。

③、jqGrid在bootstrap中的模块化

②中我们注意到initEnv方法,那么这个方法内部就是专门针对jqGrid做的模块化封装工作。

initEnv方法

function initEnv(jqOption) {

    $(window).resize(function() {
        initLayout();
    });

    initUI(null, jqOption);
}

该方法中,我们将会看到initLayout方法和initUI方法,具体内容稍候介绍。

initLayout

function initLayout() {
    $("table[rel=jqgridForm]").each(function() {
        var rel = $(this).attr("rel");
        if (rel) {
            var $form = $("#" + rel);
            var tableWidth = $form.width();
            $(this).setGridWidth(tableWidth, true);
        }
    });
}

也就是说,在窗口缩放的时候,我们为jqGrid重新绘制宽度,使其自适应于bootstrap的响应式布局。使用的方法就是jqGrid的setGridWidth方法。

initUI

function initUI(_box, jqOption) {
    var $p = $(_box || document);
    if (jqOption) {
        YUNM.debug("初始化jqgrid");

        var $form = $("#" + $("#pageGrid").attr("rel"));

        YUNM.debug(YUNM.array2obj($form.serializeArray()));

        // 初始化
        var op = $.extend({
            url : $form.attr("action"),
            postData : YUNM.array2obj($form.serializeArray()),
        }, jqOption);
        $("#pageGrid").jqGrid(op);

        // 检索按钮
        $("#searchBtn", $form).click(function() {
            $("#pageGrid").jqGrid(‘setGridParam‘, {
                url : $form.attr("action"),
                page : 1,
                postData : YUNM.array2obj($form.serializeArray()),
            });
            $("#pageGrid").trigger("reloadGrid");

        });

        // toolbar,将button的圆角去掉
        $(".btn", $form).each(function() {
            var $this = $(this);
            $this.css({
                "border-radius" : "0px",
                "border-bottom" : "0",
            });
        });

    }
}
array2obj : function(array) {
    var params = $({});
    $.each(array, function(i) {
        var $param = $(this)[0];
        params.attr($param.name, $param.value);
    });
    return params[0];
},

如果你曾看过我之前的系列文章,对于initUi方法就不会太陌生,熟悉dwz的朋友,自然也不会陌生,我项目中的大部分模板还是依赖于dwz,谢谢这些前辈们。

  1. var $form = $("#" + $("#pageGrid").attr("rel"));由于我们在jqGrid上关联了form检索条件的form表单,此处就可以将form表单对象取到,取到form表单对象,自然也就去得到了检索域的值($form.serializeArray())。
  2. 拿到form表单的检索域值后,此时就需要做一番处理了。我们知道,jqGrid在向controller传递参数时,必然需要上送分页、排序的相关字段(page、rows、sord、sidx),使用的方法是$("#pageGrid").jqGrid({postData:xxx});,通常情况下,我们上送form表单时,只需要使用$form.serializeArray()就可以,但如果此时,只是将xxx替换为$form.serializeArray(),那么controller中将不会获得分页、排序的相关字段(page、rows、sord、sidx),这是一个冲突,此时怎么处理呢?解决办法就是将form表单数据对象化(array2obj 方法),然后我们再通过var op =$.extend({url:$form.attr("action"),postData:YUNM.array2obj($form.serializeArray()),},jqOption);$("#pageGrid").jqGrid(op);将检索域的值和分页、排序的相关字段一起上送到controller。
  3. $("#searchBtn", $form).click通过封装click事件,将jqGrid的数据重新加载。
  4. $(".btn", $form).each(function() {此处的方法将检索button去圆角,使其更贴合jqGrid,见效果图。

④ 、jqGrid的数据操作

数据操作部分,我认为包含有 检索参数传递、分页排序参数传递、sql语句的编写。

关于参数传递,前端的参数封装在③中已有介绍,我们来看一看controller中如何处理数据的。

首先,我们来定义PageGrid,也就是jqGrid中xmlReader的数据源。

package com.honzh.common.page;

import java.util.List;

import com.thoughtworks.xstream.annotations.XStreamAlias;

@XStreamAlias("pageGrid")
@SuppressWarnings("rawtypes")
public class PageGrid {
    private int page;
    private int total;
    private int records;

    private List data;

    public int getPage() {
        return this.page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public int getTotal() {
        return this.total;
    }

    public void setTotal(int total) {
        this.total = total;
    }

    public int getRecords() {
        return this.records;
    }

    public void setRecords(int records) {
        this.records = records;
    }

    public List getData() {
        return this.data;
    }

    public void setData(List data) {
        this.data = data;
    }
}

项目中需要xstream.jar,自行下载。

XStreamComponent.java

package com.honzh.common.page;

import org.apache.commons.lang.StringUtils;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.mapper.DefaultMapper;
import com.thoughtworks.xstream.mapper.XStream11XmlFriendlyMapper;

public class XStreamComponent {
    private XStream xstream;

    public static XStreamComponent newInstance() {
        XStreamComponent xmlComponent = new XStreamComponent();
        xmlComponent.alias(new Class[] { PageGrid.class });

        return xmlComponent;
    }

    public XStreamComponent() {
        this.xstream = new XStream(new DomDriver());
    }

    public String toXML(Object obj) {
        return this.xstream.toXML(obj);
    }

    public String toPageXML(Object obj) {
        registerConverter(new MapCustomConverter(new DefaultMapper(XStream11XmlFriendlyMapper.class.getClassLoader())));
        return toXML(obj);
    }

    public Object fromPageXML(String xml) {
        registerConverter(new MapCustomConverter(new DefaultMapper(XStream11XmlFriendlyMapper.class.getClassLoader())));
        return fromXML(xml);
    }

    public Object fromXML(String xml) {
        return this.xstream.fromXML(xml);
    }

    @SuppressWarnings("rawtypes")
    public void processAnnotations(Class type) {
        this.xstream.processAnnotations(type);
    }

    @SuppressWarnings("rawtypes")
    public void processAnnotations(Class[] types) {
        this.xstream.processAnnotations(types);
    }

    @SuppressWarnings("rawtypes")
    public void alias(String name, Class type) {
        this.xstream.alias(name, type);
    }

    @SuppressWarnings("rawtypes")
    public void alias(Class[] types) {
        for (Class type : types) {
            String className = type.getName();
            try {
                String[] classNames = StringUtils.split(className, ".");
                this.xstream.alias(classNames[(classNames.length - 1)], type);
            } catch (Exception ex) {
                this.xstream.alias(className, type);
            }
        }
    }

    public void registerConverter(Converter converter) {
        this.xstream.registerConverter(converter);
    }

    @SuppressWarnings("rawtypes")
    public void useAttributeFor(Class definedIn, String fieldName) {
        this.xstream.useAttributeFor(definedIn, fieldName);
    }
}

主要将pageGrid封装为xml对象,进而传递会前端。

MapCustomConverter.java

package com.honzh.common.page;

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

import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;

public class MapCustomConverter extends AbstractCollectionConverter {
    public MapCustomConverter(Mapper mapper) {
        super(mapper);
    }

    @SuppressWarnings("rawtypes")
    public boolean canConvert(Class type) {
        return (type.equals(HashMap.class)) || (type.equals(Hashtable.class))
                || (type.getName().equals("java.util.LinkedHashMap"))
                || (type.getName().equals("sun.font.AttributeMap"));
    }

    @SuppressWarnings({ "rawtypes" })
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        Map map = (Map) source;
        for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) {
            Map.Entry entry = (Map.Entry) iterator.next();
            writer.startNode(entry.getKey() == null ? "null" : entry.getKey().toString());
            writer.setValue(entry.getValue() == null ? "" : entry.getValue().toString());
            writer.endNode();
        }
    }

    @SuppressWarnings("rawtypes")
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        Map map = (Map) createCollection(context.getRequiredType());
        populateMap(reader, context, map);
        return map;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected void populateMap(HierarchicalStreamReader reader, UnmarshallingContext context, Map map) {
        while (reader.hasMoreChildren()) {
            reader.moveDown();
            Object key = reader.getNodeName();
            Object value = reader.getValue();
            map.put(key, value);
            reader.moveUp();
        }
    }
}

主要将数据库中获取的hashmap转换为标准的xml格式数据。

BaseConditionVO.java

package com.honzh.common.persistence;

import java.util.HashMap;
import java.util.Map;

import org.apache.ibatis.session.RowBounds;

/**
 * 分页查询时的参数设置类.<br>
 *
 * <P>
 * 1.PAGE_SHOW_COUNT──当然默认一页显示10。<br>
 * 2.pageNum──第几页。<br>
 * 3.numPerPage──一页显示多少,为空时,显示PAGE_SHOW_COUNT。<br>
 * 4.totalCount──总共数目。totalCount/numPerPage=多少页<br>
 * 5.orderField──排序的列。<br>
 * 6.orderDirection──排序的方向。
 * </P>
 */
public class BaseConditionVO {
    public final static int PAGE_SHOW_COUNT = 50;
    private int pageNum = 1;
    private int numPerPage = 0;
    private long totalCount = 0;
    private String orderField = "";
    private String orderDirection = "";

    /**
     * @Fields ps : 对参数类型进行封装.
     */
    private Map<String, Object> mo = new HashMap<String, Object>();

    public int getPageNum() {
        return pageNum;
    }

    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }

    public int getNumPerPage() {
        return numPerPage > 0 ? numPerPage : PAGE_SHOW_COUNT;
    }

    public void setNumPerPage(int numPerPage) {
        this.numPerPage = numPerPage;
    }

    public String getOrderField() {
        return orderField;
    }

    public void setOrderField(String orderField) {
        this.orderField = orderField;
    }

    public String getOrderDirection() {
        return "desc".equals(orderDirection) ? "desc" : "asc";
    }

    public void setOrderDirection(String orderDirection) {
        this.orderDirection = orderDirection;
    }

    public long getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(long totalCount) {
        this.totalCount = totalCount;
    }

    public int getStartIndex() {
        int pageNum = this.getPageNum() > 0 ? this.getPageNum() - 1 : 0;
        return pageNum * this.getNumPerPage();
    }

    public RowBounds createRowBounds() {
        RowBounds ro = new RowBounds(this.getStartIndex(), this.getNumPerPage());
        return ro;
    }

    /**
     * @Title: addParams
     * @Description: 添加查询条件
     * @param key
     * @param value
     */
    public void addParams(String key, Object value) {
        this.getMo().put(key, value);
    }

    /**
     * @Title: getParams
     * @Description: 获取查询条件
     * @param key
     * @return
     */
    public Object getParams(String key) {
        return this.getMo().get(key);
    }

    /**
     * @return the mo
     */
    public Map<String, Object> getMo() {
        return mo;
    }

    /**
     * @param mo
     *            the mo to set
     */
    public void setMo(Map<String, Object> mo) {
        this.mo = mo;
    }

    @Override
    public String toString() {
        return "条件:" + pageNum + "," + numPerPage + "," + totalCount + "," + orderField + "," + orderDirection + ","
                + mo;
    }
}

分页的查询数据对象,包括分页、排序、检索域。

    protected BaseConditionVO getBaseConditionVOForTable() {
        BaseConditionVO vo = new BaseConditionVO();
        // 分页的参数
        int currentPage = getParaToInt("page");
        int sizes = getParaToInt("rows");
        String sortOrder = getPara("sord");
        String sortCol = getPara("sidx");
        vo.setNumPerPage(sizes);
        vo.setPageNum(currentPage);
        vo.setOrderField(sortCol);
        vo.setOrderDirection(sortOrder);

        return vo;
    }

将jqGrid传递的参数转换为BaseConditionVO分页查询对象。

protected void renderXml(HttpServletResponse res, String xmlResponse) {
        try {
            res.setCharacterEncoding("UTF-8");
            res.setHeader("Content-type", "text/xml");
            PrintWriter out = res.getWriter();
            out.print(xmlResponse);
            if (out != null) {
                out.close();
            }
        } catch (IOException e) {
            logger.error(e.getMessage());
            logger.error(e.getMessage(), e);
        }

    }

将xml写入到输出流中。

定义完了这些基础的对象,接下来,我们就要着手获取数据和传递数据了。

@SuppressWarnings("rawtypes")
    @RequestMapping(value = "datablePayDealOrdersList")
    public void datablePayDealOrdersList(HttpServletResponse response) {
        try {
            logger.debug("获取我支付的订单");

            XStreamComponent xstreamComponent = XStreamComponent.newInstance();
            // 获取列表参数
            BaseConditionVO vo = getBaseConditionVOForTable();
            vo.addParams("name", getPara("name"));

            logger.debug("我支付的订单查询" + vo);

            // 我创建的项目
            List myDealOrders = dealOrderService.getByIssueUid(vo, vo.createRowBounds());
            Long count = dealOrderService.searchIssueTotalCount(vo);

            String xmlResponse = xstreamComponent.toPageXML(createPageGrid(myDealOrders, vo, count.intValue()));

            renderXml(response, xmlResponse.replaceAll("__", "_"));
        } catch (UncategorizedSQLException e) {
            logger.error(e.getMessage());
            logger.error(e.getMessage(), e);

            renderXml(response, Constants.QUERY_ERROR);
        } catch (Exception e) {
            logger.error(e.getMessage());
            logger.error(e.getMessage(), e);

            renderXml(response, Constants.SERVER_ERROR);
        }
    }

我们来详细说明一下:

1. XStreamComponent.newInstance()创建xml流对象。

2. BaseConditionVO vo = getBaseConditionVOForTable();创建分页查询参数对象。

3. vo.addParams("name", getPara("name"));将检索域的值放入到查询对象中。

4. dealOrderService.getByIssueUid(vo, vo.createRowBounds());mybatis的分页查询方式,超简单,之前一个群里的朋友专门做了一种mybatis的分页组件,我觉得用原始的mybatis查询方法更有效率,之后,我们会写出对应的mybatis中xml的sql写法。

5. renderXml(response, xmlResponse.replaceAll("__", "_"));将数据写入到jsp的out输出流中。

最后,我们来介绍,通过mybatis如何获取分页数据。

mapper.java

package com.honzh.biz.database.mapper;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;

import org.apache.ibatis.session.RowBounds;

import com.honzh.common.persistence.BaseConditionVO;

public interface DealOrderMapper {
    @SuppressWarnings("rawtypes")
    List<HashMap> getByIssueUid(BaseConditionVO vo, RowBounds createRowBounds);
}

想mapper.xml传递的两个对象,分别是BaseConditionVO 还有分页的RowBounds ,xml中sql就会自动分页。

mapper.xml

<select id="getByIssueUid" resultType="hashmap" parameterType="map">
        select * from daa
        WHERE is_delete=0

        <if test="mo.name != null and mo.name != ‘‘">
            and y.name like CONCAT(‘%‘,‘${mo.name}‘,‘%‘)
        </if>

         <choose>
            <when test="orderField !=null and orderField !=‘‘">
                 ORDER BY ${orderField} <if test="orderDirection != null and orderDirection != ‘‘">${orderDirection}</if>
            </when>
            <otherwise>
                 order by d.order_time DESC
            </otherwise>
        </choose>
    </select>
  1. 你完全可以不关注RowBounds ,mybatis内部会自动为你封装好limit的。
  2. 检索域的name可以直接通过mo.name或得到。
  3. orderField、orderDirection也传递过来了。

到此为止,整篇的Bootstrap嵌入jqGrid就圆满结束了,ok,使你的table牛逼起来吧!


感谢您阅读【沉默王二的博客】,如果王二的博客给您带来一丝帮助或感动,我(也就是王二)将不甚荣幸。

如果您碰巧喜欢,可以留言或者 加qq群120926808,这将是我鼓捣更多优秀文章的最强动力。

时间: 2024-10-05 19:58:47

Bootstrap嵌入jqGrid,使你的table牛逼起来的相关文章

Bootstrap dropdown menu within a responsive table

Bootstrap 的 dropdown menu 在 responsive table内 会被外层遮挡住 解决办法: $('.table-responsive').on('show.bs.dropdown', function () { $('.table-responsive').css( "overflow", "inherit" ); }); $('.table-responsive').on('hide.bs.dropdown', function ()

程序员别迷茫,通往牛逼的道路有很多

有个网友给我留言,说看了我的上篇文章<三个月不工作,我才转行成了程序员>,感触很深,自己和奶爸的经历类似,也是从其它行业,转到IT圈做了一名程序员.如今已有2年时间,大大小小也参与了一些系统开发项目,可如今感觉机械化的重复写程序很没有意思,再转一次行成本太大,如今年龄也不小了,不想再折腾.不知道下一步该怎么办? 看到他的困惑,如同看到了当年奶爸自己,自己也是摸着石头过河,才一步步走上岸来.我想对有类似困惑的朋友说,不要完全怀疑自己当初的选择,因为IT这条路很宽,一条路走不通,试试其它的,通往牛

为什么美国学生学的数学比我们简单却还能做出很牛逼的东西?

听说过这样一种说法:美国初中生学的数学是咱们国家小学生学的水平,美国高中生学的数学是咱们国家初中的水平.(不知道对不对) 那么,为什么很多需要数学的东西(比如计算机图形学领域)都是人家做出来的而不是咱们 ?算法对数学的要求够大了吧? PPS:一个类似的回答,有启发意义:美国高中教育那么粗浅,大学教育那么尖端,中间的 Gap 怎么搞定? 私以为 @倪大为 同学引用的答案说的是最正确的.特此赞同一下:"美国给予不热爱数学的学生最基础的数学教育,而给予热爱数学的天才最高水平的数学教育." 长久以来,中

如何定义一个牛逼的前端工程师

有软件工程方面的研究说,对于开发者个体而言,最优秀的开发者的生产效率约为平均值的2倍,而优秀的开发者会吸引其它优秀的人,或者激励与帮助团队中的其它成员,最终使团队之间的生产效率差异达到10倍之多. 所谓牛逼的工程师,就是那些个体效率是其它人2倍,形成团队之后达到10倍差异的一群人. 前端领域这几年发展速度非常快,人才分布呈两级分化趋势,大家都在说缺前端,其实缺的是牛逼前端,对于低端的前端,培训机构一直在量产,但是无法满足要求.很多情况下,一个牛逼前端对于团队的价值是再多低端前端都无法提供的. 牛

成为牛逼的程序员

Tip 1 要方法而不是记忆 我的一个程序员朋友常跟我说记住超过200个C++函数是多么的有帮助."我从来不必去查找函数的定义,因此我可以比其他程序员编程快上50%."他自豪的说.可结果是什么? 难道他不知道编译器的代码自动完成功能可以节约大量查找函数及输入函数的时间吗,另外当C#发布出来后,他在记忆函数上面的努力就白费了.当然,编程中对函数的熟记是一件 必需的事情,但是你应当花费更多的时间在学习做事的方法上,比如说创建一个数据库连接,如何产生RSS源等,然后是关注于代码是如何实现的.

嗯,太牛逼了

以前听很多人说话,总是喜欢笑他们说话时带口头禅,比如无数遍的说,"呃,这个-这个-这个-balabala-"或者,"然后-然后-然后-balabala-" 今天我发现我也有这毛病,比如,"哎,那人太牛逼了","哎,那学校太牛逼了". 我喜欢说"太牛逼了". 如果不是聊天时麦基说起两次,"友哥哥总是爱说太牛逼",我还不知道自己说话时有这个毛病. 说太牛逼,有点不登大雅了,哈哈-- 当我对有

我喜欢ASP.NET的MVC因为它牛逼的9大理由(转载)

我很早就关注ASP.NET的mvc的,因为最开始是学了Java的MVC,由于工作的原因一直在做.Net开发,最近的几个新项目我采用了MVC做了,我个一直都非常喜欢.Net的MVC.我们为什么使用MVC而不是用WebForm呢?下面就来说说MVC的亮点.由于我最近使用都是MVC5.0和EF6.1,所以下面的所有实例都是基于这两个版本的. 1.创建项目内置了Bootsrap Bootsrap是一个响应式的UI界面库,能快速的搭建响应式界面,如果没有美工,对界面要求不是很高的话完全可以直接作用,很方便

【项目总结】:如何做一个牛逼的Team leader?

随着ITOO高校云平台3.1项目的结束,我们各种各样的总结也被提上了日程.Java版本的所有开发人员和Donet版本的所有开发人员坐在一起进行了关于项目开发管理的头脑风暴,虽然我只是Donet开发组的一个子系统--考评系统的模块开发人员,但是对于项目开发管理也有自己的一些思考和看法. 众所周知,作为一个Teamleader,是要考虑很多很多事情的,如何调动团队成员的积极性,如何统筹安排团队成员分工合作,使工作效率达到最佳,如何根据开发人员的技术水平.经验以及个人性格等诸多因素为他们分配任务,以使

【项目总结】:怎样做一个牛逼的Team leader?

随着ITOO高校云平台3.1项目的结束,我们各种各样的总结也被提上了日程. Java版本号的全部开发者和Donet版本号的全部开发者坐在一起进行了关于项目开发管理的头脑风暴,尽管我仅仅是Donet开发组的一个子系统--考评系统的模块开发者.可是对于项目开发管理也有自己的一些思考和看法. 众所周知.作为一个Teamleader,是要考虑非常多非常多事情的,怎样调动团队成员的积极性,怎样统筹安排团队成员分工合作,使工作效率达到最佳,怎样依据开发者的技术水平.经验以及个人性格等诸多因素为他们分配任务.