即使可观察到更改,视图也不会更新
问题描述:
在我之前的一个问题(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,但愿意解释/提供更多的代码。
任何帮助表示赞赏。
答
success
或error
您可观察的函数很可能用完了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>
嘛,说实话.. 。你的代码有很多问题,我甚至不会开始考虑像NgZone或ChangeDetectorRef这样复杂的东西 - 在这些问题真的成为问题之前需要进行大量修正......但是我没有真的得到你想要做的。例如 - 为什么有很多BehaviorSubjects可以转换为可观察对象?仅仅返回http.get()映射的结果是不够的?你是否试图实施某种缓存?只是一个提示:你的直接问题是在ResultsComponent.changePage()函数中。 –
你能提供一些建议或改进吗? – bawse
当然,我可以,但我需要一些开始。我没有看到你想要做什么,所以除非你对此有所了解,否则我将无法提出任何有意义的建议。你正在描述***你和***做了什么 - 你创建了与组件B等对话的组件A,而我要求***为什么你创建了***他们这样,而不是另一个。我想了解你想要解决的真实世界的任务。 –