fix(editor): Input loses focus after typing to a fixed collection parameter (#19372)

This commit is contained in:
Suguru Inoue
2025-09-10 15:26:04 +02:00
committed by GitHub
parent 2514301abd
commit 815ecfe680
2 changed files with 61 additions and 2 deletions

View File

@@ -4,7 +4,10 @@ import FixedCollectionParameter, { type Props } from '@/components/FixedCollecti
import { STORES } from '@n8n/stores'; import { STORES } from '@n8n/stores';
import { createTestingPinia } from '@pinia/testing'; import { createTestingPinia } from '@pinia/testing';
import userEvent from '@testing-library/user-event'; import userEvent from '@testing-library/user-event';
import { fireEvent, waitFor } from '@testing-library/vue';
import { setActivePinia } from 'pinia'; import { setActivePinia } from 'pinia';
import { nextTick } from 'vue';
describe('FixedCollectionParameter.vue', () => { describe('FixedCollectionParameter.vue', () => {
const pinia = createTestingPinia({ const pinia = createTestingPinia({
initialState: { initialState: {
@@ -107,4 +110,51 @@ describe('FixedCollectionParameter.vue', () => {
], ],
]); ]);
}); });
it('[SUG-128] maintains focus after receiving updated values even when the inner most property shares the same name with its parent', async () => {
const myProps: Props = {
...props,
parameter: {
...props.parameter,
options: [
{
name: 'p0',
displayName: 'Values',
values: [
{
displayName: 'Output Name',
name: 'p0',
type: 'string',
default: '',
},
],
},
],
},
};
const rendered = renderComponent({
props: {
...myProps,
nodeValues: { parameters: { rules: { p0: [{ p0: 'Test' }] } } },
values: { p0: [{ p0: 'Test' }] },
},
});
const input = rendered.getByRole('textbox');
await waitFor(() => expect(input).toHaveValue('Test'));
await fireEvent.focus(input);
expect(document.activeElement).toBe(input);
await rendered.rerender({
...myProps,
nodeValues: { parameters: { rules: { p0: [{ p0: 'Updated' }] } } },
values: { p0: [{ p0: 'Updated' }] },
});
await nextTick();
expect(input).toBeInTheDocument();
expect(input).toHaveValue('Updated');
expect(document.activeElement).toBe(input);
});
}); });

View File

@@ -1,7 +1,12 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { IUpdateInformation } from '@/Interface'; import type { IUpdateInformation } from '@/Interface';
import type { INodeParameters, INodeProperties, NodeParameterValueType } from 'n8n-workflow'; import type {
INodeParameters,
INodeProperties,
INodePropertyCollection,
NodeParameterValueType,
} from 'n8n-workflow';
import { deepCopy, isINodePropertyCollectionList } from 'n8n-workflow'; import { deepCopy, isINodePropertyCollectionList } from 'n8n-workflow';
import get from 'lodash/get'; import get from 'lodash/get';
@@ -229,6 +234,10 @@ const trackWorkflowInputFieldAdded = () => {
node_id: ndvStore.activeNode?.id, node_id: ndvStore.activeNode?.id,
}); });
}; };
function getItemKey(item: INodeParameters, property: INodePropertyCollection) {
return mutableValues.value[property.name]?.indexOf(item) ?? -1;
}
</script> </script>
<template> <template>
@@ -257,7 +266,7 @@ const trackWorkflowInputFieldAdded = () => {
/> />
<div v-if="multipleValues"> <div v-if="multipleValues">
<Draggable <Draggable
:item-key="property.name" :item-key="(item: INodeParameters) => getItemKey(item, property)"
v-model="mutableValues[property.name]" v-model="mutableValues[property.name]"
handle=".drag-handle" handle=".drag-handle"
drag-class="dragging" drag-class="dragging"