Я использую генератор форм для логики в своем приложении, я хочу обрабатывать асинхронные вызовы в выпадающих списках и полях автозаполнения на основе изменений значений некоторых элементов управления формой.
Вот как я строю выпадающий список в любом компоненте:
new DropdownInput({
name: 'Название агентства',
multiple: true,
formControlName: 'agencyIds',
classes: 'col-lg-4 col-md-12 col-sm-12',
placeholder: 'Shams travel',
asyncOptions: (pageSize, pageNo) => this.manageAgency.getAll({ status: 1 }, { pageSize, pageNo }).pipe(map((res) => res.payload)),
optionLabel: 'name',
optionValue: 'id',
VirtualScroll: true,
VirtualScrollObject: {
virtualScrollItemSize: 43,
},
}),
А вот как я обрабатываю варианты в DropDownInputComponent:
getOptions(): void {
if (this.input.asyncOptions) {
this.isLoading = true
this.input.asyncOptions(this.pageSize, this.currentPage).subscribe((options) => {
this.isLoading = false
this.options = options
})
this.cdr.detectChanges()
} else {
if (!(this.input.options instanceof Array)) {
;(this.input.options as () => Observable<unknown[]>)().subscribe((options) => (this.options = options))
} else {
this.options = this.input.options
this.cdr.detectChanges()
}
}
}
На данный момент логика работает отлично.
Я хочу добавить еще одну логику в asyncOptions, чтобы она принимала строку, которая будет именем элемента управления формой, чтобы я мог подписаться на ее изменения в DropDownInputComponent и обновить варианты на основе этого.
Я определил asyncOptions следующим образом:
asyncOptions?: (size: number, page: number) => Observable<T[]> | ((formControlName: string) => Observable<T[]>)
А в некоторых случаях это будет выглядеть так:
new DropdownInput({
name: 'Название агентства',
multiple: true,
formControlName: 'agencyIds',
classes: 'col-lg-4 col-md-12 col-sm-12',
placeholder: 'Shams travel',
asyncOptions: ('countryId') => this.manageAgency.getAll({ status: 1 }).pipe(map((res) => res.payload)),
optionLabel: 'name',
optionValue: 'id',
VirtualScroll: true,
VirtualScrollObject: {
virtualScrollItemSize: 43,
},
}),
Я не знаю, как я могу получить доступ к аргументу countryId в DropDownInputComponent, чтобы я мог обработать логику.
Ответ
Чтобы решить вашу задачу с асинхронными опциями в выпадающих списках и полях автозаполнения в Angular, мы можем модернизировать ваш компонент DropDownInputComponent
так, чтобы он мог обрабатывать асинхронные вызовы как с использованием страницы и номера страницы, так и с учетом изменений других полей формы. Давайте разберем, как это сделать, шаг за шагом.
1. Обновление определения asyncOptions
Вы уже правильно определили asyncOptions
как функцию, которая может принимать либо параметры для пагинации, либо строку с именем поля формы. Однако при передаче имени поля в asyncOptions
, наша задача заключается в том, чтобы подписаться на изменения этого контрола.
2. Изменение DropDownInputComponent
Нам нужно немного изменить ваш компонент getOptions
, чтобы он мог обрабатывать оба варианта. Вот обновленная версия вашего метода:
getOptions(): void {
const controlName = this.input.asyncOptions instanceof Function ? this.input.asyncOptions : undefined;
if (controlName) {
// Подписываемся на изменения в контроле
this.form.get(controlName)?.valueChanges.subscribe((newValue) => {
// Здесь нужно вызывать вашу функцию асинхронного запроса
this.fetchOptions(newValue);
});
} else if (this.input.asyncOptions) {
this.isLoading = true;
this.input.asyncOptions(this.pageSize, this.currentPage).subscribe((options) => {
this.isLoading = false;
this.options = options;
});
} else {
if (!(this.input.options instanceof Array)) {
(this.input.options as () => Observable<unknown[]> )().subscribe((options) => (this.options = options));
} else {
this.options = this.input.options;
}
}
}
private fetchOptions(countryId: string): void {
this.isLoading = true;
this.manageAgency.getAll({ status: 1, countryId }).pipe(map((res) => res.payload)).subscribe((options) => {
this.isLoading = false;
this.options = options;
this.cdr.detectChanges();
});
}
3. Обновление входных параметров DropdownInput
Необходимо убедиться, что вы правильно передаете asyncOptions
при создании DropdownInput
. Вот пример:
new DropdownInput({
name: 'Agency Name',
multiple: true,
formControlName: 'agencyIds',
classes: 'col-lg-4 col-md-12 col-sm-12',
placeholder: 'Shams travel',
asyncOptions: (countryId: string) => this.manageAgency.getAll({ status: 1, countryId }).pipe(map((res) => res.payload)),
optionLabel: 'name',
optionValue: 'id',
VirtualScroll: true,
VirtualScrollObject: {
virtualScrollItemSize: 43,
},
}),
4. Работа с изменениями в контроле
Когда значение другого контрола формы изменяется (например, countryId
), подписка, которую мы настроили в getOptions()
, будет вызвана. Это приведет к выполнению запроса по репозиторию manageAgency
с новым значением countryId
, и обновленные опции будут загружены и установлены в options
.
5. Обновление шаблона
Убедитесь, что в шаблоне вашего компонента DropDownInputComponent
вы корректно обрабатываете состояние загрузки и отображаете опции выборки.
Эти изменения позволят вашему DropDownInputComponent
динамически загружать опции на основе изменения других контролов формы. Убедитесь, что ваша логика работы с API соответствует ожиданиям, и ваши данные правильно отрисовываются.
Если у вас возникнут дополнительные вопросы или вам потребуется дополнительная информация, не стесняйтесь задавать вопросы.