JS表格组件BootstrapTable行内编辑解决方案x-editable


Posted in Javascript onSeptember 01, 2016

前言:之前介绍bootstrapTable组件的时候有提到它的行内编辑功能,只不过为了展示功能,将此一笔带过了,罪过罪过!最近项目里面还是打算将行内编辑用起来,于是再次研究了下x-editable组件,遇到过一些坑,再此做个采坑记录吧!想要了解bootstrapTable的朋友可以移步JS组件系列——表格组件神器:bootstrap table。

一、x-editable组件介绍 

x-editable组件是一个用于创建可编辑弹出框的插件,它支持三种风格的样式:bootstrap、Jquery UI、Jquery。大致效果如下图: 

JS表格组件BootstrapTable行内编辑解决方案x-editable

根据博主一贯的风格,这里肯定是选用第一种喽。首先还是给出开源地址吧。 
x-editable开源地址:https://github.com/vitalets/x-editable 
x-editable文档地址:http://vitalets.github.io/x-editable/docs.html 
x-editable在线Demo:http://vitalets.github.io/x-editable/demo-bs3.html 

 1、x-editable初体验

首先下载基于bootstrap的源码到本地。引用相关文件。

<link href="/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/bootstrap3-editable/css/bootstrap-editable.css" rel="stylesheet" />

<script src="/Scripts/jquery-1.9.1.min.js"></script>
<script src="/Content/bootstrap/js/bootstrap.min.js"></script>
<script src="~/Content/bootstrap3-editable/js/bootstrap-editable.js"></script>

页面元素

<a href="#" id="username" data-type="text" data-title="用户名">用户名</a>

js初始化

$(function () {
 $('#username').editable();
 });

效果展示

JS表格组件BootstrapTable行内编辑解决方案x-editable

上面是通过html的data属性去设置x-editable的参数,当然,我也可以在初始化的时候去设置参数,比如,我仅仅给一个空的a标签:<a href="#" id="username">用户名</a>

js初始化 

$(function () {
 $('#username').editable({
 type: "text", //编辑框的类型。支持text|textarea|select|date|checklist等
 title: "用户名", //编辑框的标题
 disabled: false, //是否禁用编辑
 emptytext: "空文本", //空值的默认文本
 mode: "inline", //编辑框的模式:支持popup和inline两种模式,默认是popup
 validate: function (value) { //字段验证
 if (!$.trim(value)) {
 return '不能为空';
 }
 }
 });

 });

查看效果

JS表格组件BootstrapTable行内编辑解决方案x-editable

再来个稍微复杂一点的
 <a href="#" id="department">选择部门</a>

$(function () {
 $('#department').editable({
 type: "select", //编辑框的类型。支持text|textarea|select|date|checklist等
 source: [{ value: 1, text: "开发部" }, { value: 2, text: "销售部" }, {value:3,text:"行政部"}],
 title: "选择部门", //编辑框的标题
 disabled: false, //是否禁用编辑
 emptytext: "空文本", //空值的默认文本
 mode: "popup", //编辑框的模式:支持popup和inline两种模式,默认是popup
 validate: function (value) { //字段验证
 if (!$.trim(value)) {
 return '不能为空';
 }
 }
 });

 });

查看效果

JS表格组件BootstrapTable行内编辑解决方案x-editable

上文只是给出了一些常用字段,当然x-editable组件还有很多其他的功能参数,有兴趣可以看看文档,官方文档对每个参数都有详细的说明。

二、bootstrapTable行内编辑初始方案

说了这么半天,上面的只是铺垫,我们最终是希望在bootstrapTable里面实现行内编辑。根据上面的规则,我们想要使用x-editable实现行内编辑,表格的单元格里面必须要有一个a标签,然后对a标签做x-editable的初始化。有了这个想法,我们按照这种思路先试试。

引用相关文件 

<link href="/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/bootstrap3-editable/css/bootstrap-editable.css" rel="stylesheet" />
<link href="/Content/bootstrap-table/bootstrap-table.min.css" rel="stylesheet" />

