问题描述
我正在尝试在FormArray中实现垫自动完成功能.我遵循了此链接,但是当我尝试从下面的示例中放入此代码时,尝试打开链接时,控制台会出现很多错误:
编辑
在您的建议@polyglot之后,一些错误消失了,只是该数组的异步管道和ngFor出现了问题,如下图所示,并且this.filteredEmployees [index]的错误manageNameControl.
类型'Observable< Observable< IEmployee []>''不可分配给可观察"类型.输入"Observable< IEmployee []>"缺少"IEmployee"类型的以下属性:id,firstName,
已解决
我已经解决了filteredEmyployee的问题
filteredEmployees:IEmployee [] 和manageNameControl方法看起来像
manageNameControl(index:number){var arrayControl = this.createProjectForm.get('projectTeamMembers')as FormArray;arrayControl.at(index).get('employeeId').valueChanges.管道(debounceTime(300),switchMap((value)=> this.projectManagementService.filterEmployees(value)),).subscribe((employees:IEmployee [])=>(this.filteredEmployees =员工));}
并从html表单中删除了aync管道
< mat-form-field fxFlex ="100%"><输入matInput formControlName ='employeeId'name ='employeeId'placeholder ="开始键入雇员的名字或姓氏."[matAutocomplete] =自动"< mat-error * ngIf ="t.get('employeeId').errors..required">{{'FIELD_REQUIRED_MESSAGE'|翻译 }}</mat-error></mat-form-field>< mat-autocomplete #auto =" matAutocomplete"[displayWith] ="employeeTypeaheadDisplayFn(filteredEmployees)"< mat-option * ngFor =让已过滤雇员的雇员"[值] ="employee.id"{{employee.firstName}} {{employee.lastName}}</mat-option></mat-autocomplete>
I'm trying to implement mat autocomplete in FormArray. I followed this link but my console have a lot of errors when I try to open link when put this code like example from below:
https://stackblitz.com/edit/angular-szxkme-yfphur?file=app%2Fautocomplete-display-example.ts
create-project.ts
export class CreateProjectComponent implements OnInit {
pageNavigation: IPageNavigation = {
pageTitle: 'Project Management',
subPages: [{ label: 'Projects', link: '/projects' }],
};
createProjectForm: FormGroup;
projectTeamMemberFormArray = new FormArray([]);
filteredEmployees: Observable<IEmployee[]>;
constructor(
private formBuilder: FormBuilder,
private projectManagementService: ProjectManagementService
) { }
ngOnInit(): void {
this.buildForm();
}
buildForm(): void {
this.createProjectForm = this.formBuilder.group({
projectTeamMembers: this.projectTeamMemberFormArray
});
}
manageNameControl(index: number) {
var arrayControl = this.createProjectForm.get('projectTeamMembers') as FormArray;
this.filteredEmployees[index] = arrayControl.at(index).get('firstName').valueChanges
.pipe(
startWith<string | IEmployee>(''),
map(value => typeof value === 'string' ? value : value.firstName),
map(name => name ? this.projectManagementService.filterEmployees(name) : null)
);
}
addProjectTeamMember(teamMember?: IProjectMember): void {
this.projectTeamMemberFormArray = this.createProjectForm.get('projectTeamMembers') as FormArray;
this.projectTeamMemberFormArray.push(this.createProjectTeamMemberItem(teamMember));
this.manageNameControl(this.projectTeamMemberFormArray.length - 1);
}
createProjectTeamMemberItem(teamMember?: IProjectMember): FormGroup {
return this.formBuilder.group({
employeeId: new FormControl((teamMember && teamMember.employeeId) || null, Validators.required),
firstName: new FormControl((teamMember && teamMember.firstName) || null, Validators.required),
memberRoles: new FormControl((teamMember && teamMember.projectRoles) || null, Validators.required),
});
}
removeProjectTeamMemberItem(index: number, item: IProjectMember) {
this.projectTeamMemberFormArray = this.createProjectForm.get('projectTeamMembers') as FormArray;
this.projectTeamMemberFormArray.removeAt(index);
this.projectTeamMembers.forEach((c: IProjectMember) => {
if (c.id === item.id) c.deleted = true;
});
}
selectEmployee(employee: IEmployee): void {
this.createProjectForm.get('employeeId').setValue(employee.id);
}
employeeTypeaheadDisplayFn(employee: IEmployee): string {
if (employee) {
return `${employee.lastName} ${employee.firstName}`;
}
return '';
}
}
create-project.html
<form #f="ngForm" (ngSubmit)="submit()" novalidate [formGroup]="createProjectForm">
<section>
<div formArrayName="projectTeamMembers" class="single-item-container"
*ngFor="let t of createProjectForm.get('projectTeamMembers').controls; let j = index">
<ng-container [formGroupName]="j">
<div class="spinner" *ngIf="showLoader">
<mat-progress-spinner [color]="'primary'" diameter="100" mode="indeterminate" value="50">
</mat-progress-spinner>
</div>
<div [formGroupName]="j" *ngIf="!showLoader" fxLayout="row" fxLayoutGap="2%">
<!-- employee -->
<mat-form-field fxFlex="100%">
<input matInput formControlName='firstName' placeholder="Start typing employee first or last name."
[matAutocomplete]="auto">
<mat-error *ngIf="t.get('firstName').errors?.required">
{{ 'FIELD_REQUIRED_MESSAGE' | translate }}
</mat-error>
</mat-form-field>
<mat-autocomplete #auto="matAutocomplete" [displayWith]="employeeTypeaheadDisplayFn" (optionSelected)="selectEmployee($event.option.value.id)">
<mat-option *ngFor="let employee of filteredEmployees[j] | async" [value]="employee">
{{ employee.firstName }} {{ employee.lastName }}
</mat-option>
</mat-autocomplete>
<div class="input-bottom">
<button mat-raised-button color="warn" (click)="removeProjectTeamMemberItem(j, t.value)">
Delete
</button>
</div>
</div>
</ng-container>
</div>
<div class="form-footer">
<div class="items-buttons">
<button mat-raised-button color="primary" type="button"
(click)="addProjectTeamMember()">{{'COMPONENTS.PROJECT.ADD_NEW_TEAM_MEMBER' | translate}}</button>
</div>
</div>
</section>
</form>
project-management.service.ts
export interface IEmployee {
id: number;
firstName: string;
lastName: string;
}
filterEmployees(searchTerm: string): Observable<IEmployee[]> {
const reqUrl = `${environment.mPortalWebApi}employee-profiles/search?searchTerm=${searchTerm}`;
return this.http.get(reqUrl).pipe(
map((response: IEmployee[]) => response),
catchError((error) => _throw(error)),
);
}
I would appreciate it if someone would look at the code and see what I missed. Thanks.
EDIT
After your suggestions @polyglot some errors disappeared just there issue with async pipe and ngFor for this array like in picture below and there is error manageNameControl for this.filteredEmployees[index].
Type 'Observable<Observable<IEmployee[]>>' is not assignable to type 'Observable'.Type 'Observable<IEmployee[]>' is missing the following properties from type 'IEmployee': id, firstName,
RESOLVED
I've fixed issue filteredEmyployee needs to be
filteredEmployees: IEmployee[] and the manageNameControl method looks like
manageNameControl(index: number) {
var arrayControl = this.createProjectForm.get('projectTeamMembers') as FormArray;
arrayControl.at(index).get('employeeId').valueChanges
.pipe(
debounceTime(300),
switchMap((value) => this.projectManagementService.filterEmployees(value)),
)
.subscribe((employees: IEmployee[]) => (this.filteredEmployees = employees));
}
and removed aync pipes with from html form
<mat-form-field fxFlex="100%">
<input matInput formControlName='employeeId' name='employeeId' placeholder="Start typing employee first or last name."
[matAutocomplete]="auto">
<mat-error *ngIf="t.get('employeeId').errors?.required">
{{ 'FIELD_REQUIRED_MESSAGE' | translate }}
</mat-error>
</mat-form-field>
<mat-autocomplete #auto="matAutocomplete" [displayWith]="employeeTypeaheadDisplayFn(filteredEmployees)">
<mat-option *ngFor="let employee of filteredEmployees" [value]="employee.id">
{{ employee.firstName }} {{ employee.lastName }}
</mat-option>
</mat-autocomplete>
这篇关于角垫自动完成功能无法在FormArray中工作吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!