订阅Observable不会触发变更检测

时间:2018-02-23 19:41:43

标签: javascript angular observable angular2-observables angular2-changedetection

我正在使用'angular2-virtual-scroll'来按需实现加载。以前使用由父组件触发的异步管道由observable驱动的项目。现在我想给孩子打电话。调用成功,我得到了我的数据,我需要使用subscribe事件来应用其他逻辑。问题是当我在订阅功能中更新我的数组时检测到的更改似乎不起作用。我已经阅读了其他类似的问题,但我没有找到解决方案的运气。

这是使用服务调用的主要组件。初始请求是从onInit完成的。然后当你向下滚动时调用fetchMore。

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);
    });
  }
}

据我所知,这可能是一个背景问题,但我不确定。任何建议都会很棒。

“EDIT”

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

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();
};

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

2 个答案:

答案 0 :(得分:2)

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

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

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

也许更改(update)来调用方法只是为了确保它正在发出,并且你得到了你期望从中得到的东西。

编辑: 这是一个示例订阅,它更新显示我的页面数据的主要绑定属性:

movies: IMovie[];

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

在这种情况下,更改检测正常。所以很可能还有其他因素导致了你所看到的问题。

请注意,您的模板 需要绑定到该属性才能使更改检测正常工作。在我的示例中,我绑定到movies属性。在您的示例中,您需要绑定到users属性。

答案 1 :(得分:1)

所以变化检测没有开始。我不得不使用&#34; ChangeDetectorRef&#34;功能&#34; markForCheck&#34;让变更检测正常工作。我不知道为什么,所以我肯定有一些研究要做。