<script src="/Scripts/jquery-1.9.1.min.js"></script>
<script src="/Content/bootstrap/js/bootstrap.min.js"></script>
<script src="~/Content/bootstrap3-editable/js/bootstrap-editable.js"></script>
<script src="~/Content/bootstrap-table/bootstrap-table.js"></script>
<script src="/Content/bootstrap-table/locale/bootstrap-table-zh-CN.js"></script>

bootstrapTable的相关初始化 

<script type="text/javascript">
 var curRow = {};
 $(function () {
 $("#tb_user").bootstrapTable({
 toolbar: "#toolbar",
 idField: "Id",
 pagination: true,
 showRefresh: true,
 search: true,
 clickToSelect: true,
 queryParams: function (param) {
 return {};
 },
 url: "/Editable/GetUsers",
 columns: [{
 checkbox: true
 }, {
 field: "UserName",
 title: "用户名",
 formatter: function (value, row, index) {
 return "<a href=\"#\" name=\"UserName\" data-type=\"text\" data-pk=\""+row.Id+"\" data-title=\"用户名\">" + value + "</a>";
 }
 }, {
 field: "Age",
 title: "年龄",
 }, {
 field: "Birthday",
 title: "生日",
 formatter: function (value, row, index) {
 var date = eval('new ' + eval(value).source)
 return date.format("yyyy年MM月dd日");
 }
 },
 {
 field: "DeptName",
 title: "部门"
 }, {
 field: "Hodd",
 title: "爱好"
 }],
 onClickRow: function (row, $element) {
 curRow = row;
 },
 onLoadSuccess: function (aa, bb, cc) {
 $("#tb_user a").editable({
 url: function (params) {
 var sName = $(this).attr("name");
 curRow[sName] = params.value;
 $.ajax({
 type: 'POST',
 url: "/Editable/Edit",
 data: curRow,
 dataType: 'JSON',
 success: function (data, textStatus, jqXHR) {
 alert('保存成功!');
 },
 error: function () { alert("error");}
 });
 },
 type: 'text'
 });
 },
 });
 });</script>

后台方法 

后台测试方法

public JsonResult GetUsers()
 {
 var lstRes = new List<User>();
 lstRes.Add(new User() { Id = "1", UserName = "张三", Age = 22, Birthday = Convert.ToDateTime("1994-12-21"), DeptId = "1", DeptName = "研发部" });
 lstRes.Add(new User() { Id = "2", UserName = "李四", Age = 28, Birthday = Convert.ToDateTime("1988-09-09"), DeptId = "2", DeptName = "销售部" });
 lstRes.Add(new User() { Id = "3", UserName = "风衣大叔", Age = 40, Birthday = Convert.ToDateTime("1976-09-01"), DeptId = "2", DeptName = "销售部" });
 lstRes.Add(new User() { Id = "4", UserName = "闪电大虾", Age = 37, Birthday = Convert.ToDateTime("1979-03-12"), DeptId = "4", DeptName = "创意部" });
 lstRes.Add(new User() { Id = "5", UserName = "韩梅梅", Age = 29, Birthday = Convert.ToDateTime("1987-05-01"), DeptId = "5", DeptName = "事业部" });

 return Json(lstRes, JsonRequestBehavior.AllowGet);
 }

 public JsonResult Edit(User user)
 {
 //反序列化之后更新

 return Json(new { }, JsonRequestBehavior.AllowGet);
 }

JS表格组件BootstrapTable行内编辑解决方案x-editable

这样确实是可以实现想要的效果,貌似也能行内编辑了,可是如果没个列都需要行内编辑,并且列的个数很多,那么是不是每个列都得这样去formmater?并且这种写法狠显然很死板,博主着实难以接受。于是又找了找例子,发现在bootstrapTable的扩展里面存在bootstrap-table-editable.js这个js。

三、bootstrapTable行内编辑最终方案

好吧,博主承认,上面还是铺垫,因为博主觉得这可能是解决问题的一般思路,所以将这些铺垫的篇幅可能有点多。首先来看看bootstrap-table-editable.js这个文件:

/**
 * @author zhixin wen <wenzhixin2010@gmail.com>
 * extensions: https://github.com/vitalets/x-editable
 */

