对不起,我什至不确定这是否是我的问题的正确标题。我试图使the code尽可能轻。
基本上,我有一个FormGroups的FormArray,每个FormGroups由一个Angular Material Autocomplete组成。我希望自动完成功能的选项是可观察的,以便每当数组中的一个FormGroups更改时,我就可以更新整个选项列表-基本上,每当选择了一个选项时,我都不希望它能够由数组中的任何其他FormGroup选择。
但是,这就是我对角度的新颖性的体现,我正在更新valueChanges
上的选项列表,但是当我在数组上推送新的FormGroup时,我需要一个超时来触发第二个valueChanges
,以便完全显示自动填充选项。如果我没有该列表,则该列表不会显示在最近添加的FormGroup中。
这是为什么?
只需单击“添加输入”,您将在自动完成功能中看到一个用户列表,但是如果注释掉第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>