Skip to main content

Configure a form data source by using the form mid-link component

This case comes from the three-party developer Su Yi 」

1. Usage scenarios

YIDA cascade components do not support associating other form options. In this example, let's learn how to achieve this effect through YIDA OpenAPI.

2. Implement functions

2.1 Use regular

(1)Bottom table configuration

If there are more levels, you can continue to configure them. This example uses level 4 as an example.

By default, the subform data in the first instance of the bottom table is selected.

(2) use page configuration

(3) configure variables and bind them

(4) configure data sources

Reference documents:Obtain a list of instance details based on search criteria

The interface configuration is as follows:

(5) configure and obtain cascade option function encapsulation and call

// 当页面渲染完毕后马上调用下面的函数,这个函数是在当前页面 - 设置 - 生命周期 - 页面加载完成时中被关联的。
export function didMount() {
console.log(`「页面 JS」:当前页面地址 ${location.href}`);
// console.log(`「页面 JS」:当前页面 id 参数为 ${this.state.urlParams.id}`);
// 更多 this 相关 API 请参考:https://www.yuque.com/yida/support/ocmxyv#OCEXd
// document.title = window.loginUser.userName + ' | 宜搭';
this.fetchData();
}

// 获取级联选项
export function fetchData() {
const loading = this.utils.toast({
title: '级联选项获取中...',
type: 'loading'
});
this.dataSourceMap.getData.load({
formUuid,
}).then(res => {
loading();
const { totalCount, data } = res;
if (!totalCount) { return };
const { formData, instValue } = data[0];
const tableData = this.formatTableData(instValue, tableField);
const result = this.transformData(tableData);
this.setState({
dataSource: result
});
}).catch(error => {
loading();
this.utils.toast({
title: error.message,
type: 'error'
});
});
}

(6) configure cascade component option value processing function

// 级联选项数据处理
export function transformData(inputStr) {
const rows = inputStr.map(item => {
return dataSourceList.map(_item => {
return item[_item]
}).filter(item => {
return !!item
});
});
const res = {
children: {}
};
rows.forEach(row => {
row.reduce((pre, cur) => {
if (!pre.children[cur]) {
pre.children[cur] = {
label: cur,
value: pre.value ? `${pre.value}_${cur}` : cur,
children: {}
}
}
return pre.children[cur];
}, res);
});
const mapToArray = (map) => {
return Object.values(map).map(item => {
if (item.children) {
item.children = mapToArray(item.children);
}
if (Object.keys(item.children).length === 0) {
delete item.children;
}
return item;
});
};
return mapToArray(res.children);
}

(7) configure the subform data formatting function

// 格式化子表单数据
// instValue 接口返回,tableFieldId:需要获取的子表单唯一标识
export function formatTableData(instValue = '', tableFieldId = '') {
const tableData = [];
if (!instValue || !tableFieldId) {
return tableData;
};
const initInstValue = JSON.parse(instValue);
const tableInstValue = (((initInstValue.filter(item => {
return item.fieldId === tableFieldId;
})[0] || {}).fieldData || {}).value || []);
for (let i = 0; i < tableInstValue.length; i++) {
let tableObj = {};
for (let j = 0; j < tableInstValue[i].length; j++) {
tableObj[tableInstValue[i][j].fieldId] = tableInstValue[i][j].fieldData.value;
};
tableData.push(tableObj);
};
return tableData;
}

(8) configure fixed parameters

Note: The Cascade option corresponds to the unique identifier of each level, which must be in the order of level 1 to level n.

const formUuid = 'FORM-XXXXXXXXXXXXXXXXX'; // 级联选项数据底表
const tableField = 'tableField_lf7mskog'; // 级联选项数据底表子表单唯一标识
const dataSourceList = [
'textField_lf7mskoh', // 一级
'textField_lf7mskoi', // 二级
'textField_lf7mskoj', // 三级
'textField_lf7mskok' // 四级
]; // 级联选项对应各级的唯一标识,注意需要按照一级 ~ n级的顺序

2.2 Asynchronous loading

(1) Data Base Table configuration

Configure the data source:

Configure level fields onChange events:

const formUuid = 'FORM-RS966T81PG09H7S26RWSGDFW1VVC2QPDMKGFLP'; // 当前表 formUuid

// 循环调用,适用于请求全量数据(单次数据量大于100)的场景,调用后,请在then方法里面查看请求结果。
// dpName:String,数据源名称(必填),formUuid:String,查询目标表的formUuid(必填),searchFieldJson:Object,查询条件(非必填)。
export async function loopLoad(dpName, formUuid, searchFieldJson = {}) {
const result = []; // 最终数据集合
const errorPages = []; // 错误请求页码
await this.dataSourceMap[dpName].load({
formUuid,
searchFieldJson: JSON.stringify(searchFieldJson),
pageSize: 100
}).catch(error => {
this.utils.toast({
title: error.message,
type: 'error',
});
errorPages.push(1);
});
if (!this.state[dpName]) { return result };
if (this.state[dpName].totalCount <= 100) {
//当实例总数不大于100时
result.push(...this.state[dpName].data); //归整数据
} else {
//当实例总数大于100时
for (let i = 0; i < Math.ceil(this.state[dpName].totalCount / 100); i++) {
const delay = i === 0 ? 0 : 200;
await new Promise((resolve => {
// 注意节流,每次请求间隔 200 ms
setTimeout(async () => {
await this.dataSourceMap[dpName].load({
formUuid,
searchFieldJson: JSON.stringify(searchFieldJson),
pageSize: 100,
currentPage: i + 1
}).then(res => {
if (!res) { return };
result.push(...res.data);
}).catch(error => {
errorPages.push(i + 1);
});
resolve();
}, delay);
}));
};
};
return { result, errorPages };
}

