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 相关文章推荐
IE Firefox 使用自定义标签的区别
Oct 15 Javascript
jQuery 在光标定位的地方插入文字的插件
May 10 Javascript
jQuery中hover与mouseover和mouseout的区别分析
Dec 24 Javascript
引用jquery框架后出错的解决方法
Aug 09 Javascript
JS验证 只能输入小数点,数字,负数的实现方法
Oct 07 Javascript
AngularJS实现网站换肤实例
Feb 19 Javascript
JavaScript定义全局对象的方法示例
Jan 12 Javascript
微信小程序 本地数据读取实例
Apr 27 Javascript
详解angular脏检查原理及伪代码实现
Jun 08 Javascript
vue.js计算属性computed用法实例分析
Jul 06 Javascript
微信小程序中换行空格(多个空格)写法详解
Jul 10 Javascript
uniapp微信小程序实现一个页面多个倒计时
Nov 01 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 file_get_contents函数轻松采集html数据
2010/04/22 PHP
无刷新动态加载数据 滚动条加载适合评论等页面
2013/10/16 PHP
php中操作memcached缓存进行增删改查数据的实现代码
2014/08/15 PHP
php实现遍历目录并删除指定文件中指定内容
2015/01/21 PHP
对于Laravel 5.5核心架构的深入理解
2018/02/22 PHP
php简单计算权重的方法示例【适合抽奖类应用】
2019/06/10 PHP
提高javascript效率 一次判断,而不要次次判断
2012/03/30 Javascript
页面加载完后自动执行一个方法的js代码
2014/09/06 Javascript
javascript实现根据身份证号读取相关信息
2014/12/17 Javascript
Javascript 是你的高阶函数(高级应用)
2015/06/15 Javascript
javascript实现树形菜单的方法
2015/07/17 Javascript
非常漂亮的相册集 使用jquery制作相册集
2016/04/28 Javascript
JQuery核心函数是什么及使用方法介绍
2016/05/03 Javascript
利用js来实现缩略语列表、文献来源链接和快捷键列表
2016/12/16 Javascript
js字符串与Unicode编码互相转换
2017/05/17 Javascript
JS使用正则表达式获取小括号、中括号及花括号内容的方法示例
2018/06/01 Javascript
layui 表格的属性的显示转换方法
2018/08/14 Javascript
echarts多条折线图动态分层的实现方法
2019/05/24 Javascript
[01:57]2018年度DOTA2最具潜力解说-完美盛典
2018/12/16 DOTA
[02:44]重置世界,颠覆未来——DOTA2 7.23版本震撼上线
2019/12/01 DOTA
python实现dict版图遍历示例
2014/02/19 Python
python中文分词教程之前向最大正向匹配算法详解
2017/11/02 Python
Python AES加密实例解析
2018/01/18 Python
Python3.6.2调用ffmpeg的方法
2019/01/10 Python
Python re正则表达式元字符分组()用法分享
2020/02/10 Python
Python pytesseract验证码识别库用法解析
2020/06/29 Python
OpenCV灰度化之后图片为绿色的解决
2020/12/01 Python
python中_del_还原数据的方法
2020/12/09 Python
KTV的创业计划书范文
2014/02/02 职场文书
纪检干部个人对照检查材料
2014/09/23 职场文书
财政局党的群众路线教育实践活动剖析材料
2014/10/13 职场文书
2014年技术工作总结范文
2014/11/20 职场文书
2014年公务员个人工作总结
2014/11/22 职场文书
Mac M1安装mnmp (Mac+Nginx+MySQL+PHP) 开发环境
2021/03/29 PHP
Win11开始菜单添加休眠选项
2022/04/19 数码科技
Python+SeaTable实现计算两个日期间的工作日天数
2022/07/07 Python