fix(@vben-core/form-ui): preserve array field focus
This commit is contained in:
@@ -485,6 +485,37 @@ describe('useVbenForm integration', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('preserves array row inputs and focus while editing', async () => {
|
||||||
|
const [Form] = useVbenForm({
|
||||||
|
schema: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
component: TestInput,
|
||||||
|
fieldName: 'name',
|
||||||
|
label: 'Name',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultValue: [{ name: 'Ada' }],
|
||||||
|
fieldName: 'contacts',
|
||||||
|
type: 'array',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const wrapper = mount(Form, { attachTo: document.body });
|
||||||
|
wrappers.push(wrapper);
|
||||||
|
await flushPromises();
|
||||||
|
const input = wrapper.get('input');
|
||||||
|
const inputElement = input.element;
|
||||||
|
inputElement.focus();
|
||||||
|
|
||||||
|
await input.setValue('Ada Lovelace');
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(wrapper.get('input').element).toBe(inputElement);
|
||||||
|
expect(document.activeElement).toBe(inputElement);
|
||||||
|
});
|
||||||
|
|
||||||
it('scopes resolve dependencies to array rows', async () => {
|
it('scopes resolve dependencies to array rows', async () => {
|
||||||
const resolve = vi.fn(({ schema }: Record<string, any>) => ({
|
const resolve = vi.fn(({ schema }: Record<string, any>) => ({
|
||||||
componentProps: {
|
componentProps: {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
VbenIconButton,
|
VbenIconButton,
|
||||||
VbenRenderContent,
|
VbenRenderContent,
|
||||||
} from '@vben-core/shadcn-ui';
|
} from '@vben-core/shadcn-ui';
|
||||||
import { cn, isObject, set } from '@vben-core/shared/utils';
|
import { cn, set } from '@vben-core/shared/utils';
|
||||||
|
|
||||||
import { injectRenderFormProps } from '../form-render/context';
|
import { injectRenderFormProps } from '../form-render/context';
|
||||||
import FormField from '../form-render/form-field.vue';
|
import FormField from '../form-render/form-field.vue';
|
||||||
@@ -72,8 +72,6 @@ if (!form) {
|
|||||||
}
|
}
|
||||||
const formActions = form;
|
const formActions = form;
|
||||||
const arrayValue = formActions.useFieldValue(props.name);
|
const arrayValue = formActions.useFieldValue(props.name);
|
||||||
const rowKeys = new WeakMap<object, string>();
|
|
||||||
let nextRowKey = 0;
|
|
||||||
|
|
||||||
const fields = computed<Record<string, any>[]>(() => {
|
const fields = computed<Record<string, any>[]>(() => {
|
||||||
return Array.isArray(arrayValue.value) ? arrayValue.value : [];
|
return Array.isArray(arrayValue.value) ? arrayValue.value : [];
|
||||||
@@ -124,20 +122,6 @@ function removeRow(index: number) {
|
|||||||
void formActions.removeFieldValue(arrayPath.value, index);
|
void formActions.removeFieldValue(arrayPath.value, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRowKey(row: Record<string, any>, index: number) {
|
|
||||||
if (!isObject(row)) {
|
|
||||||
return `${arrayPath.value}-${index}`;
|
|
||||||
}
|
|
||||||
const existingKey = rowKeys.get(row);
|
|
||||||
if (existingKey) {
|
|
||||||
return existingKey;
|
|
||||||
}
|
|
||||||
nextRowKey += 1;
|
|
||||||
const key = `${arrayPath.value}-${nextRowKey}`;
|
|
||||||
rowKeys.set(row, key);
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
function rowSchemas(index: number) {
|
function rowSchemas(index: number) {
|
||||||
return props.schema.map((col) =>
|
return props.schema.map((col) =>
|
||||||
createArrayChildSchema(col as never, {
|
createArrayChildSchema(col as never, {
|
||||||
@@ -179,8 +163,8 @@ function rowSchemas(index: number) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-for="(entry, index) in fields"
|
v-for="(_, index) in fields"
|
||||||
:key="getRowKey(entry, index)"
|
:key="`${arrayPath}-${index}`"
|
||||||
class="border-border/60 border-b p-3 last:border-b-0 sm:grid sm:p-0"
|
class="border-border/60 border-b p-3 last:border-b-0 sm:grid sm:p-0"
|
||||||
:style="gridStyle"
|
:style="gridStyle"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user