!function ($) {

 'use strict';

 $.extend($.fn.bootstrapTable.defaults, {
 editable: true,
 onEditableInit: function () {
 return false;
 },
 onEditableSave: function (field, row, oldValue, $el) {
 return false;
 },
 onEditableShown: function (field, row, $el, editable) {
 return false;
 },
 onEditableHidden: function (field, row, $el, reason) {
 return false;
 }
 });

 $.extend($.fn.bootstrapTable.Constructor.EVENTS, {
 'editable-init.bs.table': 'onEditableInit',
 'editable-save.bs.table': 'onEditableSave',
 'editable-shown.bs.table': 'onEditableShown',
 'editable-hidden.bs.table': 'onEditableHidden'
 });

 var BootstrapTable = $.fn.bootstrapTable.Constructor,
 _initTable = BootstrapTable.prototype.initTable,
 _initBody = BootstrapTable.prototype.initBody;

 BootstrapTable.prototype.initTable = function () {
 var that = this;
 _initTable.apply(this, Array.prototype.slice.apply(arguments));

 if (!this.options.editable) {
 return;
 }

 $.each(this.columns, function (i, column) {
 if (!column.editable) {
 return;
 }

 var _formatter = column.formatter;
 column.formatter = function (value, row, index) {
 var result = _formatter ? _formatter(value, row, index) : value;

 return ['<a href="javascript:void(0)"',
 ' data-name="' + column.field + '"',
 ' data-pk="' + row[that.options.idField] + '"',
 ' data-value="' + result + '"',
 '>' + '</a>'
 ].join('');
 };
 });
 };

 BootstrapTable.prototype.initBody = function () {
 var that = this;
 _initBody.apply(this, Array.prototype.slice.apply(arguments));

 if (!this.options.editable) {
 return;
 }

 $.each(this.columns, function (i, column) {
 if (!column.editable) {
 return;
 }

 that.$body.find('a[data-name="' + column.field + '"]').editable(column.editable)
 .off('save').on('save', function (e, params) {
 var data = that.getData(),
 index = $(this).parents('tr[data-index]').data('index'),
 row = data[index],
 oldValue = row[column.field];

 row[column.field] = params.submitValue;
 that.trigger('editable-save', column.field, row, oldValue, $(this));
 });
 that.$body.find('a[data-name="' + column.field + '"]').editable(column.editable)
 .off('shown').on('shown', function (e, editable) {
 var data = that.getData(),
 index = $(this).parents('tr[data-index]').data('index'),
 row = data[index];
 
 that.trigger('editable-shown', column.field, row, $(this), editable);
 });
 that.$body.find('a[data-name="' + column.field + '"]').editable(column.editable)
 .off('hidden').on('hidden', function (e, reason) {
 var data = that.getData(),
 index = $(this).parents('tr[data-index]').data('index'),
 row = data[index];
 
 that.trigger('editable-hidden', column.field, row, $(this), reason);
 });
 });
 this.trigger('editable-init');
 };

}(jQuery);

这个js其实是对x-editable做了一个简单的封装,增加了列的editable属性以及编辑保存后的一些事件。有了这个作为基础,于是我们行内编辑的代码变成了这样。

需要引用的文件如下: 

<link href="/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/bootstrap3-editable/css/bootstrap-editable.css" rel="stylesheet" />
<link href="/Content/bootstrap-table/bootstrap-table.min.css" rel="stylesheet" />

<script src="/Scripts/jquery-1.9.1.min.js"></script>
<script src="/Content/bootstrap/js/bootstrap.min.js"></script>
<script src="~/Content/bootstrap3-editable/js/bootstrap-editable.js"></script>
<script src="~/Content/bootstrap-table/bootstrap-table.js"></script>
<script src="/Content/bootstrap-table/locale/bootstrap-table-zh-CN.js"></script>
<script src="~/Content/bootstrap-table/extensions/editable/bootstrap-table-editable.js"></script>

1、文本框

