0

In my application, I am facing problems with Angular not binding properties. It also does not call ngOnInit and ngAfterViewInit or execute directives.
Here is partial LoginComponent code:

@Component({
    templateUrl: './login.component.html',
    styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit

//.....

    public test: string = 'some dummy test';

    constructor(
        private cd: ChangeDetectorRef,
        private fb: FormBuilder, private router: Router, private route: ActivatedRoute,
        private authService: AuthService,
        private usersService: UserService,
        private notificationsService: NotificationsService
    )
    {
        this.loginForm = fb.group({
            email: ["", Validators.required],
            password: ["", Validators.required]
        });
        console.info("constructor");
    }

    ngOnInit()
    {
        console.info("ngOnInit");
        this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';        
    }

    ngAfterViewInit()
    {
        this.initGapi();
        console.info("afterviewinit");
    }

Strange is that this works when I open page, or HMR refresh page, but not when I login and logout.
Here is the logout code:

logout(): boolean
{
    this.authService.logout();
}

//authservice.ts
logout()
{    
    localStorage.removeItem("token");
    localStorage.removeItem("refresh_token");
    localStorage.removeItem("profile");

    if (gapi.auth2)
    {
        const instance = gapi.auth2.getAuthInstance();
        if (instance)
        {
            instance.signOut().then(() =>
            {
                this.router.navigate(["login"]);
            });
            return;
        }
    }
    this.router.navigate(["login"]);
}

The differences when I logout and binding not occur are:

  • Button is not styled. This should do kendoButton directive <button class="center" kendoButton type="submit">

  • Binding to test (some dummy test) is missing

  • ngOnInit and ngAfterViewInit is not called.

There is no error in console. I also record screen (it starts with empty page). I have the latest Chrome and Firefox, and same problem is in both browsers.

Does anybody have any idea what is wrong or what else can I try?

screen recording

Makla
  • 9,899
  • 16
  • 72
  • 142

2 Answers2

2

If gapi is running outside Angulars zone, then change detection doesn't get notified to run. You can run code explicitly inside Angulars zone like

constructor(private zone:NgZone) {}

...    

  this.zone.run(() => {
    this.router.navigate(["login"])
  });
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I understand that, I already answer my own question.I find it strange that it doesn't work. The router change route, new page is displayed. Is all that happening outside Angular? – Makla Nov 15 '17 at 08:32
  • 1
    If ` instance.signOut().then(() => ... )` calls `...` outside Angulars zone, everything that is invoked by that runs outside Angulars zone. The router adding the component is outside Angulars zone, therefore no change detection for the new component and its children. Nothing will happen there until change detection is caused by some other means. – Günter Zöchbauer Nov 15 '17 at 08:34
  • You didn't use `zone` in your answer, but this is what should be used here. `ChangeDetectorRef.detectChanges()` only works on the local component and it's children. – Günter Zöchbauer Nov 15 '17 at 08:35
0

Problem is in Google gapi library:

const instance = gapi.auth2.getAuthInstance();
if (instance)
{
    instance.signOut().then(() =>
    {
        this.router.navigate(["login"]);    //This is runned outside Angular's context.
    });
    return;
}

Callback of instance.signOut runs outside Angular's context. Solution is to place navigate outside google.gapi callback:

const instance = gapi.auth2.getAuthInstance();
if (instance)
{
    instance.signOut();
    this.router.navigate(["login"]);
}

Or if you wish to navigate after signOut from Google, use zones. This may help.

Makla
  • 9,899
  • 16
  • 72
  • 142