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 相关文章推荐
prototype class详解
Sep 07 Javascript
兼容IE和FF的js脚本代码小结(比较常用)
Dec 06 Javascript
ExtJS的拖拽效果示例
Dec 09 Javascript
JavaSript中变量的作用域闭包的深入理解
May 12 Javascript
谈谈JavaScript异步函数发展历程
Sep 29 Javascript
很棒的Bootstrap选项卡切换效果
Jul 01 Javascript
AngularJS ng-bind-template 指令详解
Jul 30 Javascript
javascript实现简易计算器
Feb 01 Javascript
Angular 4依赖注入学习教程之组件服务注入(二)
Jun 04 Javascript
vue轮播图插件vue-awesome-swiper的使用代码实例
Jul 10 Javascript
js插件实现图片滑动验证码
Sep 29 Javascript
javaScript之split与join的区别(详解)
Nov 08 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
php实现表单提交上传文件功能
2018/05/28 PHP
ThinkPHP 3.2.3实现加减乘除图片验证码
2018/12/05 PHP
laravel5.6框架操作数据curd写法(查询构建器)实例分析
2020/01/26 PHP
深入理解Javascript闭包 新手版
2010/12/28 Javascript
常用一些Javascript判断函数
2012/08/14 Javascript
使用Function.apply()的参数数组化来提高 JavaScript程序性能的技巧
2015/12/23 Javascript
jquery+html仿翻页相册功能
2016/12/20 Javascript
微信小程序中实现一对多发消息详解及实例代码
2017/02/14 Javascript
巧妙运用v-model实现父子组件传值的方法示例
2019/04/07 Javascript
element-ui表格合并span-method的实现方法
2019/05/21 Javascript
EasyUI 数据表格datagrid列自适应内容宽度的实现
2019/07/18 Javascript
Vue中遍历数组的新方法实例详解
2019/07/21 Javascript
js 递归json树实现根据子id查父id的方法分析
2019/11/08 Javascript
js数组的基本使用总结
2021/01/18 Javascript
Python开发WebService系列教程之REST,web.py,eurasia,Django
2014/06/30 Python
Python使用Supervisor来管理进程的方法
2015/05/28 Python
TensorFlow saver指定变量的存取
2018/03/10 Python
对Python2与Python3中__bool__方法的差异详解
2018/11/01 Python
Python 分布式缓存之Reids数据类型操作详解
2020/06/24 Python
Python+Selenium随机生成手机验证码并检查页面上是否弹出重复手机号码提示框
2020/09/21 Python
python3排序的实例方法
2020/10/20 Python
python向xls写入数据(包括合并,边框,对齐,列宽)
2021/02/02 Python
CSS3 filter(滤镜)实现网页灰色或者黑色模式的代码
2020/11/30 HTML / CSS
美国标志性加大尺码时装品牌:Ashley Stewart
2016/12/15 全球购物
深圳-东方伟业笔试部分
2015/02/11 面试题
办公室文秘自我鉴定
2013/09/21 职场文书
挂职思想汇报
2013/12/31 职场文书
车队司机自我鉴定
2014/03/02 职场文书
奥林匹克的口号
2014/06/13 职场文书
火锅店的活动方案
2014/08/15 职场文书
2014年保管员工作总结
2014/11/18 职场文书
2014收银员工作总结范文
2014/12/16 职场文书
党员承诺书格式范文
2015/04/28 职场文书
党员“一帮一”活动总结
2015/05/07 职场文书
python turtle绘制多边形和跳跃和改变速度特效
2022/03/16 Python
海贼王十大逆天果实 魂魂果实上榜,岩浆果实攻击力最强
2022/03/18 日漫