$(function () {
 $("#tb_user").bootstrapTable({
 toolbar: "#toolbar",
 idField: "Id",
 pagination: true,
 showRefresh: true,
 search: true,
 clickToSelect: true,
 queryParams: function (param) {
 return {};
 },
 url: "/Editable/GetUsers",
 columns: [{
 checkbox: true
 }, {
 field: "UserName",
 title: "用户名",
 editable: {
 type: 'text',
 title: '用户名',
 validate: function (v) {
 if (!v) return '用户名不能为空';

 }
 }
 }, {
 field: "Age",
 title: "年龄",
 }, {
 field: "Birthday",
 title: "生日",
 formatter: function (value, row, index) {
 var date = eval('new ' + eval(value).source)
 return date.format("yyyy-MM-dd");
 }
 },
 {
 field: "DeptName",
 title: "部门"
 }, {
 field: "Hobby",
 title: "爱好" 
 }],
 onEditableSave: function (field, row, oldValue, $el) {
 $.ajax({
 type: "post",
 url: "/Editable/Edit",
 data: row,
 dataType: 'JSON',
 success: function (data, status) {
 if (status == "success") {
 alert('提交数据成功');
 }
 },
 error: function () {
 alert('编辑失败');
 },
 complete: function () {

 }

 });
 }
 });
 });

后台对应的更新方法

public JsonResult Edit(User user)
 {
 //更新实体

 return Json(new { }, JsonRequestBehavior.AllowGet);
 }

经过测试,用户名这一列基本可以自由编辑。同样,年龄这一列也可改成这样

{
 field: "Age",
 title: "年龄",
 editable: {
 type: 'text',
 title: '年龄',
 validate: function (v) {
 if (isNaN(v)) return '年龄必须是数字';
 var age = parseInt(v);
 if (age <= 0) return '年龄必须是正整数';
 }
 }
 }

其他基本不用做任何修改。
代码释疑:上文在初始化的columns属性里面通过editable属性来配置可编辑的参数,注意这里每个列的editable属性对应的Json对象即为x-editable里面的初始化的Json对象,也就是说我们初始化x-editable的时候可以配置哪些属性,在列的editable属性里面也可以同样配置,这样用起来就爽多了吧。编辑后的提交方法统一放到onEditableSave事件里面统一处理。

2、时间选择框

有了上面的知识作为基础,我们来初始化生日这一列: 

{
 field: "Birthday",
 title: "生日",
 formatter: function (value, row, index) {
 var date = eval('new ' + eval(value).source)
 return date.format("yyyy-MM-dd");
 },
 editable: {
 type: 'date',
 title: '生日'
 }
 }

其他地方不用做任何修改,得到效果: 

JS表格组件BootstrapTable行内编辑解决方案x-editable

这是x-editable的默认样式,如果你看着不爽,可以自行配置,x-editable提供了许多配置日期框的参数,如下: 

JS表格组件BootstrapTable行内编辑解决方案x-editable

当然,如果精确到时分秒,可以使用datetime类型的编辑框。如下是官方给出的时间框编辑效果,看着还不错。

JS表格组件BootstrapTable行内编辑解决方案x-editable

JS表格组件BootstrapTable行内编辑解决方案x-editable

3、下拉框

表单编辑里面还有一个重要的标签就是select了。上文我们知道x-editable为我们提供了下拉框的编辑模式,比如我们的部门这一列的编辑可以写成这样:

{
 field: "DeptId",
 title: "部门",
 editable: {
 type: 'select',
 title: '部门',
 source:[{value:"1",text:"研发部"},{value:"2",text:"销售部"},{value:"3",text:"行政部"}]
 }
 }

得到效果

 JS表格组件BootstrapTable行内编辑解决方案x-editable

当然,这种本地设置数据源的方法肯定是不能满足我们需求的,因为很多情况下拉框里面的选项是从数据库远程得到的。当然x-editable也为我们考虑到了,比如我们可以这样写: 

{
 field: "DeptId",
 title: "部门",
 editable: {
 type: 'select',
 title: '部门',
 source: function () {
 var result = [];
 $.ajax({
 url: '/Editable/GetDepartments',
 async: false,
 type: "get",
 data: {},
 success: function (data, status) {
 $.each(data, function (key, value) {
  result.push({ value: value.ID, text: value.Name });
 });
 }
 });
 return result;
 }
 }
 }

后台我们配置一个方法 