/**
* selectField onChange
* @param value: {mixed} 选中的值
* @param actionType: {String} 触发的方式, 'itemClick', 'enter', 'change'
* @param item: {mixed} 选中的值的对象数据
*/
export function onChange({ value, actionType, item }) {
if (value === "1") {
return;
}; // 顶级名称过滤
this.loopLoad("getData", formUuid, {
selectField_lfduy8ny: value - 1
}).then(res => {
const { result = [] } = res;
let resultArr = result.map(({ formData }) => {
return {
text: formData.textField_lfduy8nw,
value: formData.textField_lfduy8nw
};
})
this.$('selectField_lfdv3l58').set('dataSource', resultArr); //赋值父级名称
});
}

(2) use page configuration

(3) configure variables and bind them

(4) configure data sources

Reference documents:Obtain a list of instance details based on search criteria

The interface configuration is as follows:

(5) configure and obtain cascade option function encapsulation and call

export function didMount() {
console.log(`「页面 JS」:当前页面地址 ${location.href}`);
// console.log(`「页面 JS」:当前页面 id 参数为 ${this.state.urlParams.id}`);
// 更多 this 相关 API 请参考:https://www.yuque.com/yida/support/ocmxyv#OCEXd
// document.title = window.loginUser.userName + ' | 宜搭';
this.fetchData();
}

const formUuid = 'FORM-RS966T81PG09H7S26RWSGDFW1VVC2QPDMKGFLP'; // 级联选项数据底表

// 获取级联选项
export function fetchData() {
const loading = this.utils.toast({
title: '级联选项获取中...',
type: 'loading'
});
this.dataSourceMap.getData.load({
formUuid,
pageSize: 100,
searchFieldJson: JSON.stringify({
selectField_lfduy8ny: 1, //初始化查找等级为1的顶级名称
})
}).then(({ data }) => {
let arr = data.map(({ formData }) => {
return {
value: formData.textField_lfduy8nw, // 地区名称
label: formData.textField_lfduy8nw, // 地区名称
level: formData.selectField_lfduy8ny, // 级别
}
})
loading();
this.setState({
dataSource: arr
})
}).catch(error => {
loading();
console.log(error)
this.utils.toast({
title: error.message,
type: 'error'
});
});
}

(6) configure cascade asynchronous loading functions

// 级联异步加载数据请求函数
export async function asyncLoadData(node) {
const treeFind = (tree, nodeId, data, falg) => {
if (tree.label === nodeId) {
if (falg) {
// 没有下一级加上标识代表是尾节点
tree.isLeaf = true;
} else {
// 如果找到节点就把数据加入children
tree.children = data;
}
return;
}
if (tree.children) {
for (let child of tree.children) {
treeFind(child, nodeId, data, falg); // 递归判断
}
}
};

const deepClone = (obj) => {
if (obj === null || typeof obj !== "object") {
return obj;
};
const copy = Array.isArray(obj) ? [] : {};
Object.keys(obj).forEach((key) => {
copy[key] = deepClone(obj[key]);
});
return copy;
};

const { dataSource } = this.state;
let cloneData = {
children: deepClone(dataSource)
}; //拷贝数据

try {
const result = await this.dataSourceMap.getData.load({
formUuid,
pageSize: 100,
searchFieldJson: JSON.stringify({
selectField_lfduy8ny: +node.level + 1, //查找当前的等级
selectField_lfdv3l58: node.label, // 父级名称
}),
});

let childList = result.data.map(({ formData }) => {
return {
label: formData.textField_lfduy8nw,
value: formData.textField_lfduy8nw,
level: +node.level + 1,
parent: node.label,
};
});
const falg = childList.length === 0; //是否有下一级数据
treeFind(cloneData, node.label, childList, falg);
this.setState({
dataSource: cloneData.children,
});
} catch (error) {
// 错误提示
this.utils.toast({
title: error.message,
type: "error",
});
}
}

(7) configure fixed parameters

(8) Use in custom pages

async function loadData(node) {
await this.asyncLoadData(node);
}

(9) used in forms

Change the unique identifier.

this.$('cascadeSelectField_lfhkoxd3').set('isLoadData', true);
this.$('cascadeSelectField_lfhkoxd3').set('loadData', async (node) => {
await this.asyncLoadData(node);
});

3. Achieve results

3.1 Use regular

3.2 asynchronous loading

4. Try it online

This doc is generated using machine translation. Any discrepancies or differences created in the translation are not binding and have no legal effect for compliance or enforcement purposes.
Copyright © 2024钉钉(中国)信息技术有限公司和/或其关联公司浙ICP备18037475号-4