feat(table): 新增 `table.updateRow`方法 (#1540)

* feat(table): 新增 `table.updateRow` 方法

* refactor

* update code

* update doc

* feat(table): 新增 `table.updateTotalRow`

* perf(table): 改进 updateRow 渲染性能

* feat(table): col.totalRow 支持函数,改进 updateTotalRow 参数

* feat(table): 新增 table.getTotalRow

* feat(table): table.getTotalRow 支持获取原始结果

* perf(table): 改进 table.updateRow 性能

* fix: 修复 updateRow  一些问题

* revert: 回退除 table.updateRow 以外的所有改动

REVERT:
bc61f9ff08
1a5258b292
4af5b1cda4
62e551d22b
这些方法互相关联,而 totalRow 存在暂时无法解决的问题,故全部回退。后续在其他 PR 中实现。

* refactor(table): updateRow options.row 重命名为 options.data
pull/1584/head
morning-star 2024-01-18 13:10:49 +08:00 committed by GitHub
parent 3bced33798
commit 90000f39f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 116 additions and 36 deletions

View File

@ -28,6 +28,7 @@ toc: true
| [table.reload(id, options, deep)](#table.reload) | 表格完整重载。 |
| [table.reloadData(id, options, deep)](#table.reloadData) <sup>2.7+</sup> | 表格数据重载。 |
| [table.renderData(id)](#table.renderData) <sup>2.8.5+</sup> | 重新渲染数据。 |
| [table.updateRow(id, opts)](#table.updateRow) <sup>2.9.4+</sup> | 更新指定行数据。 |
| [table.checkStatus(id)](#table.checkStatus) | 获取选中行相关数据。 |
| [table.setRowChecked(id, opts)](#table.setRowChecked) <sup>2.8+</sup> | 设置行选中状态。 |
| [table.getData(id)](#table.getData) | 获取当前页所有行表格数据。 |
@ -313,6 +314,41 @@ data.splice(newIndex, 0, item[0]);
table.renderData('test');
```
<h3 id="table.updateRow" lay-pid="api" class="ws-anchor ws-bold">更新指定行数据 <sup>2.9.4+</sup></h3>
`table.updateRow(id, opts);`
- 参数 `id` : table 渲染时的 `id` 属性值
- 参数 `opts` : 更新指定行时的可选属性,详见下表
| opts | 描述 | 类型 | 默认值 |
| --- | --- | --- | --- |
| index | 行索引 | number | - |
| data | 行数据 | object | - |
| related | 是否更新其他包含自定义模板且可能有所关联的列视图 | boolean/function | - |
该方法用于更新指定行数据。
```js
// 渲染
table.render({
elem: '', // 绑定元素选择器
id: 'test', // 自定义 id 索引
// 其他属性 …
});
// 更新指定行数据
table.updateRow('test', {
index: 0,
data: {
id: 1,
username: 'name'
}
// 是否更新关联的列视图
related: function(field, index){
return ['score', '5'].indexOf(field) !== -1;
}
});
```
<h3 id="table.checkStatus" lay-pid="api" class="ws-anchor ws-bold">获取选中行</h3>

View File

@ -1527,6 +1527,13 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
form.render(type, filter);
};
// 定向渲染表单
Class.prototype.renderFormByElem = function(elem){
layui.each(['input', 'select'], function(i, formType){
form.render(elem.find(formType));
})
};
// 同步全选按钮状态
Class.prototype.syncCheckAll = function(){
var that = this;
@ -1886,6 +1893,73 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.layFixRight.css('right', scrollWidth - 1);
};
/**
* @typedef updateRowOptions
* @prop {number} index - 行索引
* @prop {Object.<string, any>} data - 行数据
* @prop {boolean | ((field, index) => boolean)} [related] - 更新其他包含自定义模板且可能有所关联的列视图
*/
/**
* 更新指定行
* @param {updateRowOptions | updateRowOptions[]} opts
* @param {(field: string, value: any) => void} [callback] - 更新每个字段时的回调函数
*/
Class.prototype.updateRow = function(opts, callback){
var that = this;
var ELEM_CELL = '.layui-table-cell';
var opts = layui.type(opts) === 'array' ? opts : [opts];
var dataCache = table.cache[that.key] || [];
var update = function(opt){
var index = opt.index;
var row = opt.data;
var related = opt.related;
var data = dataCache[index] || {};
var tr = that.layBody.find('tr[data-index="' + index + '"]');
// 更新缓存中的数据
layui.each(row, function (key, value) {
data[key] = value;
callback && callback(key, value);
});
// 更新单元格
that.eachCols(function (i, item3) {
var field = String(item3.field || i);
var shouldUpdate = field in row || ((typeof related === 'function' ? related(field, i) : related) && (item3.templet || item3.toolbar));
if(shouldUpdate){
var td = tr.children('td[data-field="' + field + '"]');
var cell = td.children(ELEM_CELL);
var content = data[item3.field];
cell.html(parseTempData.call(that, {
item3: item3,
content: content,
tplData: $.extend({
LAY_COL: item3,
}, data)
}));
td.data("content", content);
that.renderFormByElem(cell);
}
});
}
layui.each(opts, function(i, opt){
update(opt);
});
};
/**
* 更新指定行
* @param {string} id - table ID
* @param {updateRowOptions | updateRowOptions[]} options
*/
table.updateRow = function (id, options){
var that = getThisTable(id);
return that.updateRow(options);
}
// 事件处理
Class.prototype.events = function(){
var that = this;
@ -2229,43 +2303,13 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
},
update: function(fields, related){ // 修改行数据
fields = fields || {};
layui.each(fields, function(key, value){
var td = tr.children('td[data-field="'+ key +'"]');
var cell = td.children(ELEM_CELL); // 获取当前修改的列
// 更新缓存中的数据
data[key] = obj.data[key] = value;
// 更新相应列视图
that.eachCols(function(i, item3){
if(item3.field == key){
cell.html(parseTempData.call(that, {
item3: item3
,content: value
,tplData: $.extend({
LAY_COL: item3
}, data)
}));
td.data('content', value);
}
// 更新其他包含自定义模板且可能有所关联的列视图
else if(related && (item3.templet || item3.toolbar)){
var thisTd = tr.children('td[data-field="'+ (item3.field || i) +'"]');
var content = data[item3.field];
thisTd.children(ELEM_CELL).html(parseTempData.call(that, {
item3: item3
,content: content
,tplData: $.extend({
LAY_COL: item3
}, data)
}));
thisTd.data('content', content);
}
});
that.updateRow({
index: index,
data: fields,
related: related
}, function(key, value){
obj.data[key] = value;
});
that.renderForm();
},
// 设置行选中状态
setRowChecked: function(opts){