我有一个搜索框的子组件。用户输入某些输入并按下搜索按钮。这会发出一个“搜索”事件,父组件随后会使用搜索参数调用搜索服务,并将结果分配给子组件的Observable输入属性。在子组件输入属性的setter中,我订阅了Observable,然后映射结果。我的问题是,在设置结果之前UI不会刷新,直到发生鼠标移动或按钮点击等事件。我想我需要使用ngZone调用subscribe我的问题是为什么我必须这样做?在我的搜索组件的另一种风格中,父组件负责调用subscribe,然后将结果分配给子组件的输入属性,这可以按预期工作。非常感谢对这两种方法的不同之处以及最佳解决方法的一些解释。
以下是我的搜索框(子)组件。
transform="translate(50 50)"
以下是父组件代码。如果我在onSearch中绕过注释和未注释的行,我的结果会立即显示。否则,我需要通过移动鼠标,单击或按键来触发另一个Angular UI tick。非常感谢您的帮助!
import {
AfterViewInit, ChangeDetectorRef, ChangeDetectionStrategy, Component,
ElementRef, EventEmitter, Input, OnChanges,
Output, SimpleChanges, ViewChild } from '@angular/core';
import { ControlValueAccessor } from '@angular/forms';
import {
ApplicationService, PromptActions, PromptType,
SearchItem, SearchItemType, SearchType, SearchArgs,
UserPromptRequest
} from '../../../core';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import { PanelBarItemModel } from '@progress/kendo-angular-layout';
@Component({
moduleId: module.id,
selector: 'search-box',
templateUrl: 'search-box.component.html',
styleUrls: ['search-box.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SearchBoxComponent implements ControlValueAccessor {
constructor(private cd: ChangeDetectorRef, private applicationService: ApplicationService) { }
@Input() searchText: string;
@Output() search: EventEmitter<SearchArgs> = new EventEmitter();
private _searchObservable: Observable<SearchItemType[]>;
@Input()
set searchObservable(val: Observable<SearchItemType[]>) {
this._searchObservable = val;
if (this._searchObservable) {
this.searchSubscription = this._searchObservable.subscribe(r => this.resp(r));
}
}
private _selectedItem: SearchItem;
@Input()
set selectedItem(val: SearchItem) {
this._selectedItem = val;
this.propagateChange(this._selectedItem);
}
get selectedItem(): SearchItem {
return this._selectedItem;
}
searchResultsModel: PanelBarItemModel[];
private _searchResults: SearchItemType[];
@Input()
set searchResults(val: SearchItemType[]) {
this._searchResults = val;
this.setUpPanelBarModel();
}
get searchResults(): SearchItemType[] {
return this._searchResults;
}
private setUpPanelBarModel() {
this.isSearching = false;
this.cd.markForCheck();
}
onSearch() {
this.isResultsPopupVisible = true;
this.searchResults = undefined;
let searchArgs = new SearchArgs(this.searchText, this.selectedSearchTypeValue);
this.search.emit(searchArgs);
this.isSearching = true;
this.cd.markForCheck();
}
resp(r: any) {
this.searchResults = r;
this.cd.markForCheck();
}
writeValue(obj: any): void {
this.selectedItem = obj;
}
private propagateChange = (_: any) => { };
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void { } // Don't need
}
答案 0 :(得分:0)
使用ChangeDetectionStrategy.OnPush
,您仅限于通过@Input
和@Output
属性更改检测。否则,您必须手动通知Angular有关更改。
尝试将服务中的搜索结果连接到您用来显示结果的@Input
属性(ClientTypeListComponent.searchResults
??)。此外,我不确定更改检测如何与SearchBoxComponent.searchResults
中的getter / setter一起使用;您可以尝试将其重写为普通@Input
属性。