public JsonResult GetDepartments()
 {
 var lstRes = new List<Department>();
 lstRes.Add(new Department() { ID = "1", Name = "研发部" });
 lstRes.Add(new Department() { ID = "2", Name = "销售部" });
 lstRes.Add(new Department() { ID = "3", Name = "行政部" });
 lstRes.Add(new Department() { ID = "4", Name = "创意部" });
 lstRes.Add(new Department() { ID = "5", Name = "事业部" });
 return Json(lstRes, JsonRequestBehavior.AllowGet);
 }

同样能达到我们想要的结果。

代码释疑:这里有一点需要说明一下,细心的园友可能发现了,我们这里的 field: "DeptId" ,为什么这里要配置DeptId而不是DeptName呢?很简单,因为我们需要和数据源里面的value值对应。

4、复选框

除了上述几种常见的编辑框,x-editable还为我们提供了复选框组的编辑。比如:

{
 field: "Hobby",
 title: "爱好",
 editable: {
 type: "checklist",
 separator:",",
 source: [{ value: 'bsb', text: '篮球' },
 { value: 'ftb', text: '足球' },
 { value: 'wsm', text: '游泳' }],
 }
 }

得到效果:

 JS表格组件BootstrapTable行内编辑解决方案x-editable

当然,如果远程数据,也可以使用类似上文的方法去取。

5、“阴魂不散”的select2 

说到上文的复选框,博主不由自主又想到了Multiselect这些个东西,于是查找x-editable的文档,结果发现它不支持Multiselect,但是支持select2,也不知道这是不是一个好消息。根据博主自己的使用经历,也包括技术交流群里面的聊天经历,发现很多人在使用select2的时候都遇到过各种各样的样式问题,并且不太好解决。

既然x-editable支持select2,那我们就用用试试呗,反正官方demo说得挺好的,下面是官方demo的使用示例:

JS表格组件BootstrapTable行内编辑解决方案x-editable

怀着忐忑的心情,博主自己尝试了一把。

引用select2文件

<link href="~/Content/select2-bootstrap.css" rel="stylesheet" />
<link href="~/Content/select2-master/dist/css/select2.min.css" rel="stylesheet" />
<script src="~/Content/select2-master/dist/js/select2.full.min.js"></script>

代码尝试 

{
 field: "Hobby",
 title: "爱好",
 editable: {
 type: 'select2',
 title: '爱好',
 name: 'Hobby',
 placement: 'top',
 success: function (response, newValue) {
 debugger;
 },
 error: function(response, newValue) {
 debugger;
 },
 url: function(params) {
 debugger;
 },
 source: [{ id: 'bsb', text: '篮球' },
 { id: 'ftb', text: '足球' },
 { id: 'wsm', text: '游泳' }],
 inputclass: 'input-large',
 select2: {
 allowClear: true,
 multiple: true,
 } 
 }
 }

得到结果:

JS表格组件BootstrapTable行内编辑解决方案x-editable

结果发现select2的选中值不能正常传递到后台。反正博主试过各种参数,按照官方demo的写法也试过,均以失败告终。也不知道官方的demo如何成功的。这个问题先抛出来,如果有使用的园友欢迎指正与解答。后续如果博主解决了这个问题,也会在此更新。

四、总结 

还有一个问题就是在编辑完成提交之后,博主在项目中遇到这样一个问题:如果提交之后的文本内容过多,表格的thead里面th的宽度和tbody里面td的宽度不对其的问题,看着相当恶心。但是在写demo的时候又没有遇到这个问题。在此还是将解决方案给出来。

 JS表格组件BootstrapTable行内编辑解决方案x-editable

就这么一句话解决你的困扰!

本篇介绍了下bootstrapTable结合x-editable实现行内编辑的使用。文中很多问题都是根据博主的使用经历来说明,如果你打算将它用起来,也可以试试。

如果大家还想深入学习,可以点击这里进行学习,再为大家附3个精彩的专题:

以上就是本文的全部内容,希望能够帮助大家更好的学习JS表格组件神器bootstrap table。

