mirror of
https://github.com/VisActor/VTable
synced 2024-11-22 10:03:28 +00:00
Merge pull request #2500 from YELineee/feat-vue-vtable-docs
feat: add configuration and live demo for ArcoVue as Editor
This commit is contained in:
commit
657b0b2466
@ -8,6 +8,7 @@ importers:
|
||||
../../docs:
|
||||
specifiers:
|
||||
'@arco-design/web-react': 2.60.2
|
||||
'@arco-design/web-vue': ^2.11.0
|
||||
'@internal/eslint-config': workspace:*
|
||||
'@internal/ts-config': workspace:*
|
||||
'@types/buble': ^0.20.5
|
||||
@ -47,6 +48,7 @@ importers:
|
||||
yargs: ^17.1.1
|
||||
dependencies:
|
||||
'@arco-design/web-react': 2.60.2_52ux7kpa62vlx2is4pxiuz7b44
|
||||
'@arco-design/web-vue': 2.56.1_vue@3.5.0
|
||||
'@visactor/openinula-vtable': link:../packages/openinula-vtable
|
||||
'@visactor/react-vtable': link:../packages/react-vtable
|
||||
'@visactor/vchart': 1.12.1
|
||||
@ -1130,7 +1132,6 @@ packages:
|
||||
resize-observer-polyfill: 1.5.1
|
||||
scroll-into-view-if-needed: 2.2.31
|
||||
vue: 3.5.0_typescript@4.9.5
|
||||
dev: true
|
||||
|
||||
/@babel/code-frame/7.24.7:
|
||||
resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==}
|
||||
@ -12374,7 +12375,6 @@ packages:
|
||||
resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==}
|
||||
dependencies:
|
||||
compute-scroll-into-view: 1.0.20
|
||||
dev: true
|
||||
|
||||
/semver-compare/1.0.0:
|
||||
resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==}
|
||||
|
@ -1,21 +1,229 @@
|
||||
---
|
||||
category: examples
|
||||
group: functional-components
|
||||
title: 自定义编辑器中使用arco列表选择器
|
||||
title: Using Arco Select in Custom Editor
|
||||
cover:
|
||||
link: '../guide/Developer_Ecology/vue'
|
||||
---
|
||||
|
||||
# 自定义编辑器中使用 arco 列表选择器
|
||||
# Using Arco Select in Custom Editor
|
||||
|
||||
创建自定义编辑器类 ArcoListEditor, 并实现 onStart 方法,创建一个 arco-design 的 Select 组件,并将组件挂载到编辑器容器中。完善 isEditorElement 和 onEnd 方法。
|
||||
Create a custom editor class `ArcoListEditor` and implement the `onStart` method to create an Arco Design `Select` component and mount it to the editor container. Complete the `isEditorElement` and `onEnd` methods.
|
||||
|
||||
参考:
|
||||
References:
|
||||
|
||||
https://visactor.io/vtable/guide/edit/edit_cell
|
||||
|
||||
https://arco.design/vue/components/select
|
||||
|
||||
## 代码演示
|
||||
## Code Demonstration
|
||||
|
||||
```javascript livedemo template=vtable-vue
|
||||
```javascript livedemo template=vtable-vue
|
||||
|
||||
class ArcoListEditor {
|
||||
root = null;
|
||||
element = null;
|
||||
container = null;
|
||||
currentValue = null;
|
||||
|
||||
onStart(editorContext) {
|
||||
const { container, referencePosition, value } = editorContext;
|
||||
this.container = container;
|
||||
this.createElement(value);
|
||||
if (value) this.setValue(value);
|
||||
if (referencePosition?.rect) this.adjustPosition(referencePosition.rect);
|
||||
}
|
||||
|
||||
createElement(defaultValue) {
|
||||
const div = document.createElement('div');
|
||||
div.style.position = 'absolute';
|
||||
div.style.width = '100%';
|
||||
div.style.padding = '1px';
|
||||
div.style.boxSizing = 'border-box';
|
||||
this.container?.appendChild(div);
|
||||
|
||||
const app = this.createVueApp(defaultValue);
|
||||
app.mount(div);
|
||||
this.root = app;
|
||||
this.element = div;
|
||||
}
|
||||
|
||||
createVueApp(defaultValue) {
|
||||
const self = this;
|
||||
return createApp({
|
||||
data() {
|
||||
return {
|
||||
currentValue: defaultValue,
|
||||
options: ['Beijing', 'Shanghai', 'Guangzhou'],
|
||||
};
|
||||
},
|
||||
render() {
|
||||
return h('div', {}, [
|
||||
h(ArcoDesignVue.Select, {
|
||||
style: { height: '32px' },
|
||||
placeholder: 'Select city',
|
||||
modelValue: this.currentValue,
|
||||
'onUpdate:modelValue': (value) => {
|
||||
this.currentValue = value;
|
||||
self.setValue(value);
|
||||
},
|
||||
}, {
|
||||
default: () =>
|
||||
this.options.map((option) =>
|
||||
h(ArcoDesignVue.Option, { key: option, value: option }, { default: () => option })
|
||||
),
|
||||
}),
|
||||
]);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.currentValue;
|
||||
}
|
||||
|
||||
setValue(value) {
|
||||
this.currentValue = value;
|
||||
}
|
||||
|
||||
adjustPosition(rect) {
|
||||
if (this.element) {
|
||||
this.element.style.top = `${rect.top}px`;
|
||||
this.element.style.left = `${rect.left}px`;
|
||||
this.element.style.width = `${rect.width}px`;
|
||||
this.element.style.height = `${rect.height}px`;
|
||||
}
|
||||
}
|
||||
|
||||
onEnd() {
|
||||
if (this.root) {
|
||||
this.root.unmount();
|
||||
this.root = null;
|
||||
}
|
||||
if (this.element && this.container) {
|
||||
this.container.removeChild(this.element);
|
||||
this.element = null;
|
||||
}
|
||||
}
|
||||
|
||||
isEditorElement(target) {
|
||||
return this.element?.contains(target) || this.isClickPopUp(target);
|
||||
}
|
||||
|
||||
isClickPopUp(target) {
|
||||
while (target) {
|
||||
if (target.classList && target.classList.contains('arco-select')) {
|
||||
return true;
|
||||
}
|
||||
target = target.parentNode;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const input_editor = new VTable_editors.InputEditor();
|
||||
const date_input_editor = new VTable_editors.DateInputEditor();
|
||||
VTable.register.editor('input-editor', input_editor);
|
||||
VTable.register.editor('date-input-editor', date_input_editor);
|
||||
VTable.register.editor('arcoVue-editor', new ArcoListEditor());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
address: `No.${i + 100} ${generateRandomString(10)} ${generateRandomString(5)} ${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: 140,
|
||||
editor: 'input-editor',
|
||||
},
|
||||
{
|
||||
field: 'lastName',
|
||||
title: 'Last Name\n(input editor)',
|
||||
width: 100,
|
||||
editor: 'input-editor',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
field: 'address',
|
||||
title: 'location\n(arcoVue-editor)',
|
||||
width: 400,
|
||||
editor: 'arcoVue-editor',
|
||||
},
|
||||
];
|
||||
|
||||
const option = {
|
||||
enableLineBreak: true,
|
||||
autoWrapText: true,
|
||||
limitMaxAutoWidth: 700,
|
||||
heightMode: 'autoHeight',
|
||||
editCellTrigger: 'click',
|
||||
keyboardOptions: {
|
||||
copySelected: true,
|
||||
pasteValueToCell: true,
|
||||
selectAllOnCtrlA: true,
|
||||
},
|
||||
};
|
||||
|
||||
const app = createApp({
|
||||
template: `
|
||||
<ListTable :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"
|
||||
/>
|
||||
</ListTable>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
records,
|
||||
columns,
|
||||
option,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
app.component('ListTable', VueVTable.ListTable);
|
||||
app.component('ListColumn', VueVTable.ListColumn);
|
||||
|
||||
app.mount(`#${CONTAINER_ID}`);
|
||||
|
@ -18,4 +18,214 @@ https://arco.design/vue/components/select
|
||||
|
||||
## 代码演示
|
||||
|
||||
```javascript livedemo template=vtable-vue
|
||||
```javascript livedemo template=vtable-vue
|
||||
|
||||
|
||||
class ArcoListEditor {
|
||||
root = null;
|
||||
element = null;
|
||||
container = null;
|
||||
currentValue = null;
|
||||
|
||||
onStart(editorContext) {
|
||||
const { container, referencePosition, value } = editorContext;
|
||||
this.container = container;
|
||||
this.createElement(value);
|
||||
if (value) this.setValue(value);
|
||||
if (referencePosition?.rect) this.adjustPosition(referencePosition.rect);
|
||||
}
|
||||
|
||||
createElement(defaultValue) {
|
||||
const div = document.createElement('div');
|
||||
div.style.position = 'absolute';
|
||||
div.style.width = '100%';
|
||||
div.style.padding = '1px';
|
||||
div.style.boxSizing = 'border-box';
|
||||
this.container?.appendChild(div);
|
||||
|
||||
const app = this.createVueApp(defaultValue);
|
||||
app.mount(div);
|
||||
this.root = app;
|
||||
this.element = div;
|
||||
}
|
||||
|
||||
createVueApp(defaultValue) {
|
||||
const self = this;
|
||||
return createApp({
|
||||
data() {
|
||||
return {
|
||||
currentValue: defaultValue,
|
||||
options: ['Beijing', 'Shanghai', 'Guangzhou'],
|
||||
};
|
||||
},
|
||||
render() {
|
||||
return h('div', {}, [
|
||||
h(ArcoDesignVue.Select, {
|
||||
style: { height: '32px' },
|
||||
placeholder: 'Select city',
|
||||
modelValue: this.currentValue,
|
||||
'onUpdate:modelValue': (value) => {
|
||||
this.currentValue = value;
|
||||
self.setValue(value);
|
||||
},
|
||||
}, {
|
||||
default: () =>
|
||||
this.options.map((option) =>
|
||||
h(ArcoDesignVue.Option, { key: option, value: option }, { default: () => option })
|
||||
),
|
||||
}),
|
||||
]);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.currentValue;
|
||||
}
|
||||
|
||||
setValue(value) {
|
||||
this.currentValue = value;
|
||||
}
|
||||
|
||||
adjustPosition(rect) {
|
||||
if (this.element) {
|
||||
this.element.style.top = `${rect.top}px`;
|
||||
this.element.style.left = `${rect.left}px`;
|
||||
this.element.style.width = `${rect.width}px`;
|
||||
this.element.style.height = `${rect.height}px`;
|
||||
}
|
||||
}
|
||||
|
||||
onEnd() {
|
||||
if (this.root) {
|
||||
this.root.unmount();
|
||||
this.root = null;
|
||||
}
|
||||
if (this.element && this.container) {
|
||||
this.container.removeChild(this.element);
|
||||
this.element = null;
|
||||
}
|
||||
}
|
||||
|
||||
isEditorElement(target) {
|
||||
return this.element?.contains(target) || this.isClickPopUp(target);
|
||||
}
|
||||
|
||||
isClickPopUp(target) {
|
||||
while (target) {
|
||||
if (target.classList && target.classList.contains('arco-select')) {
|
||||
return true;
|
||||
}
|
||||
target = target.parentNode;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const input_editor = new VTable_editors.InputEditor();
|
||||
const date_input_editor = new VTable_editors.DateInputEditor();
|
||||
VTable.register.editor('input-editor', input_editor);
|
||||
VTable.register.editor('date-input-editor', date_input_editor);
|
||||
VTable.register.editor('arcoVue-editor', new ArcoListEditor());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
address: `No.${i + 100} ${generateRandomString(10)} ${generateRandomString(5)} ${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: 140,
|
||||
editor: 'input-editor',
|
||||
},
|
||||
{
|
||||
field: 'lastName',
|
||||
title: 'Last Name\n(input editor)',
|
||||
width: 100,
|
||||
editor: 'input-editor',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
field: 'address',
|
||||
title: 'location\n(arcoVue-editor)',
|
||||
width: 400,
|
||||
editor: 'arcoVue-editor',
|
||||
},
|
||||
];
|
||||
|
||||
const option = {
|
||||
enableLineBreak: true,
|
||||
autoWrapText: true,
|
||||
limitMaxAutoWidth: 700,
|
||||
heightMode: 'autoHeight',
|
||||
editCellTrigger: 'click',
|
||||
keyboardOptions: {
|
||||
copySelected: true,
|
||||
pasteValueToCell: true,
|
||||
selectAllOnCtrlA: true,
|
||||
},
|
||||
};
|
||||
|
||||
const app = createApp({
|
||||
template: `
|
||||
<ListTable :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"
|
||||
/>
|
||||
</ListTable>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
records,
|
||||
columns,
|
||||
option,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
app.component('ListTable', VueVTable.ListTable);
|
||||
app.component('ListColumn', VueVTable.ListColumn);
|
||||
|
||||
app.mount(`#${CONTAINER_ID}`);
|
||||
|
@ -11,6 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@arco-design/web-react": "2.60.2",
|
||||
"@arco-design/web-vue": "^2.11.0",
|
||||
"@visactor/vtable": "workspace:*",
|
||||
"@visactor/react-vtable": "workspace:*",
|
||||
"@visactor/vue-vtable": "workspace:*",
|
||||
|
@ -13,11 +13,14 @@ import * as VueVTable from '@visactor/vue-vtable';
|
||||
import * as InulaVTable from '@visactor/openinula-vtable';
|
||||
import { App } from './app';
|
||||
import * as ArcoDesign from '@arco-design/web-react';
|
||||
import * as ArcoDesignVue from '@arco-design/web-vue';
|
||||
import * as ArcoDesignIcon from '@arco-design/web-react/icon';
|
||||
import '@arco-design/web-react/dist/css/arco.css';
|
||||
import '@arco-design/web-vue/dist/arco.css';
|
||||
import { createApp, ref, onMounted, h } from 'vue';
|
||||
|
||||
(window as any).ArcoDesign = ArcoDesign;
|
||||
(window as any).ArcoDesignVue = ArcoDesignVue;
|
||||
(window as any).ArcoDesignIcon = ArcoDesignIcon;
|
||||
(window as any).VTable = VTable;
|
||||
(window as any).VRender = VRender;
|
||||
|
Loading…
Reference in New Issue
Block a user