订阅Observable不会触发更改检测 [英] Subscribing to Observable not triggering change detection

查看:74
本文介绍了订阅Observable不会触发更改检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用"angular2-virtual-scroll"来实现按需加载.以前由可观察对象使用父组件触发的异步管道驱动的项目.现在,我正试图从孩子那里打电话给我.调用成功,并且我获取了数据,我需要使用Subscribe事件来应用其他逻辑.问题是,当我在订阅函数中更新阵列时,检测到更改似乎无法正常工作.我读过其他类似的文章,但是我没有运气找到解决方案.

I am using 'angular2-virtual-scroll' to implement load on demand. The items used to be driven by observable's using the async pipe triggered by the parent component. Now i am trying to call my service from the child. The call is successful and i get my data, i need to use the subscribe event to apply other logic. The issue is change detected does not appear to be working when i update my arrays in the subscribe function. I have read other similar issues but i have had no luck finding a solution.

这是使用服务调用的主要组件.初始请求是通过onInit完成的.然后向下滚动时会调用fetchMore.

This is the main component where the service calls are used. The inital request is done from the onInit. And then when you scroll down fetchMore is called.

import { Component, OnInit, Input, OnDestroy  } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import { User } from './../models/user';
import { Role } from './../../roles/models/role';
import { UsersService } from './../services/users.service';
import { ChangeEvent } from 'angular2-virtual-scroll';
import { promise } from 'selenium-webdriver';
import { VirtualScrollComponent } from 'angular2-virtual-scroll';
import { Subscription } from 'rxjs/Subscription';

@Component({
  selector: 'app-users-list',
  template: `
    <div class="status">
        Showing <span class="">{{indices?.start + 1}}</span>
        - <span class="">{{indices?.end}}</span>
        of <span class="">{{users?.length}}</span>
        <span>({{scrollItems?.length}} nodes)</span>
    </div>
    <virtual-scroll [childHeight]="75" [items]="users" (update)="scrollItems = $event" (end)="fetchMore($event)">
        <div #container>
            <app-user-info *ngFor="let user of scrollItems" [roles]="roles" [user]="user">
              <li>
                <a [routerLink]="['/users/edit/', user.id]" class="btn btn-action btn-edit">Edit</a>
              </li>
            </app-user-info>
            <div *ngIf="loading" class="loader">Loading...</div>
        </div>
    </virtual-scroll>
  `
})
export class UsersListComponent implements OnInit, OnDestroy {
  users: User[] = [];
  @Input() roles: Role[];
  currentPage: number;
  scrollItems: User[];
  indices: ChangeEvent;
  readonly bufferSize: number = 20;
  loading: boolean;
  userServiceSub: Subscription;

  constructor(private usersService: UsersService) {
  }

  ngOnInit() {
    this.reset();
  }

  ngOnDestroy() {
      if(this.userServiceSub) {
          this.userServiceSub.unsubscribe();
      }
  }

  reset() {
    this.loading=true;
    this.currentPage = 1;
    this.userServiceSub = this.usersService.getUsers(this.currentPage).subscribe(users => {
        this.users = users;
    });
  }

  fetchMore(event: ChangeEvent) {
    if (event.end !== this.users.length) return;
    this.loading=true;
    this.currentPage += 1;
    this.userServiceSub = this.usersService.getUsers(this.currentPage).subscribe(users => {
        this.users = this.users.concat(users);
    });
  }
}

从我阅读的内容来看,这可能是一个上下文问题,但我不确定.任何建议都会很棒.

From what i have read this could be a context issue but i am not sure. Any suggestions would be great.

编辑"

查看插件组件的源代码,我可以看到更改事件的捕获位置.

Looking at the source code for the plugin component i can see where the change event is captured.

VirtualScrollComponent.prototype.ngOnChanges = function (changes) {
    this.previousStart = undefined;
    this.previousEnd = undefined;
    var items = changes.items || {};
    if (changes.items != undefined && items.previousValue == undefined || (items.previousValue != undefined && items.previousValue.length === 0)) {
        this.startupLoop = true;
    }
    this.refresh();
};

如果我在此事件中放置一个断点,它将在初始加载时触发,因此当我们将数组实例化为[]时.当我单击页面时会触发.但是,在订阅事件中更新数组时,它不会触发.我什至放了一个按钮,将数组设置为空,并更新了视图,因此订阅功能必须中断更改检测.

If i put a breakpoint in this event it fires on the initial load, so when we instantiate the array to []. It fires when i click on the page. But it does not fire when the array is update in the subscribe event. I have even put a button in that sets the array to empty, and that updates the view so the subscribe function must be breaking the change detection.

推荐答案

因此,当您说更改检测似乎不起作用时,我假设您是指以下内容:*ngFor="let user of scrollItems"?

So when you say the change detection does not appear to be working, I assume you are referring to this: *ngFor="let user of scrollItems"?

我没有使用过该特定组件,也没有任何正在运行的代码可以使用...,但我将首先仔细研究一下:

I have not used that particular component nor do I have any running code to work with ... but I'd start by taking a closer look at this:

<virtual-scroll [childHeight]="75" 
                [items]="currentBuffer" 
                (update)="scrollItems = $event" 
                (end)="fetchMore($event)">

也许可以更改(update)来调用方法,只是为了确保它正在发出并确保您从该方法中得到了预期的结果.

Maybe change the (update) to call a method just to ensure it is emitting and that you are getting what you expect back from it.

以下是一个示例订阅,该订阅更新了显示我的页面数据的主绑定属性:

Here is an example subscription that updates the primary bound property showing the data for my page:

movies: IMovie[];

getMovies(): void {
    this.movieService.getMovies().subscribe(
        (movies: IMovie[]) => {
            this.movies = movies;
            this.performFilter(null);
        },
        (error: any) => this.errorMessage = <any>error
    );
}

在这种情况下,更改检测可以正常工作.因此,最有可能是其他原因导致了您所看到的问题.

The change detection works fine in this case. So there is most likely something else going on causing the issue you are seeing.

请注意,您的模板确实需要绑定到属性,才能使更改检测生效.在我的示例中,我绑定到movies属性.在您的示例中,您需要绑定到users属性.

Note that your template does need to bind to the property for the change detection to work. In my example, I'm binding to the movies property. In your example, you'd need to bind to the users property.

这篇关于订阅Observable不会触发更改检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