angular - 如何阻止材料下拉自动完成选择在 Angular 8/9 中触发另一个搜索查询?
问题描述
摘要:我有一个按您输入的字段下拉搜索。当我从下拉列表中选择时,它很乐意将字段设置为我在搜索中收到的对象,但不高兴地注册了该更改并将整个对象发送出去进行搜索。
HTML:
<form [formGroup]="myForm" novalidate>
<mat-form-field>
<input matInput
placeholder="SKU / Item Number"
[matAutocomplete]="auto"
formControlName='itemName'>
</mat-form-field>
<mat-autocomplete #auto="matAutocomplete" [displayWith]="parseDropDownSelection">
<mat-option
*ngFor="let row of searchQueryResult"
[value]="row"
(onSelectionChange)="onItemSelection($event)">
<span>{{ row.Name }}</span>
</mat-option>
</mat-autocomplete>
</form>
设置:
import {FieldSearchServiceItem} from './../services/field-search.service';
constructor(
private dialog: MatDialog,
private formBuilder: FormBuilder,
private http: HttpClient,
private appServiceItem: FieldSearchServiceItem,
) {}
ngOnInit()
ngOnInit(){
this.myForm = this.formBuilder.group
({
itemName: '',
});
this.myForm
.get('itemName')
.valueChanges
.pipe(
debounceTime(200),
switchMap(value => this.appServiceItem.search({name: value}, 1))
)
.subscribe(serviceResult => this.searchQueryResult = serviceResult.qResult);
}
服务:
@Injectable()
export class FieldSearchServiceItem
{
constructor(private http: HttpClient) {}
search(filter: {name: string} = {name: ''}, page = 1): Observable<apiQueryResponseForItem>
{
var queryResponse;
return this.http.get<apiQueryResponseForItem>(`example.com/search/item/${filter.name}`)
.pipe(
tap((response: apiQueryResponseForItem) =>
{
response.qResult = response.qResult
.map(unit => new ItemUnit(unit.Id, unit.Name))
return response;
})
);
}
}
类定义:
export class ItemUnit
{
constructor
(
public Id:number,
public Name:string,
) {}
}
export interface apiQueryResponseForItem
{
qSuccess: boolean;
qResult: ItemUnit[];
}
我已经看到其他答案,解决方案是在设置值时使用 emitEvent:false ,如下所示:
this.myForm.get('itemName').patchValue('theDataThatCameBackFromSeach', {emitEvent:false})
这是有道理的……但我觉得解决方案与这种可观察/可注射/材料方法不匹配……主要是因为我没有使用执行 .setValue() 或 .patchValue() 的调用,我猜在 Material 东西的某个地方有一个绑定来处理它。
服务器最终看到这样的调用:
http://example.com/search/item/a (when the letter a is typed)
http://example.com/search/item/[object%20Object] (after clicking the dropdown, JS tries to search 'object' after clumsily falling back to string representation )
我onItemSelection()
目前没有参与,它正在工作,但除了转储到控制台之外什么也没做。.qResult
从我的服务返回的内容searchQueryResult
包含{Id:number,Name:string}
. 我怎样才能让自动完成的字段设置操作仍然完成设置字段的工作,但在这样做时不创建更改事件,同时仍然尊重onItemSelection()
我可以完成其他处理?
解决方案
我前段时间遇到过同样的问题,这是我在系统中用于多个输入的最终解决方案。
步骤是:
- 意识到这里实际上有两个事件。已键入的内容和已选择的值。
- 为这两个事件创建两个 observables 并分别处理它们。
class Component {
ngOnInit() {
/* SEPARATE THE EVENTS */
// If it's an object, it's been selected.
// I also don't allow selecting `null` but it's up to you.
const itemSelected$ = this.myForm.get('itemName').valueChanges.pipe(
filter(val => typeof val === 'object' && val !== null),
);
// If it's a string, it's been typed into the input
const itemTyped$ = this.myForm.get('itemName').valueChanges.pipe(
filter(val => typeof val === 'string'),
);
/* HANDLE ITEM SELECTED */
itemSelected$.subscribe(item => {
// If you want, you can also handle "fake" items here.
// I use this trick to show a placeholder like "Create New Item" in the dropdown
if (item.id === 0 && item.name === 'Create New Item') {
this.createNewItem().subscribe(
newItem => this.myForm.get('itemName').setValue(newItem),
);
return;
}
// I use this in a custom input component (with ControlValueAccessor)
// So this is where I notify the parent
this.onChange(item);
});
/* HANDLE ITEM TYPED */
const searchQueryResult$ = itemTyped$.pipe(
debounce(200),
tap(value => {/* you could handle starting a loading spinner or smth here */}),
switchMap(name => this.appServiceItem.search({name}, 1)),
);
// now you can either use searchQueryResult$ with async pipe:
// this.filteredResults$ = searchQueryResult$;
// or subscribe to it and update a field in your component class:
searchQueryResult$.subscribe(result => this.searchQueryResult = result);
// If you subscribe, don't forget to clean up subscriptions onDestroy
}
}
我冒昧地添加了一些建议和技巧,但您明白了 - 创建两个独立的互斥可观察对象并分别处理它们。
推荐阅读
- powershell - 如何使用 PowerShell 从 Azure 函数查询 Azure 表
- amazon-web-services - 如何在 EC2 上定义 ssh 主机密钥以避免连接时验证失败?
- javascript - Slick - 带有上一张/下一张幻灯片名称的箭头
- python-sphinx - SPHINX - numref 适用于 HTML 但不适用于 LaTex
- spring-boot - PowerMockito 没有在我的代码中运行,这是我的代码
- mysql - 在 GROUP_CONCAT 中搜索过滤数据
- android - 对齐顶部相对布局的底部以使其底部到达固定底部布局的顶部时出现问题
- python - Gitlab CI/CD 错误 机器学习 Python
- javascript - 函数未在 HTMLButtonElement.onclick Angular 4 中定义
- python-3.x - 气流:将 execution_date 作为参数传递给 DataflowPythonOperator