【问题标题】:Angular 2 component not updating from observable subscriptionAngular 2 组件未从可观察订阅更新
【发布时间】:2016-09-19 18:02:41
【问题描述】:

使用 Angular 2 和 Meteor,我有一个组件树,它使用服务在组件之间传递数据并执行获取和保存内容。

在服务中,

   constructor() {
    this._contactId = new Subject<string>();
    this.contactid$ = this._contactId.asObservable();

  }
  // Service message commands
  SetContactId(id: string) {
      console.log("SetContactId "+id);
      this._contactId.next(id);
  }

这在组件中用于区分新联系人或编辑现有联系人。

<div style="display:flex">
    Id: {{contactid}}
    <div style="flex:1 order:1" *ngIf="!contactid">
        <contact-new></contact-new>
    </div>
    <div style="flex:1 order:1" *ngIf="contactid">
        <contact-editor ></contact-editor>
    </div>
</div>

这里是组件订阅。

private contactid : string;

constructor (private _ContactService:ContactService) {


    ContactService.contactid$.subscribe(
        id => {
            //this.id = id;
            console.log('ContactEdit subscription '+id);
            this.contactid = id;
            this.updateId(id);
        } );
    }

    updateId(id) {
        console.log('updateid '+id)
        console.log(this.contactid);
    }

contactid设置两种方式,结果不一样。

clickItem(contact) {
        console.log('clickItem');
        console.log(contact._id);
        this._contactService.SetContactId(contact._id);
    }

这是来自具有联系人列表和点击处理程序的组件。它在服务中设置 id,new/edit 组件按预期工作。

第二种方式是在新建联系人组件构造函数中,

this.newContactForm.valueChanges
            .debounceTime(1000)
            .subscribe(newValue => this.readySave())

readySave() {
...
this._ContactService.newContact(q,true);
}

newContact方法如下,调用时组件不会更新contactid。

newContact(data,setid : boolean) {
    let self = this;
    this.call('contacts.add',data,function (error,id) {
        if (!error) {
            console.log(id);
        if (setid) {
             self.SetContactId(id);
          }
          //self.loadRelations(id);
        }
      });
  }

点击处理程序有效,但插入集合和返回的延迟似乎使其他场景无法更新。如果我选择或单击输入,组件会更新。 Console.log 调用显示正在传递并正确设置的 id。

有什么建议吗?

编辑: 我只用相关组件构建了应用程序的骨架。奇怪的是,它在前几条记录有效,然后在插入文档后不更新,在回调中获取 id,然后在组件中分配 contactid 的订阅函数。

另一个编辑:在解决了这个问题之后,我想我找到了问题所在,但没有找到解决方案。

服务是一个 MeteorComponent,Injectable()。该组件带有 Angular2-meteor,它包装了订阅和调用流星方法。具体来说,调用函数似乎返回了一个承诺,一旦函数执行并在服务器上返回一个值,该承诺就会更新该值。

如果从单击处理程序调用 SetContactId,则更新有效,但如果由 MeteorComponent 中的 Meteor 方法“调用”回调函数调用,则更新无效。

现在寻找解决方案。

【问题讨论】:

  • 我不明白问题出在哪里。你能创建一个 Plunker 来演示这个问题吗?
  • contactid 变量不会在模板中被动更新。
  • console.log('ContactEdit subscription '+id);updateId(id) {...} 打印到控制台吗?
  • 是的。在这两种情况下,都会在组件中设置 Id 值。但在从插入回调获取 Id 的一种情况下,模板不会更新。如果我退出输入,则会发生模板更新。
  • 我在您的代码中没有看到“获得”。你能创建一个允许重现问题的 Plunker 吗?

标签: meteor angular angular2-meteor


【解决方案1】:

感谢Hongbo_Miao,我找到了答案。有必要将 SetContactId 调用包装在 NgZone 的 Meteor.call 回调中以使其更新。它按预期工作。

newContact(data,setid : boolean) {
    this.call('contacts.add',data,
        (error,id) => {
            this._ngZone.run(() => {
                console.log(id);
                if (setid) {
                    this.SetContactId(id);
                    console.log('newContact callback');
                }
            });
        });
    }

【讨论】:

  • 虽然 autorun 方法有一个布尔标志,如果要在 NgZone 内运行,由于某种原因,call 没有。我也被这个咬过一次。也许值得一个错误报告?
  • 哈,很高兴我能帮上忙!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-23
  • 2016-06-10
  • 2017-12-04
  • 2018-01-19
相关资源
最近更新 更多