ng2 update template after making a simple meteor.c

2019-07-07 19:45发布

This has been asked before but I cannot find an answer that helps. I want oResult to change its value after the call is made. The answer has to be appropriate to running ng2, meteor and angular-meteor. Thanks!

/// <reference path="../../typings/angular2-meteor.d.ts" />

import {Input, Component, View, NgZone} from 'angular2/core';
import {MeteorComponent} from 'angular2-meteor';

@Component({
  selector: 'testcall',
  template: `
    <button (click)="testCall()">Get TestCall Data</button>
    <code><pre>{{oResult}}</pre></code>
  `
})

export class TestCall extends MeteorComponent {

  oResult:any

  constructor(private _ngZone: NgZone) {
    super();
    this.oResult = JSON.stringify({res: 'start'});
  }

  testCall(): void {
    Meteor.call('testCall', function(error,result) {
      if (error) {
        console.log('failed', error);
      } else {
          console.log('successful call', result);
          this._ngZone.run(() => {
              this.oResult = result
          });
      }
    });
  }
}

Edit

I've shortened the code and tried to explore if 'this' was the problem. Absence of the angular-meteor component makes to difference to execution of the Meteor.call. But ng2 still fails to change template after the call has executed. And I've tried with and without NgZone. Might dump ng2 'cos I sure haven't the brains or time to get stuck on trivial stuff like this!

/// <reference path="../../typings/angular2-meteor.d.ts" />

import {Input, Component, View} from 'angular2/core';

@Component({
  selector: 'testcall',
  template: `
    <button (click)="testCall()">Get TestCall Data</button>
    <code><pre>{{oResult}}</pre></code>
  `
})

export class TestCall {

  oResult:any

  testCall(): void {
    Meteor.call('testCall', (error:any, result:any) => error ? 
    console.log('failed', error) : 
    (this.oResult=result, console.log('successful call', result, this.oResult)));
  }
}

Edit

This clunky bit of code works to a fashion. Could anyone suggest how to make the Meteor.call a callback of the setTimeout?

  testCall(): void {
    var self:any = this
    Meteor.call('testCall', (error:any, result:string) => error ?
      console.log('failed', error) :
      (self.oResult=result, console.log('successful call', self.oResult)));
    setTimeout(()=>{
      this.oResult=self.oResult;
    },2000);
  }

3条回答
可以哭但决不认输i
2楼-- · 2019-07-07 20:00
export class TestCall extends MeteorComponent {

  oResult:any

  constructor(private zone: NgZone) {
    super();
    this.oResult = JSON.stringify({res: 'start'});
  }

  testCall(): void {
    Meteor.call('testCall', function(error,result) {
      if (error) {
        console.log('failed', error);
      } else {
          console.log('successful call', result);
        this.zone.run(() => { // do updates within Angular zones 
          this.oResult = result
        });
      }
    });
  }
}

See also Triggering Angular2 change detection manually

查看更多
再贱就再见
3楼-- · 2019-07-07 20:13

I personally prefer entire async callback logic runs synchronously within the Angular zone.

export class TestComponent {
  oResult: any;

  constructor(private ngZone: NgZone) {
  }

  testCall(): void {
    Meteor.call('testCall', (error, result) => this.ngZone.run(() => {

      if (error)
        console.log('failed', error);
      else {
        console.log('successful call', result);
        this.oResult = result;
      }

    }));
  }
}
查看更多
祖国的老花朵
4楼-- · 2019-07-07 20:20

After 3 weekends (I'm a weekend coder) I found something that worked!

This doesn't seem to need the ng2-meteor package.

/// <reference path="../../typings/angular2-meteor.d.ts" />

import {Component, View, NgZone} from 'angular2/core';

@Component({
  selector: 'testcall',
  template: `
    <button (click)="testCall()">Get TestCall Data</button>
    <div>{{oResult}}</div>
  `,
  inputs: ['oResult']
})


export class TestCall {

  oResult:any

  constructor(private _ngZone: NgZone) {
  }

  testCall(): void {

      var promise = function() {
        return new Promise((resolve, reject) =>
          Meteor.call('testCall', (error:any, result:string) => error ? reject(error) : resolve(result))
        );
      };

      promise()
        .then(
          (result) => {
            this._ngZone.run(()=>{
              this.oResult = result;
              console.log(result);
            })
          }
        )
  }
}
查看更多
登录 后发表回答