2017-10-12 67 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

相关问题