And*_*rs8 8 angular-material angular
摘要:我有一个可以正常使用的字段下拉搜索。当我从下拉列表中选择时,它很高兴地将字段设置为我在搜索中收到的对象,但不幸地注册了该更改并将整个对象发送出去以供搜索。
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>
Run Code Online (Sandbox Code Playgroud)
设置:
import {FieldSearchServiceItem} from './../services/field-search.service';
constructor(
private dialog: MatDialog,
private formBuilder: FormBuilder,
private http: HttpClient,
private appServiceItem: FieldSearchServiceItem,
) {}
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
服务:
@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;
})
);
}
}
Run Code Online (Sandbox Code Playgroud)
类定义:
export class ItemUnit
{
constructor
(
public Id:number,
public Name:string,
) {}
}
export interface apiQueryResponseForItem
{
qSuccess: boolean;
qResult: ItemUnit[];
}
Run Code Online (Sandbox Code Playgroud)
我已经看到其他答案,其中解决方案是在设置值时使用 emitEvent:false ,如下所示:
this.myForm.get('itemName').patchValue('theDataThatCameBackFromSeach', {emitEvent:false})
Run Code Online (Sandbox Code Playgroud)
这是有道理的......但我觉得解决方案与这种可观察/可注射/材料方法不匹配......主要是因为我没有使用执行 .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 )
Run Code Online (Sandbox Code Playgroud)
我onItemSelection()
目前没有参与,它正在工作,但除了转储到控制台之外什么都不做。该.qResult
从我这要回来searchQueryResult
服务包含{Id:number,Name:string}
。我怎样才能让自动完成的字段设置操作仍然执行设置字段的工作,但在执行此操作时不创建更改事件,同时仍然尊重onItemSelection()
以便我可以完成其他处理?
前段时间我遇到了同样的问题,这是我在系统中用于多个输入的最终解决方案。
步骤是:
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
}
}
Run Code Online (Sandbox Code Playgroud)
我冒昧地添加了一些建议和技巧,但你明白了一般的想法 - 创建两个独立的互斥可观察对象并分别处理它们。
归档时间: |
|
查看次数: |
1781 次 |
最近记录: |