0

i have a simple cordova app angular 2 test where @Component decorated AppComponent class member variable is updated when button click method starts and later when i land in callback for promise enabled method it calls.

that member variable is referenced in the @component template as per the getting started tutorials.

what i'm finding is that when i debug/test this in ripple emulator [ / chrome ] the first member variable update gets rendered in view template but the 2nd one doesn't. Conversely when i debug/test this in android emulator, windows mobile / uwp emulator and windows x64 / uwp app the first member variable update doesn't get rendered in view template but the 2nd one does.

in the debugger console i am confirming that the member variable updates referenced in template are in fact showing up.

can repro this using https://github.com/myusrn/acu6withng2 | test button processing and it repros with current ng2.0.0-beta.8 in place.

here is excerpt i would think is most relevant from the sources in that repo.

@Component({
    selector: 'my-app',
    //template: '<h1>Welcome page for {{message}}</h1>',
    template: `
    <button id='signin' (click)='onSignInClick()'>sign-in</button>&nbsp;&nbsp;{{signinMessage}}<br >
    <button id='test' (click)='onTestClick()'>test</button>&nbsp;&nbsp;{{testMessage}}`,
    //providers: [<list of dependency injection providers you want to override or set at this component scope>]
})
export class AppComponent {
    //message: string;
    signinMessage = '';
    testMessage = '';

    // onSignInClick() {  // repros whether i define as method
    onSignInClick = () => {  // and when defined as member function
        this.signinMessage = 'starting signin . . .';  /*** problem area ***/
        this.authService.getAccessToken().then(accessToken => {
            this.signinMessage = 'success';  /*** problem area ***/
        });

    // onTestClick() {  // repros whether i define as method
    onTestClick = () => {  // and when defined as member function
        this.testMessage = 'starting test . . .';  /*** problem area ***/

        this.ping().then(result => {
            this.testMessage = 'success';  /*** problem area ***/
        });     
    }

 
does this sound like anything to do with a known issue that can arise that has a known work around?

myusrn
  • 1,050
  • 2
  • 15
  • 29
  • 2
    Can you please add the relevant code to the question. Do you really expect people to investigate tons of unrelated files and directories to find where your application could misbehave? – Günter Zöchbauer Feb 17 '16 at 06:14
  • thanks for guidance, i've added what i expect to be relevant code excerpts to original post. – myusrn Feb 17 '16 at 15:45

1 Answers1

2

For more details see Triggering Angular2 change detection manually

   constructor(private zone:NgZone);

   onSignInClick = () => {  // and when defined as member function
     this.signinMessage = 'starting signin . . .';  /*** problem area ***/
     this.authService.getAccessToken().then(accessToken => {
       zone.run(() => {
         this.signinMessage = 'success';  
       });
     });

   // onTestClick() {  // repros whether i define as method
   onTestClick = () => {  // and when defined as member function
     this.testMessage = 'starting test . . .';  /*** problem area ***/

     this.ping().then(result => {
       zone.run(() => {
         this.testMessage = 'success';  /*** problem area ***/
       });
     });     
   }
Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Hi @Gunter, thanks for the response and proposed solution to this matter. When I tried addressing issue with the this.zone.run() wrapper proposed above my dependency injection attempts for NgZone produced the javascript console output error `Cannot resolve all parameters for 'NgZone'(?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'NgZone' is decorated with Injectable.` . . . was there something special you were doing in provider entry for NgZone that addresses this? – myusrn Mar 07 '16 at 17:17
  • i then turned to the ChangeDetectorRef provider option outlined in article you referenced, e.g. with `constructor( . . . private cdr: ChangeDetectorRef)` and `this.cdr.detectChanges();` calls following each member variable update that wasn't being reflected in view and that worked. Not sure if this is alternative is fine or used only if you can't make NgZone wrapper work. – myusrn Mar 07 '16 at 17:20
  • Here is a full example https://angular.io/docs/ts/latest/api/core/NgZone-class.html. Sure this is one of the variants to make Angular check for changes. – Günter Zöchbauer Mar 07 '16 at 17:20
  • i then turned to the ApplicationRef provider option outlined in article you referenced, e.g. with `constructor( . . . private ar: ApplicationRef)` and `this.ar.tick();` calls following each member variable update that wasn't being reflected in view and that worked. Again not sure if this is alternative is fine or used only if you can't make ChangeDetectorRef.detectChanges() or NgZone.run() wrapper work. – myusrn Mar 07 '16 at 17:25
  • thanks for pointer to docs on NgZone class. It doesn't contain any details in terms of how you declare it in main.ts bootstrap(AppComponent, [ ] or app.component.ts @Component decorator providers list. I tested with the no NgZone provider specified, e.g. `providers: [ApplicationRef, ChangeDetectorRef /*, NgZone */]` and just the `constructor( . . . private zone: NgZone)` reference which transpiled fine and at runtime got rid of the `Cannot resolve all parameters for 'NgZone'` error but at that point . . . – myusrn Mar 07 '16 at 17:33
  • . . . use of `this.zone.run(() => { this.testMessage = 'success'; });` didn't produce the same result that use of `this.applicationReference.tick();` and `this.changeDectectionRef.detectChanges();` did so i'm thinking both of those are usable solutions unless for some reason they are something to use only where i can't make `ngZone.run(() => { . . . })` wrapper work. – myusrn Mar 07 '16 at 17:36
  • 1
    You don't need to add `NgZone` to providers, it's included in the core providers. See the live example in the NgZone docs (link 3 comments above). I also run into a situation where `ApplicationRef.tick()` worked but `NgZone.run()` didn't but I wasn't able to figure out why `NgZone.run()` didn't work in this case. – Günter Zöchbauer Mar 07 '16 at 17:37