[Bug] 在Vue中,使用多级数据源,并通过数组的方式定义 field 时,Cell 的修改无法同步到数据上
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 3.7k
- Forks
- 486
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 16
Description
Version
1.19.2
Link to Minimal Reproduction
https://www.visactor.io/vtable/demo-vue/edit-data/edit-cell
Steps to Reproduce
复制以下修改后的代码到官方的示例中进行全选替换,修改的要点在于给 birthday: {data: generateRandomBirthday()} 这里给数据源中的birthday添加了一个data层级,然后在定义field时候使用field: ['birthday', 'data']方式指定层级,如此设置后,表格数据读取正常,但是使用birthday的日期编辑器编辑,会发现日期无法更改,似乎响应性丢失。
const input_editor = new VTable_editors.InputEditor();
const date_input_editor = new VTable_editors.DateInputEditor();
VueVTable.register.editor('input-editor', input_editor);
VueVTable.register.editor('date-input-editor', date_input_editor);
function generateRandomString(length) {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
return result;
}
function generateRandomHobbies() {
const hobbies = [
'Reading books',
'Playing video games',
'Watching movies',
'Cooking',
'Hiking',
'Traveling',
'Photography',
'Playing musical instruments',
'Gardening',
'Painting',
'Writing',
'Swimming'
];
const numHobbies = Math.floor(Math.random() * 3) + 1;
const selectedHobbies = [];
for (let i = 0; i < numHobbies; i++) {
const randomIndex = Math.floor(Math.random() * hobbies.length);
selectedHobbies.push(hobbies[randomIndex]);
hobbies.splice(randomIndex, 1);
}
return selectedHobbies.join(', ');
}
function generateRandomBirthday() {
const start = new Date('1970-01-01');
const end = new Date('2000-12-31');
const randomDate = new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
const year = randomDate.getFullYear();
const month = randomDate.getMonth() + 1;
const day = randomDate.getDate();
return `${year}-${month < 10 ? '0' + month : month}-${day < 10 ? '0' + day : day}`;
}
function generateRandomPhoneNumber() {
const areaCode = ['130', '131', '132', '133', '134', '135', '136', '137', '138', '139'];
const prefix = areaCode[Math.floor(Math.random() * areaCode.length)];
const suffix = String(Math.random()).substr(2, 8);
return prefix + suffix;
}
const generatePersons = count => {
return Array.from(new Array(count)).map((_, i) => {
const first = generateRandomString(10);
const last = generateRandomString(4);
return {
id: i + 1,
email1: `${first}_${last}@xxx.com`,
name: first,
lastName: last,
hobbies: generateRandomHobbies(),
birthday: {data: generateRandomBirthday()},
tel: generateRandomPhoneNumber(),
address: `No.${i + 100} ${generateRandomString(10)} ${generateRandomString(5)}`,
sex: i % 2 === 0 ? 'boy' : 'girl',
work: i % 2 === 0 ? 'back-end engineer' : 'front-end engineer',
city: 'beijing'
};
});
};
const records = generatePersons(10);
const columns = [
{ field: 'id', title: 'ID', width: 80, sort: true },
{
field: 'full name',
title: 'Full name',
columns: [
{ field: 'name', title: 'First Name\n(input editor)', width: 120, editor: 'input-editor' },
{ field: 'lastName', title: 'Last Name\n(input editor)', width: 100, editor: 'input-editor' }
]
},
{ field: ['birthday', 'data'], title: 'birthday\n(date editor)', width: 120, editor: 'date-input-editor' },
{ field: 'sex', title: 'sex\n(list editor)', width: 100, editor: 'list-editor' },
{ field: 'address', title: 'address\n(textArea editor)', width: 300, editor: 'textArea-editor' },
{ field: 'tel', title: 'telephone', width: 150 },
{ field: 'work', title: 'job', width: 200 },
{ field: 'city', title: 'city', width: 150 }
];
const option = {
enableLineBreak: true,
autoWrapText: true,
limitMaxAutoWidth: 600,
heightMode: 'autoHeight',
editCellTrigger: 'click',
keyboardOptions: {
copySelected: true,
pasteValueToCell: true,
selectAllOnCtrlA: true
}
};
const app = createApp({
template: `
<vue-list-table :options="option" :records="records">
<ListColumn
v-for="column in columns"
:key="column.field"
:field="column.field"
:title="column.title"
:width="column.width"
:columns="column.columns"
:editor="column.editor"
/>
</vue-list-table>
`,
data() {
return {
records,
columns,
option
};
}
});
app.component('vue-list-table', VueVTable.ListTable);
app.component('ListColumn', VueVTable.ListColumn);
app.mount(`#${CONTAINER_ID}`);
// release Vue instance, do not copy
window.customRelease = () => {
app.unmount();
};
Current Behavior
指定多层级的数据源后,修改无法同步到数据源
Expected Behavior
指定多层级的数据源后,修改可以同步到数据源
Environment
- OS: Windows 11
- Browser: Chrome 138
- Framework: Vue 3.5
Any additional comments?
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked Vue minimal reproduction and the VueVTable.ListTable/ListColumn integration, focusing on the date-input editor for the nested field ['birthday', 'data']. Trace how an edit is written back to records and verify the nested birthday data updates reactively. Done means editing the birthday cell synchronizes the change to the data source.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100