Angular 在每个 select 更改事件上加载新的自动完成值
Angular Load new Autocomplete values on each select change event
我的表单中有几个最重要的字段。在第一种形式中,用户应该通过mat-select-搜索来选择公司。之后,通过使用 (selectionChange) 我在第一个字段中使用 selected 值调用 API(这是公司 ID)和来自该公司的 return 用户自动完成收件人字段。如果用户不更改他选择的公司,它会完美运行。但是如果他这样做 (selectionChange) 方法不会重新加载新值的自动完成。有一种情况,用户有另一家公司 selected,而自动完成仍然来自前一家公司。如果先前的输出为空,则事件仅加载新的。
是否有可能改变这种行为?是否可以从 api 调用中删除以前的结果?
我的表格:
<form [formGroup]="orderForm" novalidate (ngSubmit)="createOrder()">
<div class="row">
<div class="col-md-12">
<mat-form-field class="example-full-width" formGroupName='Company'>
<mat-select ngDefaultControl placeholder="Company" #singleSelect formControlName="id" (openedChange)="onSelectionChange($event)" [(value)]="selectedVariable">
<mat-option>
<ngx-mat-select-search [formControl]="companySelectFilter" [searching]="searching" placeholderLabel="Find company..." noEntriesFoundLabel="'no matching companies found'" ></ngx-mat-select-search>
</mat-option>
<mat-option *ngFor="let company of filteredCompanies | async" [value]="company.id">
{{company.company_name| titlecase}} {{company.company_address| titlecase}}
</mat-option>
</mat-select>
<mat-error *ngIf="orderForm.hasError('notSame')">
Recipient has another company! Select again.
</mat-error>
</mat-form-field>
</div>
</div>
<div class="row" matAutocompleteOrigin #origin="matAutocompleteOrigin">
<div class="col-md-6">
<mat-form-field class="example-full-width" formGroupName='recipient' >
<input type="text"
matInput
formControlName="user_name"
placeholder="First Name"
[matAutocomplete]="auto"
[matAutocompleteConnectedTo]="origin">
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="setFormData($event)">
<mat-option *ngFor="let recipient of filteredOptions | async" [value]="recipient">
<div style="display:flex;flex-wrap: nowrap;align-items:center;justify-content:center;margin: auto;">
<span style="flex-grow: 1;flex: 1 1 33%;"> {{recipient.user_name.toString() | titlecase}} {{recipient.user_surname.toString() | titlecase}} {{recipient.company.company_name.toString() | titlecase}}
</span>
</div>
</mat-option>
</mat-autocomplete>
</mat-form-field>
</div>
<div class="col-md-6" >
<mat-form-field class="example-full-width" formGroupName='recipient'>
<input matInput formControlName="user_surname" placeholder="Last Name"[matAutocomplete]="auto"
[matAutocompleteConnectedTo]="origin" >
<mat-error *ngIf="orderForm.get('recipient.user_surname').hasError('required')">
Last Name is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
</div>
<div class="col-md-6" >
<mat-form-field class="example-full-width" formGroupName='recipient'>
<input matInput placeholder="Mobile Phone" type="text" formControlName="user_telephone" >
</mat-form-field>
</div>
OnSelected 更改方法:
onSelectionChange(opened: boolean) {
console.log(`opened is : ${opened}`);
if (!opened && this.selectedVariable) {
this.orderForm.get('recipient.user_name').reset()
this.orderForm.get('recipient.user_surname').reset()
this.orderForm.get('recipient.user_telephone').reset()
this.filteredOptions = this.orderForm
.get('recipient.user_name')
.valueChanges.pipe(
startWith(""),
debounceTime(400),
distinctUntilChanged(),
switchMap((val) => {
return this.doFilter(this.selectedVariable, val || '');
})
);
}
}
和 doFilter 方法:
doFilter(id: number, val: any): Observable<any[]> {
return this.recipientService.getRecipientsByCompany(id).pipe(
map((response) =>
response.filter((option) => {
return (
option.user_name
.toString()
.toLowerCase()
.indexOf(val.toString().toLowerCase()) === 0 ||
option.user_surname
.toString()
.toLowerCase()
.indexOf(val.toString().toLowerCase()) === 0
);
})
)
);
}
终于,我找到了解决办法。我的错误是我试图在页面加载后从 API 检索数据。现在,我在 NgOnInit 方法中加载所有收件人,并在用户更改公司后过滤数据。
我们放入 ngOnInit 的 LoadRecipients 方法:
this.recipientService
.getRecipientsObs()
.subscribe((recipients) => (this.recipients = recipients));
}
以及新的 OnChange 方法:
selectedVariable: any;
onSelectionChange(opened: boolean) {
console.log(`opened is : ${opened}`);
console.log(this.selectedVariable)
if (!opened && this.selectedVariable) {
this.orderForm.get("recipient.user_name").reset();
this.orderForm.get("recipient.user_surname").reset();
this.orderForm.get("recipient.user_telephone").reset();
const formsInput = merge(
this.orderForm.get('recipient.user_name').valueChanges,
this.orderForm.get('recipient.user_surname').valueChanges
);
formsInput.pipe(
startWith(""),
debounceTime(400),
distinctUntilChanged(),
map((search) => {
if (!this.recipients) {
return [];
} else {
search = search.toLowerCase();
}
return this.recipients.filter(
(recipient) =>
recipient.company.id === this.selectedVariable &&
recipient.user_name.toLowerCase().indexOf(search) > -1 &&
recipient.user_surname.toLowerCase().indexOf(search) > -1
);
}),
delay(500)
)
.subscribe(
(filteredRecipients) => {
this.searching = false;
this.filteredRecipients.next(filteredRecipients);
},
(error) => {
this.searching = false;
}
);
}
}
我的表单中有几个最重要的字段。在第一种形式中,用户应该通过mat-select-搜索来选择公司。之后,通过使用 (selectionChange) 我在第一个字段中使用 selected 值调用 API(这是公司 ID)和来自该公司的 return 用户自动完成收件人字段。如果用户不更改他选择的公司,它会完美运行。但是如果他这样做 (selectionChange) 方法不会重新加载新值的自动完成。有一种情况,用户有另一家公司 selected,而自动完成仍然来自前一家公司。如果先前的输出为空,则事件仅加载新的。 是否有可能改变这种行为?是否可以从 api 调用中删除以前的结果?
我的表格:
<form [formGroup]="orderForm" novalidate (ngSubmit)="createOrder()">
<div class="row">
<div class="col-md-12">
<mat-form-field class="example-full-width" formGroupName='Company'>
<mat-select ngDefaultControl placeholder="Company" #singleSelect formControlName="id" (openedChange)="onSelectionChange($event)" [(value)]="selectedVariable">
<mat-option>
<ngx-mat-select-search [formControl]="companySelectFilter" [searching]="searching" placeholderLabel="Find company..." noEntriesFoundLabel="'no matching companies found'" ></ngx-mat-select-search>
</mat-option>
<mat-option *ngFor="let company of filteredCompanies | async" [value]="company.id">
{{company.company_name| titlecase}} {{company.company_address| titlecase}}
</mat-option>
</mat-select>
<mat-error *ngIf="orderForm.hasError('notSame')">
Recipient has another company! Select again.
</mat-error>
</mat-form-field>
</div>
</div>
<div class="row" matAutocompleteOrigin #origin="matAutocompleteOrigin">
<div class="col-md-6">
<mat-form-field class="example-full-width" formGroupName='recipient' >
<input type="text"
matInput
formControlName="user_name"
placeholder="First Name"
[matAutocomplete]="auto"
[matAutocompleteConnectedTo]="origin">
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="setFormData($event)">
<mat-option *ngFor="let recipient of filteredOptions | async" [value]="recipient">
<div style="display:flex;flex-wrap: nowrap;align-items:center;justify-content:center;margin: auto;">
<span style="flex-grow: 1;flex: 1 1 33%;"> {{recipient.user_name.toString() | titlecase}} {{recipient.user_surname.toString() | titlecase}} {{recipient.company.company_name.toString() | titlecase}}
</span>
</div>
</mat-option>
</mat-autocomplete>
</mat-form-field>
</div>
<div class="col-md-6" >
<mat-form-field class="example-full-width" formGroupName='recipient'>
<input matInput formControlName="user_surname" placeholder="Last Name"[matAutocomplete]="auto"
[matAutocompleteConnectedTo]="origin" >
<mat-error *ngIf="orderForm.get('recipient.user_surname').hasError('required')">
Last Name is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
</div>
<div class="col-md-6" >
<mat-form-field class="example-full-width" formGroupName='recipient'>
<input matInput placeholder="Mobile Phone" type="text" formControlName="user_telephone" >
</mat-form-field>
</div>
OnSelected 更改方法:
onSelectionChange(opened: boolean) {
console.log(`opened is : ${opened}`);
if (!opened && this.selectedVariable) {
this.orderForm.get('recipient.user_name').reset()
this.orderForm.get('recipient.user_surname').reset()
this.orderForm.get('recipient.user_telephone').reset()
this.filteredOptions = this.orderForm
.get('recipient.user_name')
.valueChanges.pipe(
startWith(""),
debounceTime(400),
distinctUntilChanged(),
switchMap((val) => {
return this.doFilter(this.selectedVariable, val || '');
})
);
}
}
和 doFilter 方法:
doFilter(id: number, val: any): Observable<any[]> {
return this.recipientService.getRecipientsByCompany(id).pipe(
map((response) =>
response.filter((option) => {
return (
option.user_name
.toString()
.toLowerCase()
.indexOf(val.toString().toLowerCase()) === 0 ||
option.user_surname
.toString()
.toLowerCase()
.indexOf(val.toString().toLowerCase()) === 0
);
})
)
);
}
终于,我找到了解决办法。我的错误是我试图在页面加载后从 API 检索数据。现在,我在 NgOnInit 方法中加载所有收件人,并在用户更改公司后过滤数据。
我们放入 ngOnInit 的 LoadRecipients 方法:
this.recipientService
.getRecipientsObs()
.subscribe((recipients) => (this.recipients = recipients));
}
以及新的 OnChange 方法:
selectedVariable: any;
onSelectionChange(opened: boolean) {
console.log(`opened is : ${opened}`);
console.log(this.selectedVariable)
if (!opened && this.selectedVariable) {
this.orderForm.get("recipient.user_name").reset();
this.orderForm.get("recipient.user_surname").reset();
this.orderForm.get("recipient.user_telephone").reset();
const formsInput = merge(
this.orderForm.get('recipient.user_name').valueChanges,
this.orderForm.get('recipient.user_surname').valueChanges
);
formsInput.pipe(
startWith(""),
debounceTime(400),
distinctUntilChanged(),
map((search) => {
if (!this.recipients) {
return [];
} else {
search = search.toLowerCase();
}
return this.recipients.filter(
(recipient) =>
recipient.company.id === this.selectedVariable &&
recipient.user_name.toLowerCase().indexOf(search) > -1 &&
recipient.user_surname.toLowerCase().indexOf(search) > -1
);
}),
delay(500)
)
.subscribe(
(filteredRecipients) => {
this.searching = false;
this.filteredRecipients.next(filteredRecipients);
},
(error) => {
this.searching = false;
}
);
}
}