1

On first render of the component everything works fine, but when I press browser back button and click the link that brings to this component again it breaks.

profile-page.module.ts

import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { ProfilePageComponent } from './profile-page.component';
import { FirebaseUIModule } from 'firebaseui-angular';
import { RouterModule, Routes } from '@angular/router';

import { AppHeaderNavbarModule } from '../../../containers/app-header-navbar';
import { ProfileNavigatorModule } from './profile-navigator';

import { MatCardModule } from '@angular/material';
import { InlineEditorModule } from 'ng2-inline-editor';

const routes: Routes = [
  { path: 'profile/:id', component: ProfilePageComponent}
];

@NgModule({
  imports: [
    CommonModule,
    FirebaseUIModule,
    FormsModule,
    MatCardModule,
    InlineEditorModule,
    AppHeaderNavbarModule,
    ProfileNavigatorModule,
    RouterModule.forChild(routes)
  ],
  declarations: [ProfilePageComponent]
})
export class ProfilePageModule {
}

profile-page.component.ts

import { Component, OnInit, Input, ChangeDetectionStrategy } from '@angular/core';    
import { Route, ActivatedRoute } from '@angular/router';
import { UserProfile } from '../../../shared/models/user-profile';
import { AuthService } from '../../../shared/services/auth.service';
import { Observable } from 'rxjs/Observable';

import { environment } from '../../../../environments/environment';
import { constants } from '../../../../constants';

@Component({
  selector: 'profile-page',
  templateUrl: './profile-page.component.html',
  styleUrls: ['./profile-page.component.scss'],
  changeDetection: ChangeDetectionStrategy.Default
})
export class ProfilePageComponent implements OnInit {

  id: string;
  private sub: any;

  ngOnDestroy() {
    this.sub.unsubscribe();
  }

  constructor(
    private route: ActivatedRoute,
    private authService: AuthService
  ) {
  }

  ngOnInit(): void {
      this.sub = this.route.params.subscribe(params => {
        this.id = params['id'];
      });
  }

  isLoggedin() {
    return this.authService.getCurrentUser() != null;
  }
}

Error:

core.js:1350 ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'unsubscribe' of undefined
TypeError: Cannot read property 'unsubscribe' of undefined
    at FirebaseUIComponent.ngOnDestroy (index.js:132)
    at callProviderLifecycles (core.js:12434)
    at callElementProvidersLifecycles (core.js:12399)
    at callLifecycleHooksChildrenFirst (core.js:12383)
    at destroyView (core.js:13727)
    at callViewAction (core.js:13878)
    at execComponentViewsAction (core.js:13790)
    at destroyView (core.js:13726)
    at callWithDebugContext (core.js:14740)
    at Object.debugDestroyView [as destroyView] (core.js:14291)
    at FirebaseUIComponent.ngOnDestroy (index.js:132)
    at callProviderLifecycles (core.js:12434)
    at callElementProvidersLifecycles (core.js:12399)
    at callLifecycleHooksChildrenFirst (core.js:12383)
    at destroyView (core.js:13727)
    at callViewAction (core.js:13878)
    at execComponentViewsAction (core.js:13790)
    at destroyView (core.js:13726)
    at callWithDebugContext (core.js:14740)
    at Object.debugDestroyView [as destroyView] (core.js:14291)
    at resolvePromise (zone.js:824)
    at resolvePromise (zone.js:795)
    at eval (zone.js:873)
    at ZoneDelegate.invokeTask (zone.js:425)
    at Object.onInvokeTask (core.js:4620)
    at ZoneDelegate.invokeTask (zone.js:424)
    at Zone.runTask (zone.js:192)
    at drainMicroTaskQueue (zone.js:602)
    at ZoneTask.invokeTask [as invoke] (zone.js:503)
    at invokeTask (zone.js:1540)

EDIT:

The issue is within parent component, when I navigate away from this component using firebase-ui to some other component, then come back then again click on some other component, I get the above error because

Second time on back button ngOnInit() is not triggered but while trying to navigate away again ngDestroy() is triggered.

import { Component, OnInit } from '@angular/core';
import { AuthService } from '../../../shared/services/auth.service';
import { FirebaseUISignInSuccess } from 'firebaseui-angular';

@Component({
  selector: 'app-home',
  template: `
          <div class="page-content">
            <firebase-ui (signInSuccess)="successCallback($event)"></firebase-ui>
            <router-outlet *ngIf="isLoggedin()"></router-outlet>
          </div>
`,
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
  constructor(private authService: AuthService) {
  }

  ngOnInit(): void {
    console.log('homepage:user::' + this.authService.getCurrentUser());
  }

  successCallback(data: FirebaseUISignInSuccess) {
    console.log('data:' + data);
  }
}
ishandutta2007
  • 16,676
  • 16
  • 93
  • 129

3 Answers3

2

@ishandutta2007 I updated the plugin with a possible fix. Please give it a try firebaseui-angular@2.5.0

Raphael Jenni
  • 318
  • 1
  • 8
0

When subscribing to an observable in a component, you almost always arrange to unsubscribe when the component is destroyed.

There are a few exceptional observables where this is not necessary. The ActivatedRoute observables are among the exceptions.

The ActivatedRoute and its observables are insulated from the Router itself. The Router destroys a routed component when it is no longer needed and the injected ActivatedRoute dies with it.

Feel free to unsubscribe anyway. It is harmless and never a bad practice.

So, Don't Unsubscribe the route.params.subscribe. and this will solve your problem.

For More Details : Please Read

Vivek Doshi
  • 56,649
  • 12
  • 110
  • 122
  • https://github.com/RaphaelJenni/FirebaseUI-Angular/blob/8dbe98d2adc14865aac1a27ac72f908a3245a383/src/firebaseui.component.ts#L54 is part of library, I don't have access to the `subscrption` variable of `firebase-ui` component . – ishandutta2007 Nov 24 '17 at 04:13
  • @günter-zöchbauer can you give your thoughts on this, I checked your similar answer https://stackoverflow.com/a/41678403/865220 – ishandutta2007 Nov 24 '17 at 04:27
  • @ishandutta2007, Please read updated answer, you will get the idea. – Vivek Doshi Nov 24 '17 at 04:36
  • @ishandutta2007, is is possible to create a plnkr or stackbliz for this ? – Vivek Doshi Nov 24 '17 at 04:49
  • Not very accustomed of creating complex plunkr with external dependancies. Facing few issues. Here is the latest atempt http://plnkr.co/edit/5ZMfJ9 – ishandutta2007 Nov 24 '17 at 05:43
-1

Under the conditions that you have described, your issue appears to be that the subscription has not been initialized. You are calling unsubscribe on an undefined sub variable. You should check that sub exists before unsubscribing. For example:

ngOnDestroy() {
  if(this.sub) {    
    this.sub.unsubscribe();
  }
}

It's also worth noting that, per the documentation, it is not necessary to unsubscribe from a subscription on ActivatedRoute. Reference: https://angular.io/guide/router#!#route-parameters

When subscribing to an observable in a component, you almost always arrange to unsubscribe when the component is destroyed.

There are a few exceptional observables where this is not necessary. The ActivatedRoute observables are among the exceptions.

The ActivatedRoute and its observables are insulated from the Router itself. The Router destroys a routed component when it is no longer needed and the injected ActivatedRoute dies with it.

Feel free to unsubscribe anyway. It is harmless and never a bad practice.

Tamadrumma
  • 11
  • 2
  • doesn't help. if you look at the stake trace it has got nothing to do with this subscription, but subscription of FirebaseUIComponent – ishandutta2007 Nov 24 '17 at 03:27