shotleybuilder
shotleybuilder

Reputation: 123

ng2 update template after making a simple meteor.call

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

Upvotes: 2

Views: 425

Answers (3)

Mandakh
Mandakh

Reputation: 1213

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

    }));
  }
}

Upvotes: 1

shotleybuilder
shotleybuilder

Reputation: 123

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

Upvotes: 0

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657338

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

Upvotes: 0

Related Questions