Извините, я даже не уверен, что это правильный заголовок для моего вопроса.Я пытался сохранить код как можно более легким.
По сути, у меня есть FormArray из FormGroups, каждая из которых состоит из автозаполнения углового материала.Я хочу, чтобы параметры автозаполнения были Observable, чтобы я мог обновлять весь список параметров всякий раз, когда изменяется одна из групп FormGroups в массиве - в основном, когда выбран параметр, я не хочу, чтобы он был в состояниивыбранный любой другой группой FormGroup в массиве.
Но, и именно здесь будет светить мое новшество в angular, я обновляю список опций на valueChanges
, но когда я нажимаю новыйFormGroup для массива, мне нужен тайм-аут, который запускает секунду valueChanges
для того, чтобы параметры автозаполнения появлялись вообще.Если у меня его там нет, то список не отображается в последней добавленной группе FormGroup.
Почему это так?
Код здесь, на stackblitz
Просто нажмите Добавить ввод, и вы увидите список пользователей в автозаполнении, но если вы закомментируете строку 72 и нажмете Добавить ввод, вы не увидитесписок в последней добавленной группе форм.
РЕДАКТИРОВАТЬ
Будет гораздо проще увидеть вопрос, посмотрев код на stackblitz, но потому что я получилпредложили пересмотреть и закрыть, вот код компонента:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormControl, FormArray } from '@angular/forms';
import { switchMap } from 'rxjs/operators';
import { of } from 'rxjs'
const users = [
{
id:1,
name:'user1',
},
{
id:2,
name:'user2',
},
{
id:3,
name:'user3',
}
]
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
usersForm: FormArray;
users = users;
filteredUsers: Observable<any>;
selectedUsers = [];
canAddInput = true;
constructor(private fb: FormBuilder ) {}
ngOnInit() {
this.usersForm = this.fb.array([]);
this
.usersForm
.valueChanges
.subscribe(data => {
this.selectedUsers = data.map(d => d.userNameSelector).filter(d => !!d);
this.canAddInput = this.getUnselectedUsers().length !== 0 && this.usersForm.controls.length < this.users.length
})
//filtered users is an observable
this.filteredUsers = this
.usersForm
.valueChanges
.pipe(
switchMap(() => of(this.getUnselectedUsers()))
)
}
getUnselectedUsers()
{
//console.log(this.users.filter(u => this._isNotSelectedUser(u.name)));
return this.users.filter(u => this._isNotSelectedUser(u.name));
}
_isNotSelectedUser = user => !this.selectedUsers.includes(user)
addInput() {
this.usersForm.push(this.fb.group({userNameSelector:null}));
//why do I need this - it triggers usersForm.valueChanges and filteredUsers is updated, but won't the code work without it why?
setTimeout(() => this.usersForm.updateValueAndValidity(),1);
}
removeInput = idx => this.usersForm.removeAt(idx)
}
и HTML:
<form class="example-form" [formGroup]='usersForm'>
<div *ngIf="usersForm.controls">
<div
*ngFor="let ctrlName of usersForm.controls; let i = index;" [formGroupName]="i">
<mat-form-field class="example-full-width">
<input
matInput
placeholder="Choose a user"
[matAutocomplete]="auto"
formControlName="userNameSelector"
>
</mat-form-field>
<!-- <span>Your choice is: {{usersForm.get(input.name).value | json}}</span> -->
<mat-autocomplete #auto="matAutocomplete">
<mat-option
<!-- this async pipe is going to be important here -->
*ngFor="let user of filteredUsers | async"
[value]="user.name"
>
<span>{{ user.name }}</span>
</mat-option>
</mat-autocomplete>
<button
mat-raised-button
color="warn"
(click)="removeInput(i)"
>Remove Input</button>
</div>
</div>
<button
*ngIf="canAddInput"
mat-raised-button color="primary"
(click)="addInput()"
>Add Input</button>
</form>