Обработка асинхронных опций в выпадающих списках и полях автозаполнения с помощью генератора форм в Angular

Вопросы и ответы

Я использую генератор форм для логики в своем приложении, я хочу обрабатывать асинхронные вызовы в выпадающих списках и полях автозаполнения на основе изменений значений некоторых элементов управления формой.

Вот как я строю выпадающий список в любом компоненте:

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 соответствует ожиданиям, и ваши данные правильно отрисовываются.

Если у вас возникнут дополнительные вопросы или вам потребуется дополнительная информация, не стесняйтесь задавать вопросы.

Оцените материал
Добавить комментарий

Капча загружается...