diff --git a/.changeset/long-hairs-throw.md b/.changeset/long-hairs-throw.md
new file mode 100644
index 0000000000..a00b24fda3
--- /dev/null
+++ b/.changeset/long-hairs-throw.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder': patch
+---
+
+Added a new `ui:autoSelect` option to the EntityPicker field that controls whether an entity is automatically selected when the field loses focus. When set to `false`, the field will remain empty if the user closes it without explicitly selecting an entity, preventing unintentional selections. Defaults to `true` for backward compatibility.
diff --git a/docs/features/software-templates/ui-options-examples.md b/docs/features/software-templates/ui-options-examples.md
index 845da8e60b..fd4b20d466 100644
--- a/docs/features/software-templates/ui-options-examples.md
+++ b/docs/features/software-templates/ui-options-examples.md
@@ -119,6 +119,36 @@ entity:
defaultNamespace: payment
```
+### `autoSelect`
+
+Whether to automatically select the highlighted option when the input loses focus. Defaults to `true`.
+
+When set to `false`, users must explicitly select an option from the dropdown by clicking or pressing Enter. This prevents accidental selections when typing to filter options.
+
+- Default behavior with `autoSelect` as `true` (auto-selects on blur)
+
+```yaml
+entity:
+ title: Entity
+ type: string
+ description: Entity of the component
+ ui:field: EntityPicker
+ ui:options:
+ autoSelect: true
+```
+
+- Require explicit selection with `autoSelect` as `false`
+
+```yaml
+entity:
+ title: Entity
+ type: string
+ description: Entity of the component
+ ui:field: EntityPicker
+ ui:options:
+ autoSelect: false
+```
+
## MultiEntityPicker
The input props that can be specified under `ui:options` for the `MultiEntityPicker` field extension.
diff --git a/plugins/scaffolder/report.api.md b/plugins/scaffolder/report.api.md
index e624b157fa..5c0fffbcc1 100644
--- a/plugins/scaffolder/report.api.md
+++ b/plugins/scaffolder/report.api.md
@@ -74,6 +74,7 @@ export const EntityNamePickerFieldExtension: FieldExtensionComponent_2<
export const EntityPickerFieldExtension: FieldExtensionComponent_2<
string,
{
+ autoSelect?: boolean | undefined;
defaultKind?: string | undefined;
defaultNamespace?: string | false | undefined;
catalogFilter?:
@@ -103,6 +104,7 @@ export const EntityPickerFieldExtension: FieldExtensionComponent_2<
export const EntityPickerFieldSchema: FieldSchema_2<
string,
{
+ autoSelect?: boolean | undefined;
defaultKind?: string | undefined;
defaultNamespace?: string | false | undefined;
catalogFilter?:
@@ -249,6 +251,7 @@ export type MyGroupsPickerUiOptions = NonNullable<
export const OwnedEntityPickerFieldExtension: FieldExtensionComponent_2<
string,
{
+ autoSelect?: boolean | undefined;
defaultKind?: string | undefined;
defaultNamespace?: string | false | undefined;
catalogFilter?:
@@ -278,6 +281,7 @@ export const OwnedEntityPickerFieldExtension: FieldExtensionComponent_2<
export const OwnedEntityPickerFieldSchema: FieldSchema_2<
string,
{
+ autoSelect?: boolean | undefined;
defaultKind?: string | undefined;
defaultNamespace?: string | false | undefined;
catalogFilter?:
diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx
index 97c90b2aa5..4b272f1aa0 100644
--- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx
+++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx
@@ -378,6 +378,100 @@ describe('', () => {
});
});
+ describe('ui:autoSelect behavior', () => {
+ beforeEach(() => {
+ uiSchema = {
+ 'ui:options': {
+ defaultKind: 'Group',
+ },
+ };
+ props = {
+ onChange,
+ schema,
+ required,
+ uiSchema,
+ rawErrors,
+ formData,
+ } as unknown as FieldProps;
+
+ catalogApi.getEntities.mockResolvedValue({ items: entities });
+ });
+
+ it('default behavior', async () => {
+ const { getByRole } = await renderInTestApp(
+
+
+ ,
+ );
+
+ const input = getByRole('textbox');
+
+ // Type partial match and blur
+ fireEvent.change(input, { target: { value: 'team' } });
+ fireEvent.blur(input);
+
+ // Default behavior with freeSolo enabled processes the typed value
+ expect(onChange).toHaveBeenCalledWith('group:default/team');
+ });
+
+ it('does not autoSelect value onBlur', async () => {
+ uiSchema = {
+ 'ui:options': {
+ defaultKind: 'Group',
+ autoSelect: false,
+ },
+ };
+ props = {
+ ...props,
+ uiSchema,
+ } as unknown as FieldProps;
+
+ const { getByRole } = await renderInTestApp(
+
+
+ ,
+ );
+
+ const input = getByRole('textbox');
+
+ // Type and blur - with autoSelect=false, the autocomplete won't auto-select on blur
+ fireEvent.change(input, { target: { value: 'team' } });
+ fireEvent.blur(input);
+
+ // With autoSelect=false, onChange should not be called on blur
+ // This is the key difference - users must explicitly select an option
+ expect(onChange).not.toHaveBeenCalled();
+ });
+
+ it('autoSelects entity onBlur', async () => {
+ uiSchema = {
+ 'ui:options': {
+ defaultKind: 'Group',
+ autoSelect: true,
+ },
+ };
+ props = {
+ ...props,
+ uiSchema,
+ } as unknown as FieldProps;
+
+ const { getByRole } = await renderInTestApp(
+
+
+ ,
+ );
+
+ const input = getByRole('textbox');
+
+ // Type and blur
+ fireEvent.change(input, { target: { value: 'squad' } });
+ fireEvent.blur(input);
+
+ // With autoSelect=true and freeSolo, processes the typed value
+ expect(onChange).toHaveBeenCalledWith('group:default/squad');
+ });
+ });
+
describe('uses full entity ref', () => {
beforeEach(() => {
uiSchema = {
diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx
index d2197d4426..9a3dbd0009 100644
--- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx
+++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx
@@ -74,6 +74,7 @@ export const EntityPicker = (props: EntityPickerProps) => {
const defaultKind = uiSchema['ui:options']?.defaultKind;
const defaultNamespace =
uiSchema['ui:options']?.defaultNamespace || undefined;
+ const autoSelect = uiSchema?.['ui:options']?.autoSelect ?? true;
const isDisabled = uiSchema?.['ui:disabled'] ?? false;
const catalogApi = useApi(catalogApiRef);
@@ -209,7 +210,7 @@ export const EntityPicker = (props: EntityPickerProps) => {
: entities?.entityRefToPresentation.get(stringifyEntityRef(option))
?.entityRef!
}
- autoSelect
+ autoSelect={autoSelect}
freeSolo={allowArbitraryValues}
renderInput={params => (