选择主从数据
运行效果
在父页面中,打开对话框,选择主从数据。
- 主从数据显示在一行上,从数据有几行显示几行,主数据合并单元格显示为一行
- 选择列和序号列都是跟随主数据的,选择是单选
- 确定按钮关闭对话框,同时返回选择的主数据及其从数据
案例需求
- 在表格中,主从数据显示在一行上,从数据有几行显示几行,主数据合并单元格显示为一行
- 显示主数据的序号
- 选择一条主数据
- 将选择的主数据及其从数据返回父页面
知识点
- 输出数据集:返回 JSON 嵌套数据
- 整理数据:遍历数据、新增数据、编辑数据
- 表格的单元格合并
- 表格的列渲染事件
- 使用原生 Checkbox 组件
开发过程
数据开发
添加主表
添加订单主表,数据结构如下图所示
添加从表
添加订单从表,数据结构如下图所示
主表设置输出数据集
主从数据不使用关联查询,使用输出数据集,返回 JSON 嵌套数据
在订单主表中添加输出数据集,将订单从表作为主表的输出数据集
页面开发
子页面
整理数据用于显示
添加自定义数据。列包括当前数据的主键、主表数据列、从表数据列、从表记录数、序号和选择,如下图所示
- 从表记录数:用于合并单元格
- 序号:用于计算主表的序号
- 选择:用于存储选择信息
添加订单主表,必须选择数据列,除了订单主表自身的列,还必须包括输出数据集,不要选择输出数据集中的列,如下图所示
在主表的数据列中选择从表的输出数据集后,查询主表返回 JSON 嵌套数据,格式如下图所示,其中 orderd 是输出数据集的名称
订单主表添加刷新后事件,如下图所示
在刷新后事件中,将订单主表查询的数据,写入自定义数据,同时计算从表记录数、设置递增序号,js 代码如下
//将主从数据整理后写入自定义数据,用于在表格中显示
onMainDataAfterRefresh = (event) => {
let mainData = this.comp("mainData");
let mdData = this.comp("mdData");
mdData.requireBatchTransition();//开启批量处理
mdData.clear();
let i = 1;
mainData.each(({ row: mRow }) => {
//写入主表数据
mdData.newData({
defaultValues: [{
id: wx.UUID.createUUID(), //写入数据的主键
mid: mRow.fid,
orderNo: mRow.orderNo,
orderDate: mRow.orderDate,
money: mRow.money,
detailCount: mRow.orderd.length == 0 ? 1 : mRow.orderd.length,//计算从表记录数,用于合并主表数据
no: i++ //设置递增序号
}]
})
//写入从表数据
mRow.orderd.forEach((dRow, index) => {
if (index == 0) {
mdData.setValue("did", dRow.fid);
mdData.setValue("productId", dRow.productId);
mdData.setValue("num", dRow.num);
mdData.setValue("price", dRow.price);
} else {
mdData.newData({
defaultValues: [{
id: wx.UUID.createUUID(),
did: dRow.fid,
productId: dRow.productId,
num: dRow.num,
price: dRow.price,
detailCount: 0 //从表记录数设置为0,表示单元格以被合并,无需显示
}]
})
}
})
})
}
添加表格显示数据
添加表格,绑定自定义数据。添加选择列、序号列、主表的列和从表的列。不使用表格自带的选择功能,而是通过代码实现选择主数据
表格合并单元格
React 实现
在 js 中添加列渲染方法,代码如下,表示使用从表记录数实现行合并
//合并单元格
tableColumnRender(text, record, index) {
return {
children: text,
props: {
rowSpan: record.detailCount
}
};
}
切换到源码,在主表的列上,添加 render 属性,调用合并单元格的方法,render 属性代码如下
render="{$page.tableColumnRender(text, record, index)}"
添加后的源码如下图所示
Vue 实现
在 js 中添加列渲染方法,代码如下,表示使用从表记录数实现行合并
//合并行
let columnRender = ({text, record, index, column}) => {
return {
children: text,
props: {
rowSpan: record.detailCount
}
};
}
切换到源码,在主表的列上,添加 customRender 属性,调用合并单元格的方法,customRender 属性代码如下
customRender="{columnRender}"
添加后的源码如下图所示
选择主数据
React 实现
在源码中添加选择列的 render 属性,如下图所示
在 js 中添加选择列 render 属性调用的列渲染事件。在选择列中显示 Checkbox,表格当前行 select 列的值为1时,显示为选中,否则显示为未选中。选中 Checkbox 调用 onChange 方法,代码如下
//显示checkbox
tableColumn63RenderRender = (text, record, index) => {
return {
children: <Checkbox checked={record.select == 1} onChange={(e) => { return this.onChange(e, text, record, index); }} ></Checkbox>,
props: {
rowSpan: record.detailCount
}
};
}
React 使用 Checkbox 需要先引用
import React from 'react';
import { Checkbox } from 'antd';
在 js 中添加 Checkbox 改变事件,event.target.checked 表示 Checkbox 的选中状态,选中时,给 select 列赋值1,否则赋值0,代码如下
//选择主数据
onChange = (event, text, record, index) => {
let mdData = this.comp("mdData");
//单选
let rows = mdData.find(["select"],[1]);
if(rows.length > 0){
rows[0].select = 0;
}
mdData.to(record.id);
mdData.setValue("select", event.target.checked ? 1 : 0);
}
Vue 实现
在源码中添加选择列的 customRender 属性,如下图所示
在 js 中添加选择列 customRender 属性调用的列渲染事件。在选择列中显示 Checkbox,表格当前行 select 列的值为1时,显示为选中,否则显示为未选中。选中 Checkbox 调用 onChange 方法,代码如下
//显示checkbox
let tableColumn63RenderRender = ({text, record, index, column}) => {
return {
children: <Checkbox checked={record.select == 1} onChange={(e) => { return onChange(e, text, record, index); }} ></Checkbox>,
props: {
rowSpan: record.detailCount
}
};
}
Vue 使用 Checkbox 需要先引用
import { Checkbox } from 'ant-design-vue';
在 js 中添加 Checkbox 改变事件,event.target.checked 表示 Checkbox 的选中状态,选中时,给 select 列赋值1,否则赋值0,代码如下
//选择主数据
let onChange = (event, text, record, index) => {
//单选
let rows = mdData.find(["select"],[1]);
if(rows.length > 0){
rows[0].select = 0;
}
mdData.to(record.id);
mdData.setValue("select", event.target.checked ? 1 : 0);
}
返回主从数据
从自定义数据中,获取选中的主表主键,返回订单主表对应的这一行数据,这一行数据是 JSON 嵌套数据,既包括主数据也包括从数据
React 代码如下
//返回主数据,其中包括从数据
onOkBtnClick = (event) => {
let mainData = this.comp("mainData");
let mdData = this.comp("mdData");
let rows = mdData.find(["select"],[1]);
if(rows.length > 0){
let selectRowId = rows[0].mid;
mainData.to(selectRowId);
let data = mainData.current.toJson();
this.navigateBack({message:{data, isOk: true}}); //isOk: true 表示确定返回,会触发对话框组件的确定返回事件
}
}
Vue 代码如下
//返回主数据,其中包括从数据
let onOkBtnClick = (event) => {
let rows = mdData.find(["select"],[1]);
if(rows.length > 0){
let selectRowId = rows[0].mid;
mainData.to(selectRowId);
let data = mainData.current.toJson();
console.log(data);
$page.navigateBack({message:{data, isOk: true}});
}
}
父页面
打开对话框
添加对话框组件,页面文件选择子页面
在按钮的点击事件中,调用对话框的打开操作,打开对话框
接收数据
添加对话框组件的确定返回事件,如下图所示
在确定返回事件中,通过 message.data 获取子页面返回的 JSON 嵌套数据,包括一条主数据及其从数据。本例使用 loadData 方法,仅用于显示数据,如需添加数据,请使用 newData 方法。另:从表数据组件中的外键列名称为主表名称+ID,主表输出数据集中的外键列名称为主表名称,如使用外键列,请注意这两种方式中的名称不同。
React 代码如下
onDialog0Ok = (event) => {
let {detail:{message, params, pagePath}} = event;
let mdData = message.data;
let masterData = this.comp("masterData");
let detailData = this.comp("detailData");
masterData.loadData([mdData]);
detailData.loadData(mdData.orderd);
}
Vue 代码如下
let onDialog0Ok = (event) => {
let {detail:{message, params, pagePath}} = event;
let mdData = message.data;
masterData.loadData([mdData]);
detailData.loadData(mdData.orderd);
}