2017-10-12 66 views
0

在我之前的一個問題(dynamically create md-card from API response)中,我根據來自API的許多響應動態創建卡片。即使可觀察到更改,視圖也不會更新

這是使API調用服務:

@Injectable() 
export class WebSearchService { 

    private readonly _results$$ = new BehaviorSubject([]); 
    private readonly _isLoading$$ = new BehaviorSubject(false); 

    public readonly results$ = this._results$$.asObservable().shareReplay(); 
    public readonly isLoading$ = this._isLoading$$.asObservable(); 

    public term: string; 
    p: number; // page 

    public config = { 
    itemsPerPage: 10, 
    currentPage: this.p, 
    totalItems: 100 
    }; 

    constructor(private http: Http){ 
    } 

    search(term: string, page?: number){ 

    return this.http.get(`my/api/{term}`).do(response => { 
     this._isLoading$$.next(false); 
     this.config.totalItems = response.json().estimated_total; 
     this.config.currentPage = this.p; 
    }) 
     .map(response => response.json().results as WebResult[]).map(result => { 
     this._results$$.next(result); 
     this.term = term; 
     return result; 
     }) 
    .take(1); 
    } 

    updatePage(page: number){ 
    this.p = page; 
    return this.search(this.term, page); 
    } 

} 

它使用的結果從服務組件:

export class ResultsComponent implements OnInit { 
    private readonly _results$$ = new BehaviorSubject([]); 

    public readonly isLoading$ = this.webService.isLoading$; 
    public results$ = this.webService.results$; 
    p = 1; // 

    constructor(public webService: WebSearchService) { } 

    ngOnInit() { // 
    } 

    changePage(page: number){ 
    console.log('Page: ' + page); 
    this.results$ = this.webService.updatePage(page); 
    } 

和模板:

<ng-template [ngIf]="isLoading$ | async" [ngIfElse]="results"> 
    is loading ... 
</ng-template> 

<ng-template #results> 
    <div class="container-fluid" *ngFor="let result of results | paginate: this.webService.config"> 
    <!-- cards get dynamically created here --> 
    </div> 
</ng-template> 
<pagination-controls *ngIf="(results$ | async)?.length>0" maxSize="6" 
        previousLabel="" 
        nextLabel="" 
        align="center" 
        (pageChange)="changePage($event)" 
        class="my-pagination" 
        screenReaderPaginationLabel="Pagination" 
        screenReaderPageLabel="page" 
        screenReaderCurrentLabel="You are on page" 
        autoHide="true" 
></pagination-controls> 

我有另一個組件在服務中調用search方法。但是,如果在頁面1以外的任何頁面上調用搜索,則視圖不會更新。如果我轉到結果視圖的第3頁,然後執行另一個搜索,則results$可觀察部分會更新,但視圖仍然保留在舊搜索結果中。我必須手動切換到第1頁的分頁才能獲得新的結果。有沒有辦法自動刷新視圖?

我已盡力解釋問題。該項目非常大,所以我無法創建一個plunkr,但願意解釋/提供更多的代碼。

任何幫助表示讚賞。

+0

嘛,說實話.. 。你的代碼有很多問題,我甚至不會開始考慮像NgZone或ChangeDetectorRef這樣複雜的東西 - 在這些問題真的成爲問題之前需要進行大量修正......但是我沒有真的得到你想要做的。例如 - 爲什麼有很多BehaviorSubjects可以轉換爲可觀察對象?僅僅返回http.get()映射的結果是不夠的?你是否試圖實施某種緩存?只是一個提示:你的直接問題是在ResultsComponent.changePage()函數中。 –

+0

你能提供一些建議或改進嗎? – bawse

+0

當然,我可以,但我需要一些開始。我沒有看到你想要做什麼,所以除非你對此有所瞭解,否則我將無法提出任何有意義的建議。你正在描述***你和***做了什麼 - 你創建了與組件B等對話的組件A,而我要求***爲什麼你創建了***他們這樣,而不是另一個。我想了解你想要解決的真實世界的任務。 –

回答

1

successerror您可觀察的函數很可能用完了Angular區域,這意味着當發射新值時,Angulars變化檢測不會運行。當有問題的值更新時,您可以使用ChangeDetectorRef手動運行更改檢測。

constructor(private cdr: ChangeDetectorRef) {} // inject in your constructor 

myObservable.subscribe(value => { 
    this.myValue = value; // update out of scope 
    this.cdr.detectChanges(); // run change detection manually 
}); 

您也可以嘗試手動認購results$觀察到的每一個新值到達時更新實例變量。該實例變量用於ngFor指令。我刪除了一切,從你的代碼不相關,並添加一個簡單的例子來證明我的意思:

你的類:

export class ResultsComponent implements OnInit { 
    private results$ = this.webService.results$; 
    public results = []; 

    constructor(private webService: WebSearchService, private cdr: ChangeDetectorRef) { 
    this.results$.subscribe(result => { 
     this.results = result; 
     this.cdr.detectChanges(); 
    }); 
    } 
} 

而且你的模板:

<div *ngFor="let result of results | paginate: this.webService.config"></div> 

<pagination-controls 
    *ngIf="results.length > 0" 
    maxSize="6" previousLabel="" 
    nextLabel="" 
    align="center" 
    (pageChange)="changePage($event)" 
    class="my-pagination" 
    screenReaderPaginationLabel="Pagination" 
    screenReaderPageLabel="page" 
    screenReaderCurrentLabel="You are on page" 
    autoHide="true"> 
</pagination-controls> 
+0

如果我不觸摸分頁並保留在第一頁上,視圖將刷新。但是,當我導航到不同的頁面時,會出現問題,然後繼續更改搜索項。'results $'仍然會收到這些更改,但它並未反映在視圖中。我嘗試了你的建議,問題依然存在。 – bawse

+0

您是否嘗試過手動訂閱結果$ observable(而不是使用異步管道)並在您的模板中使用ngFor的實例變量,每當結果$收到更新時都會更新? – David

+0

不,我沒有試過。你能用上面提到的代碼來提供一個例子嗎? – bawse

相關問題