问题
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);
}
回答1:
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;
}
}));
}
}
回答2:
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:
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);
})
}
)
}
}
来源:https://stackoverflow.com/questions/35241724/ng2-update-template-after-making-a-simple-meteor-call