AutoComplete for suggestions with array of type object
Goal: Add Autocmplete Object
Add an AutoComplete for suggestions with array of type object as a search criteria input field for your search page.
Please replace all occurences of exampleStringObject, property1, property2 and exampleStringObjectProperty1, exampleStringObjectProperty2 respectively with the actual names in the following code snippets. |
In this section, we aim to add an AutoComplete input field. The suggestions will be an array of type string. For this use case, we want to display property1
(a string type property of the object) in the input field and the suggestions and perform a search with property2
for the search criteria. The object has the following interface:
...
export interface ExampleStringObject {
property1?: string;
property2?: string;
}
...
1. Parameters
Please define the member for your <%= featurePropertyName %>SearchCriteriasSchema
here
Adapt in File: <feature>-search.parameters.ts
exampleStringObjectProperty2: z.string().optional(),
2. State & viewmodel
Add additional array member for the AutoComplete suggestions in your state and viewmodel:
Adapt in Files: <feature>-search.state.ts
...
exampleStringObjectOptions: ExampleStringObject[];
exampleStringObjectProperty1InputText: string;
...
Adapt in Files: <feature>-search.viewmodel.ts
...
exampleStringObjectOptions: ExampleStringObject[];
selectedExampleStringObject: ExampleStringObject | null;
...
3. Actions
Create following actions to handle the events regarding AutoComplete:
Adapt in File: <feature>-search.actions.ts
...
events: {
'exampleStringObject field changed': props<{ exampleObjectProperty1InputText: string }>(),
'exampleStringObject options loaded successfully': props<{
exampleStringObjectOptions: ExampleStringObject[];
}>(),
'exampleStringObject options loading failed': emptyProps(),
'exampleStringObject option selected': props<{
exampleStringObjectOption: ExampleStringObject;
}>(),
'restored selected exampleStringObject on page reload': emptyProps(),
'restored selected exampleStringObject on page reload successfully': props<{
selectedExampleStringObject: ExampleStringObject;
}>(),
'restored selected exampleStringObject on page reload failed': props<{
error: string | null;
}>(),
},
...
4. HTML
Add the following code to your formGroup in the html file:
Adapt in File: <feature>-search.component.html
<span class="p-float-label">
<p-autoComplete
id="exampleStringObject"
formControlName="exampleStringObject"
(completeMethod)="searchExampleStringObject($event)"
optionLabel="property1"
optionValue="property2"
appendTo="body"
[suggestions]="vm?.exampleStringObjectOptions ?? []"
[forceSelection]="true"
[multiple]="true" <-- ONLY NECESSARY IF MULTIPLE VALUES CAN BE SELECTED
[showEmptyMessage]="true"
[emptyMessage]="
vm?.exampleStringObjectOptions?.length === 0
? ('YOUR_PRODUCT_SEARCH.CRITERIA.EXAMPLE_ID_NOT_FOUND' | translate)
: ''
"
(onSelect)="exampleStringObjectSelected($event)"
>
</p-autoComplete>
<label for="exampleStringObject">{{
'YOUR_PRODUCT_SEARCH.CRITERIA.ID' | translate
}}</label>
</span>
5. Component
Add the respective methods to handle the different events:
Adapt in File: <feature>-search.component.ts
...
exampleStringObjectSearch(event: AutoCompleteCompleteEvent) {
this.store.dispatch(
<feature>SearchActions.exampleStringObjectFieldChanged({
exampleStringObjectProperty1InputText: event.query,
}),
);
}
exampleStringObjectSelected(event: AutoCompleteSelectEvent) {
this.store.dispatch(
<feature>SearchActions.exampleStringObjectOptionSelected({ option: event.value }),
);
}
...
6. Reducers
In the reducers file you need to define the functions:
Adapt in File: <feature>-search.reducers.ts
...
on(
<%= featureClassName %>SearchActions.exampleStringObjectOptionsLoadedSuccessfully,
(state: <%= featureClassName %>SearchState, { exampleStringObjectOptions }): <%= featureClassName %>SearchState => ({
...state,
exampleStringObjectOptions: exampleStringObjectOptions,
}),
),
on(
<%= featureClassName %>SearchActions.exampleStringObjectOptionsLoadingFailed,
(state: <%= featureClassName %>SearchState): <%= featureClassName %>SearchState => ({
...state,
exampleStringObjectOptions: [],
}),
),
on(
<%= featureClassName %>SearchActions.exampleStringObjectFieldChanged,
(
state: <%= featureClassName %>SearchState,
{ exampleStringObjectProperty1InputText },
): <%= featureClassName %>SearchState => ({
...state,
exampleStringObjectProperty1InputText: exampleStringObjectProperty1InputText,
});
},
),
on(
<%= featureClassName %>SearchActions.exampleStringObjectOptionSelected,
(
state: <%= featureClassName %>SearchState,
{ exampleStringObjectOption },
): <%= featureClassName %>SearchState => ({
...state,
exampleStringObjectProperty1InputText: exampleStringObjectOption?.property1 ?? '',
}),
),
on(
<%= featureClassName %>SearchActions.restoredSelectedExampleStringObjectOnPageReloadSuccessfully,
(
state: <%= featureClassName %>SearchState,
{ selectedExampleStringObject },
): <%= featureClassName %>SearchState => ({
...state,
exampleStringObjectProperty1InputText: selectedExampleStringObject.property1 ?? '',
exampleStringObjectOptions: [selectedExampleStringObject],
}),
),
on(
<%= featureClassName %>SearchActions.restoredSelectedExampleStringObjectOnPageReloadFailed,
(state: <%= featureClassName %>SearchState): <%= featureClassName %>SearchState => ({
...state,
exampleStringObjectProperty1InputText: '',
}),
),
...
7. Selectors
Add the missing selectors:
Adapt in File: <feature>-search.selectors.ts
...
export const selectSelectedExampleStringObject = createSelector(
<feature>SearchSelectors.selectExampleStringObjectProperty1InputText,
<feature>SearchSelectors.selectCriteria,
(
exampleStringObjectProperty1InputText: string,
searchCriteria: <%= featureClassName %>SearchCriteria,
): ExampleStringObject | null => {
if (exampleStringObjectProperty1InputText?.length && searchCriteria?.exampleStringObjectProperty2) {
return {
property1: exampleStringObjectProperty1InputText,
property2: searchCriteria.exampleStringObjectProperty2,
};
}
return null;
},
);
export const select<%= featureClassName %>SearchViewModel = createSelector(
...
<feature>SearchSelectors.selectExampleStringObjectOptions,
selectSelectedExampleStringObject,
...
(
...
exampleStringObjectOptions,
selectedExampleStringObject,
...
): <%= featureClassName %>SearchViewModel => ({
...
exampleStringObjectOptions,
selectedExampleStringObject,
...
}),
);
...
8. Effects
Create the effect for getting the suggestions
Adapt in File: <feature>-search.effects.ts
...
searchExampleStringObject$ = createEffect(() =>
this.actions$.pipe(
ofType(<%= featureClassName %>SearchActions.exampleStringObjectFieldChanged),
filter((action) => action.exampleStringObjectProperty1InputText.length > 2),
mergeMap((action) => {
return this.<feature>Service
.searchExampleStringObject(action.exampleStringObjectProperty1InputText)
.pipe(
map((response) =>
<%= featureClassName %>SearchActions.exampleStringObjectOptionsLoadedSuccessfully({
exampleStringObjectOptions: response.exampleStringObjects,
}),
),
catchError(() =>
of(<%= featureClassName %>SearchActions.exampleStringObjectOptionsLoadingFailed()),
),
);
}),
),
);
restoreSelectedExampleStringObject$ = createEffect(() =>
this.actions$.pipe(
ofType(routerNavigatedAction),
filterForNavigatedTo(this.router, <%= featureClassName %>SearchComponent),
filterOutOnlyQueryParamsChanged(this.router),
filter(
(action) => action?.payload?.routerState?.root?.queryParams['exampleStringObjectProperty2'],
),
concatLatestFrom(() =>
this.store.select(<feature>SearchSelectors.selectCriteria),
),
switchMap(([action]) =>
this.<feature>Service
.searchExampleStringObject(
'',
action?.payload?.routerState?.root?.queryParams['exampleStringObjectProperty2'],
)
.pipe(
map((exampleStringObject) =>
<%= featureClassName %>SearchActions.restoredSelectedExampleStringObjectOnPageReloadSuccessfully(
{ selectedExampleStringObject: exampleStringObject?.exampleStringObjects[0] },
),
),
catchError((error) =>
of(
<%= featureClassName %>SearchActions.restoredSelectedExampleStringObjectOnPageReloadFailed(
{ error },
),
),
),
),
),
),
);
...
Don’t forget to add the translations to your de.json and en.json. |