Angular 2可观察的输入未更新UI后



我有一个搜索框的子组件。用户在某些输入中键入并按下搜索按钮。这发出了一个"搜索"事件,然后父组件随后调用带有搜索参数的搜索服务,并将结果分配给儿童组件的可观察到的输入属性。在儿童组件输入属性的设置中,我订阅了可观察的可观察到的结果,然后映射结果。我的问题是,在设置结果时,在设置结果时,UI将不会刷新,直到发生鼠标移动或按钮点击之类的事件。我认为我需要使用ngzone致电订阅我的问题是为什么我必须这样做?在我的搜索组件的另一种风味中,父组件负责调用订阅,然后将结果分配给子组件的输入属性,这是根据预期的。真的很感谢这两种方法和解决方案的最佳方法有什么解释。

下面是我的搜索框(儿童)组件。

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
}

以下是父组件代码。如果我在OnSearch中交换评论和未加音的行,我的结果会立即显示。否则,我需要通过移动鼠标,单击或按键来触发另一个Angular UI。非常感谢您的帮助!

import { ChangeDetectorRef, ChangeDetectionStrategy, Component }    from '@angular/core';
import { Observable }                                               from 'rxjs/Observable';
import { SettingsEntityListComponentBase }                          from '../../component-bases';
import { ClientType }                                               from '../../models/ClientType';
import { ClientTypeService }                                        from '../../services/client-type.service'
import {
    ApplicationService, NotificationContext,
    Permission, UserService, WindowType, SearchArgs,
    SearchItem, SearchItemType, SearchTypeValues
}                                                                   from '../../../core';
@Component({
    moduleId: module.id,
    selector: 'client-type-list',
    templateUrl: 'client-type-list.component.html',
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ClientTypeListComponent extends SettingsEntityListComponentBase<ClientType> {
    constructor(
        changeDetector: ChangeDetectorRef,
        appService: ApplicationService,
        clientTypeService: ClientTypeService,
        userService: UserService) {
        super(changeDetector, appService, clientTypeService, userService, Permission.SettingsClientTypes,
            Permission.GlobalClientTypes, WindowType.ClientTypeDetail, NotificationContext.ClientTypeChanged);
    }
    searchText: string = '4455';
    selectedSecurity: SearchItem;
    searchObservable: Observable<SearchItemType[]>;
    searchResults: SearchItemType[];
    onSearch(args: SearchArgs): void {
        this.searchObservable = this.appService.search(args.searchText, SearchTypeValues.Securities);
        //this.appService.search(args.searchText, SearchTypeValues.Securities).subscribe(r => this.resp(r));
    }
    resp(r: any) {
        this.searchResults = r;
        this.changeDetector.markForCheck();
    }
}

通过使用ChangeDetectionStrategy.OnPush,您可以通过@Input@Output属性更改检测。否则,您必须手动通知角度。

尝试将搜索结果从服务结果连接到您使用的@Input属性(ClientTypeListComponent.searchResults ??)。另外,我不确定SearchBoxComponent.searchResults的Getter/Setter如何/是否可以使用更改检测;您可以尝试将其作为普通@Input属性重写。

相关内容

  • 没有找到相关文章

最新更新