From 90000f39f6e113d586b1b455c6c1e7b02aaee1fb Mon Sep 17 00:00:00 2001
From: morning-star <26325820+Sight-wcg@users.noreply.github.com>
Date: Thu, 18 Jan 2024 13:10:49 +0800
Subject: [PATCH 1/2] =?UTF-8?q?feat(table):=20=E6=96=B0=E5=A2=9E=20`table.?=
=?UTF-8?q?updateRow`=E6=96=B9=E6=B3=95=20(#1540)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 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:
bc61f9ff08d4e512585b399c0dd41954c3878bd0
1a5258b292c6b67873df35f456883afd3da04cbb
4af5b1cda4d2ce6049f7dfafb25f99a498196bc4
62e551d22bfc8a379c15ce44f290f7ff73dbcb3a
这些方法互相关联,而 totalRow 存在暂时无法解决的问题,故全部回退。后续在其他 PR 中实现。
* refactor(table): updateRow options.row 重命名为 options.data
---
docs/table/index.md | 36 ++++++++++++++
src/modules/table.js | 116 +++++++++++++++++++++++++++++--------------
2 files changed, 116 insertions(+), 36 deletions(-)
diff --git a/docs/table/index.md b/docs/table/index.md
index 1a3ac49d..25179bc8 100644
--- a/docs/table/index.md
+++ b/docs/table/index.md
@@ -28,6 +28,7 @@ toc: true
| [table.reload(id, options, deep)](#table.reload) | 表格完整重载。 |
| [table.reloadData(id, options, deep)](#table.reloadData) 2.7+ | 表格数据重载。 |
| [table.renderData(id)](#table.renderData) 2.8.5+ | 重新渲染数据。 |
+| [table.updateRow(id, opts)](#table.updateRow) 2.9.4+ | 更新指定行数据。 |
| [table.checkStatus(id)](#table.checkStatus) | 获取选中行相关数据。 |
| [table.setRowChecked(id, opts)](#table.setRowChecked) 2.8+ | 设置行选中状态。 |
| [table.getData(id)](#table.getData) | 获取当前页所有行表格数据。 |
@@ -313,6 +314,41 @@ data.splice(newIndex, 0, item[0]);
table.renderData('test');
```
+
更新指定行数据 2.9.4+
+
+`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;
+ }
+});
+```
获取选中行
diff --git a/src/modules/table.js b/src/modules/table.js
index 94011e7c..d3c8f515 100644
--- a/src/modules/table.js
+++ b/src/modules/table.js
@@ -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.} 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){
From 23bf960a2a740bf5916010a6e29138d93b7cea87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=B4=A4=E5=BF=83?=
<3277200+sentsim@users.noreply.github.com>
Date: Thu, 18 Jan 2024 13:38:21 +0800
Subject: [PATCH 2/2] =?UTF-8?q?fix(table):=20=E4=BF=AE=E5=A4=8D=20Chrome?=
=?UTF-8?q?=20DevTools=20=E5=AE=A1=E6=9F=A5=20iframe=20=E4=B8=AD=20table?=
=?UTF-8?q?=20=E5=85=83=E7=B4=A0=E6=97=B6=E5=AF=BC=E8=87=B4=E9=A1=B5?=
=?UTF-8?q?=E9=9D=A2=E5=B4=A9=E6=BA=83=E7=9A=84=E9=97=AE=E9=A2=98=20(#1571?=
=?UTF-8?q?)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/modules/table.js | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/src/modules/table.js b/src/modules/table.js
index d3c8f515..871615b2 100644
--- a/src/modules/table.js
+++ b/src/modules/table.js
@@ -1757,7 +1757,24 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
lay.getStyleRules(style, function(item){
if (item.selectorText === ('.laytable-cell-'+ key)) {
- return callback(item), true;
+ callback(item);
+
+ /* 以下代码为防止 Chrome DevTools 审查 iframe 中的 table 元素时出现的页面崩溃
+ * closes https://gitee.com/layui/layui/issues/I8N08M
+ * 具体原因不明,可能是初始操作 cssRules 触发了 DevTools inspect 的解析报错
+ * 后续若浏览器本身修复了该问题,下述补丁也将会剔除
+ */
+ (function PatcheToCssRulesInDevTools(){
+ if (self === parent) return;
+ var input = lay.elem('input', {
+ style: 'position: absolute; left: 0; top: 0; opacity: 0.01;'
+ });
+ document.body.appendChild(input);
+ input.focus();
+ document.body.removeChild(input);
+ })();
+
+ return true;
}
});
};