feat: add configuration and live demo for ArcoVue as Editor

This commit is contained in:
YEL!ne 2024-09-24 17:26:43 +08:00
parent d081b32d70
commit 07db9ae60d
5 changed files with 431 additions and 9 deletions

View File

@ -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==}

View File

@ -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}`);

View File

@ -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}`);

View File

@ -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:*",

View File

@ -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;