【问题标题】:Angular 2 view not updating after edit or delete operation executed on api在 api 上执行编辑或删除操作后,Angular 2 视图未更新
【发布时间】:2017-03-15 19:13:44
【问题描述】:

我在显示列表的同一页面上有删除操作。当我执行删除 api 中的数据更改但它没有反映在列表本身中。

我尝试了几件事,其中之一是将已删除的对象从可观察数组中拉出。这不起作用,这不是我想要的,因为它不会反映其他用户是否从列表中添加或删除了“人”。

现在唯一可行的方法是在删除操作完成后触发api调用,但效率不高。

在我看来,正确的方法是触发或刷新订阅,以便它返回 api 获取新数据并将新数据添加或将数据库中不存在的数据删除到可观察数组中。

有没有办法使用 observable 和 RxJs 来做到这一点?

感谢您的帮助

import { Component, OnInit } from '@angular/core';
import {Observable} from 'rxjs/Observable';

import {PeopleService} from '../shared/people.service';
import {People} from '../shared/people.model';
import {ToastService} from '../../../core/toast/toast.service';

@Component({
  selector: 'app-people-list',
  templateUrl: './people-list.component.html',
  styleUrls: ['./people-list.component.css']
})
export class PeopleListComponent implements OnInit {

  peoples: Observable<People[]>;
  constructor(private peopleService: PeopleService,
  private toastService: ToastService) { }

  getPeoples() {
    this.peoples = this.peopleService.getPeoples()
  }

  deletePeople(people: People) {
    this.peopleService.deletePeople(people)
    .subscribe(
      () => {
        this.toastService.activate(' Deleted', 'People', 'danger');
      },
      (err) => console.log('Debug:deletefailed', err)
    );
  }

  ngOnInit() {
    this.getPeoples();
  }

}
<div>
  <h3>People List</h3>
  <hr/>
  <a href="" [routerLink]="['/peoples', 'new']"><button class="btn btn-primary">Add People</button></a>
  <table class="table table-hover">
    <thead class="thead-inverse">
      <tr>
        <th>Id</th>        
        <th>Number of People</th>
        <th>Modify</th>
        <th>Delete</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let people of peoples | async">
        <th>{{people.id}}</th>
        <td>{{people.purchaseCount}}</td>
        <td><button href="#" [routerLink]="['/peopleDetail', people.id]" class="btn btn-sm btn-info">Edit/Detail</button></td>
        <td><button (click) = "deletePeople(people)" class="btn btn-sm btn-danger">Delete</button></td>
      </tr>
    </tbody>
  </table>
</div>

【问题讨论】:

  • `peoples: Observable;`为什么你的组件中有你的 observable?
  • 该服务返回一个可观察对象,如果我在 getPeople 方法中订阅该服务,它也可能只是一个数组而不是可观察对象。

标签: angular rxjs angular2-observables


【解决方案1】:

如果我理解正确,你有一个可观察的服务要删除,然后想通过另一个调用可观察的方法来刷新。这里的问题是一个可观察的是异步的。下面的代码展示了我如何使用 finally 调用刷新数据来完成类似的任务。这反过来又会在第一个异步调用结束时再次调用服务以刷新数据。

delete(item: any) {

    if (confirm("Are you sure you wish to delete Lease ' " + item.title + " '")) {
        this.service.delete(item.leaseid)
            .finally(()=> {this.getLeases();})
            .subscribe(
            res => {
                this.alertService.success("Lease Has been Deleted");
            },
            err => {
                this.handleError(err);
            }
            )

    }
}

【讨论】:

    【解决方案2】:

    如果您想对其进行操作,将人员列表作为流是没有意义的。

    export class PeopleListComponent implements OnInit {
    
      peoples: People[];
      constructor(private peopleService: PeopleService,
      private toastService: ToastService) { }
    
      deletePeople(people: People) {
        this.peopleService.deletePeople(people)
        .subscribe(
          () => {
            this.toastService.activate(' Deleted', 'People', 'danger');
    
           //***Remove people from the peoples list here**//
    
          },
          (err) => console.log('Debug:deletefailed', err)
        );
      }
    
      ngOnInit() {
        this.getPeoples().subscribe(peoples => this.peoples = peoples);
      }
    
    }
    

    ...

    <tr *ngFor="let people of peoples">
    

    并且重新绑定对 peoples-list 的响应在任何方面都不是低效的,因为无论如何视图都必须更新。

    视图不更新的原因仅仅是因为没有任何新值被推送到它

    【讨论】:

    • 这是一种解决方法。角度文档也说了同样的话。但是对于这个特定的实例,我不能这样做,因为我还想获取其他用户可能添加的任何其他对象。
    • 当您订阅流时,您会将所有值推送到该流中,因此这与我在您的代码中看到的没有区别。
    • 为了能够保持该列表同步,您必须再次获取它以保持一致的状态。不仅适用于新值,还适用于新删除的值
    【解决方案3】:

    正如您所说,您始终可以从数据库中获取新数据并更新您的列表。但唯一需要担心的是您将不得不向 API 发出另一个请求,这似乎是不必要的。

    说到点子

    它返回api获取新数据并将新数据添加或删除数据库中不存在的数据到可观察数组。

    为什么不在删除订阅中执行 getPeoples()。

        deletePeople(people: People) {
            this.peopleService.deletePeople(people)
            .subscribe(
              (success) => {
                this.toastService.activate(' Deleted', 'People', 'danger');
                this.getPeoples();
              },
              (err) => console.log('Debug:deletefailed', err)
            );
        }
    

    【讨论】:

      【解决方案4】:

      如果我理解正确,问题不在于更新Component 本身?因为如果是 Nicolas 的回答会有所帮助......虽然我建议不要更改数组的指针作为最佳实践。 而不是:

      peoples: Observable<People[]>;    
      getPeoples() {
          this.peoples = this.peopleService.getPeoples()
      }
      

      做:

      peoples: Array<People> = [];
      getPeoples() {
          this.peoples.length = 0;
          this.peoples.push(...this.peopleService.getPeoples());
      }
      

      如果您正在寻找跨用户的实时更新,您可以创建一个自刷新服务 - 虽然这会增加 API 调用,这将不可避免地给用户带来成本。

      //refresh method:
      private refreshData(): void {
          this.getPeople().subscribe(updated => {
              this.people.next(updated);
              this.subscribeToData();
          });
      }
      //timer method:
      private subscribeToData(): void {
          Observable.timer(5000).first().subscribe(() => this.refreshData());
      }
      

      详细解释看这里:Realtime Refresh

      您还应该看看为此类事物构建的一些框架,例如Fireloop.io

      【讨论】:

        猜你喜欢
        • 2018-07-04
        • 2016-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-10
        • 2016-10-08
        • 2020-09-25
        相关资源
        最近更新 更多