Javascript 相关文章推荐
利用javascript/jquery对上传文件格式过滤的方法
Jul 25 Javascript
JavaScript 学习笔记(四)
Dec 31 Javascript
javascript实现颜色渐变的方法
Oct 30 Javascript
深入解析JavaScript中的变量作用域
Dec 06 Javascript
Jquery validation remote 验证的缓存问题解决方法
Mar 25 Javascript
jquery delay()介绍及使用指南
Sep 02 Javascript
javascript实现对表格元素进行排序操作
Nov 18 Javascript
React Native模块之Permissions权限申请的实例相机
Sep 28 Javascript
vuejs router history 配置到iis的方法
Sep 20 Javascript
详解jQuery获取特殊属性的值以及设置内容
Nov 14 jQuery
js实现全选反选不选功能代码详解
Apr 24 Javascript
JS 图片压缩原理与实现方法详解
Apr 29 Javascript
JS实现列表的响应式排版(推荐)
Sep 01 #Javascript
利用Jquery队列实现根据输入数量显示的动画
Sep 01 #Javascript
JavaScript中子对象访问父对象的方式详解
Sep 01 #Javascript
浅谈JavaScript 数据属性和访问器属性
Sep 01 #Javascript
老生常谈JavaScript 函数表达式
Sep 01 #Javascript
Ubuntu系统下Angularjs开发环境安装
Sep 01 #Javascript
利用Angularjs和原生JS分别实现动态效果的输入框
Sep 01 #Javascript
You might like
用文本文件实现的动态实时发布新闻的程序
2006/10/09 PHP
oracle资料库函式库
2006/10/09 PHP
详解WordPress中提醒安装插件以及隐藏插件的功能实现
2015/12/25 PHP
thinkPHP简单实现多个子查询语句的方法
2016/12/05 PHP
JavaScript下申明对象的几种方法小结
2008/10/02 Javascript
jQuery数组处理函数整理
2016/08/03 Javascript
MUI  Scroll插件的使用详解
2017/04/13 Javascript
WebSocket实现简单客服聊天系统
2017/05/12 Javascript
jquery Ajax实现Select动态添加数据
2017/06/08 jQuery
jQuery插件DataTables分页开发心得体会
2017/08/22 jQuery
BootStrap Validator 根据条件在JS中添加或移除校验操作
2017/10/12 Javascript
微信小程序实现YDUI的ScrollTab组件
2018/02/02 Javascript
Node.js进阶之核心模块https入门
2018/05/23 Javascript
详解Vue CLI3 多页应用实践和源码设计
2018/08/30 Javascript
微信小程序页面上下滚动效果
2020/11/18 Javascript
JavaScript实现滑块验证解锁
2021/01/07 Javascript
[00:37]2016完美“圣”典风云人物:rOtk宣传片
2016/12/09 DOTA
Python程序中设置HTTP代理
2016/11/06 Python
Python导入模块时遇到的错误分析
2017/08/30 Python
Python3 加密(hashlib和hmac)模块的实现
2017/11/23 Python
python解析json串与正则匹配对比方法
2018/12/20 Python
Python判断一个list中是否包含另一个list全部元素的方法分析
2018/12/24 Python
基于python实现的百度音乐下载器python pyqt改进版(附代码)
2019/08/05 Python
pytorch多进程加速及代码优化方法
2019/08/19 Python
Python Django模板之模板过滤器与自定义模板过滤器示例
2019/10/18 Python
Python collections中的双向队列deque简单介绍详解
2019/11/04 Python
pytorch之添加BN的实现
2020/01/06 Python
python爬虫中采集中遇到的问题整理
2020/11/27 Python
Python约瑟夫生者死者小游戏实例讲解
2021/01/04 Python
突袭HTML5之Javascript API扩展3—本地存储全新体验
2013/01/31 HTML / CSS
农田水利实习自我鉴定
2013/09/19 职场文书
信息与计算科学专业推荐信
2014/02/23 职场文书
小区推广策划方案
2014/06/06 职场文书
大学生学期个人总结
2015/02/12 职场文书
java中用float时,数字后面加f,这样是为什么你知道吗
2021/09/04 Java/Android
台式电脑蓝牙适配器怎么安装?台式电脑蓝牙适配器安装教程
2022/04/08 数码科技