【问题标题】:Angular 2 : View doesn't update when function is called from promiseAngular 2:从promise调用函数时视图不更新
【发布时间】:2018-06-06 15:18:56
【问题描述】:

我的角度非常基本。我有一个显示对象(在服务中)的视图:

<div *ngFor="let group of service.groups">
    {{group.id}} - {{group.name}}
</div>

我的服务的简单版本如下所示:

public pushNewGroup(group) {

    this.groups.push(group);
    console.log('Pushing new group!');

    // this.zone.run(() => {
    //     this.groups.push(group);
    // });

}

public addGroup(group: Group) {
    let component = this;
    this.api.postWrapper('groups', group).then(function (data: Group) {
        component.pushNewGroup(data);
    });
}

如果我创建一个按钮来调用该服务,一切正常并且视图会更新:

<input type="button" (click)="pushGroup()" value="Add group/>

在视图组件中调用服务:

pushGroup() {
    let group = { ... }
    this.service.pushNewGroup(group);
}

但如果我通过对话窗口调用承诺,那么它不会更新视图:

<li (click)="addGroup()" ><a>Add Group</a></li>

组件(简化):

addGroup() {
    let dialogRef = this.dialog.open(AddGroupComponent, {
        data: {
            ...
        },
    });
}

export class AddGroupComponent {

    constructor(private service: service) {}

    addGroup(group: Group) {
        this.service.addGroup(group);
    }
}

我已经尝试过 ngZone 和 ChangeDetectionStrategy.Default。两种解决方案都不适合我。我可以看到对象两次都发生了变化,并且控制台日志也有效。但是视图没有更新。


我的@Componment 没有任何有趣的东西。对于整个班级来说:

@Component({
    templateUrl: './mainComponent.html',
    styleUrls: ['./mainComponent.scss'],
    providers: []
})

对于我的添加组对话框,它是:

@Component({
    selector: 'addGroup',
    templateUrl: './AddGroupComponent.html',
    styleUrls: ['./AddGroupComponent.scss'],
    providers: [ApiService, PermissionsService, Service],
    changeDetection: ChangeDetectionStrategy.Default
})

编辑:很难将整个东西提取到 plunker 中,但我尝试重新创建它并证明承诺的东西有效。我认为问题可能出在 MatDialog 上。它不会更新主视图。我尝试在 plunker 中重新创建整个东西,但我无法在 plunker 中使用有角度的材料。似乎网上所有其他的例子也被打破了:

https://embed.plnkr.co/LTAEwV6bNvoGQAFoky60/

【问题讨论】:

  • 你能展示你的@Component装饰器吗?
  • 请创建一个 JS Fiddle (jsfiddle.net) 以便人们可以快速轻松地测试您的代码。此外,在 Angular 1.x 中,如果在正常的 Angular 管道之外发生了某些事情,您必须告诉视图更新 ($scope.$apply()),尽管我不知道这是否与 2.x 相同。
  • 我尝试在这里创建一个 plunker:embed.plnkr.co/LTAEwV6bNvoGQAFoky60 原来,我认为问题出在角度材质对话框窗口上(关闭后数据不会更新)。但我现在似乎无法让 MatDialog 与 plunker 一起工作。

标签: angular typescript angular-promise angular2-changedetection ngzone


【解决方案1】:

你为什么不使用箭头函数而忘记这个 hack let component = this?也许这可能是问题所在。使用 ES6 特性,遵循 Angular 风格指南。

public addGroup(group: Group) {
  this.api.postWrapper('groups', group).then( (data: Group) => {
     this.pushNewGroup(data);
  });
}

【讨论】:

  • 不幸的是,这并没有改变任何东西。我怀疑它可能是一个不同的对象(当我创建组件时),但这就是为什么我将实际推送提取到一个单独的方法。
【解决方案2】:

Promise 会将变更检测推迟到下一个检测周期。

试试这个:

在构造函数中添加private _cdr: ChangeDetectorRef。(显然是导入ChangeDetectorRef

在 promise 中添加this._cdr.detectChanges()(在末尾)。

【讨论】:

  • 这给了我:错误错误:未捕获(承诺):错误:ViewDestroyedError:尝试使用已破坏的视图:detectChanges 我从这里尝试了一些解决方案,但不幸的是它们都没有工作:@ 987654321@
  • 您的实际组件似乎不知道服务中有更改,因为您触发了对话框组件的更改。您需要通知父组件发生了更改。这可以通过向父组件发出事件来完成。你能在 plunker 或 jsFiddle 中发布简化代码,因为很难获取上下文吗?
  • 我试图在这里创建一个 plunker:embed.plnkr.co/pvBT5jGddQP8IrYHGi79 我使用了一些现有的代码并尝试格式化以像我的那样工作(真的很难提取它)。不幸的是,这个承诺现在不起作用,但如果我们能让它发挥作用,也许我们可以测试它。
  • 将您的承诺部分更改为此,使其在 plunker 上工作:this.http.get("https://randomapi.com/api/6de6abfedb24f889e0b5f675edc50deb?fmt=raw&amp;sole") .subscribe(response =&gt; { response.json(); component.pushGroup(); });
  • 谢谢。我让它工作了。整个承诺的事情都有效。我认为问题可能出在我的角度材质对话框窗口上。关闭它后,它会从 Promise 中获取数据,但视图不会更新。我试图用 MatDialog 创建一个 plunker,但似乎它的所有示例都被 plunker 破坏了(至少目前):embed.plnkr.co/LTAEwV6bNvoGQAFoky60
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-29
  • 2017-08-28
  • 1970-01-01
  • 1970-01-01
  • 2017-06-08
  • 1970-01-01
相关资源
最近更新 更多