firebase.auth().onAuthStateChanged No provider for AngularFire - firebase

I get the error
Uncaught (in promise): Error: No provider for AngularFire!
When I tried to call firebase.auth().onAuthStateChanged.
Don't know why this happens. Please help.
import { Component } from '#angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { HomePage } from '../pages/home/home';
import { Login } from '../pages/login/login';
import firebase from 'firebase';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage:any = Login;
isAuthenticated = false;
constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) {
firebase.initializeApp({
apiKey: "AIzaSyC94rD8wXG0aRLTcG29qVGw8CFfvCK7XVQ",
authDomain: "myfirstfirebaseproject-6da6c.firebaseapp.com",
});
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.isAuthenticated = true;
this.rootPage = HomePage;
} else {
this.isAuthenticated = false;
this.rootPage = Login;
}
});
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
});
}
}

Your config isn't set up properly. You should have this code in your app.module.ts, not in your component.
import {
AngularFireModule,
AuthMethods,
AuthProviders
} from 'angularfire2';
...
#NgModule({
bootstrap: [AppComponent],
declarations: [AppComponent],
imports: [
AngularFireModule.initializeApp({
apiKey: '<some-key>',
authDomain: '<some-project-authdomain>',
databaseURL: '<some-database-URL>',
storageBucket: '<some-storage-bucket>'
}, {
method: AuthMethods.Password,
provider: AuthProviders.Password
}),
BrowserModule,
...
]
})
class AppModule {}
platformBrowserDynamic().bootstrapModule(AppModule);
This is where you should have the above code. If you don't have the provider set, you'll keep getting the error.

Related

No Firebase App '[DEFAULT]' has been created- call Firebase App.initializeApp()

Before implementing authGuard in my project, everything was working fine. But, it seems authguard throwing an error.
I removed the authguard from the page and it was working. but then again added it back gave error.
App.routing.module.ts
{ path: 'login', loadChildren: './Users/login/login.module#LoginPageModule' },
{ path: 'students/:uName', loadChildren: './Academic/Students/students/students.module#StudentsPageModule',canActivate: [AuthGuard],},
{ path: 'registerclass', loadChildren: './Academic/Students/registerclass/registerclass.module#RegisterclassPageModule',canActivate: [AuthGuard], },
{ path: 'schedule', loadChildren: './Academic/Students/schedule/schedule.module#SchedulePageModule',canActivate: [AuthGuard], },
{ path: 'faculties', loadChildren: './Academic/Faculty/faculties/faculties.module#FacultiesPageModule',canActivate: [AuthGuard], },
{ path: 'addclass', loadChildren: './Academic/Faculty/addclass/addclass.module#AddclassPageModule',canActivate: [AuthGuard], },
auth.guard.ts
import { Injectable } from '#angular/core';
import { CanActivate,ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree,Router } from '#angular/router';
import { Observable } from 'rxjs';
import * as firebase from 'firebase/app'
import 'firebase/auth'
#Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private router: Router) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): boolean | Observable<boolean> | Promise<boolean> {
return new Promise((resolve, reject) => {
firebase.auth().onAuthStateChanged((user: firebase.User) => {
if (user) {
resolve(true);
} else {
console.log('User is not logged in');
this.router.navigate(['/login']);
resolve(false);
}
});
});
}
}// close of class Authguard
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { RouteReuseStrategy } from '#angular/router';
import { IonicModule, IonicRouteStrategy } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { AngularFireModule } from '#angular/fire'; //To initialize firebaseconfig
import { AngularFireAuthModule } from '#angular/fire/auth';
import { AngularFirestoreModule } from '#angular/fire/firestore';
var firebaseConfig = {
apiKey: "AIzaSyC7f8sjVR-cSeeee3ZbEErwOQReowwpTL0",
authDomain: "msuproject-74e5a.firebaseapp.com",
databaseURL: "https://msuproject-74e5a.firebaseio.com",
projectId: "msuproject-74e5a",
storageBucket: "msuproject-74e5a.appspot.com",
messagingSenderId: "748587348290",
appId: "1:748587348290:web:e10fe4336779cd2ee158db",
measurementId: "G-GE58MG9QF6"
};
#NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
BrowserModule,
IonicModule.forRoot(),
AppRoutingModule,
AngularFireModule.initializeApp(firebaseConfig),
AngularFireAuthModule,
AngularFirestoreModule
],
providers: [
StatusBar,
SplashScreen,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule {}
home.html
<ion-card style="text-align: center; background-color: rgb(19, 4, 4);">
<nav class="navCard">
<h1 class="h1Card">
<a [routerLink]="['/login']">Login</a> |
<a [routerLink]="['/faculties']">Faculty</a> |
Library |
Info
</h1>
</nav>
</ion-card>
So, when I click on "Faculty", It should take me to Faculty page rather than crashing the page.
First move the firebaseconfig object to another ts file, then inside the auth.guard.ts do the following:
import * as config from './config.ts';
let firebaseInit = firebase.initializeApp(config.firebaseConfig);
The other solution uses the firebase javascript SDK but since you are importing AngularFire you may as well use that.
auth.guard.ts
constructor(private router: Router,
private afAuth: AngularFireAuth,
private ngZone: NgZone) { }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): boolean | Observable<boolean> | Promise<boolean> {
return new Promise((resolve, reject) => {
this.afAuth.auth.onAuthStateChanged((user: firebase.User) => this.ngZone.run(() => {
if (user) {
resolve(true);
} else {
console.log('User is not logged in');
this.router.navigate(['/login']);
resolve(false);
}
});
});
}
Also I recommend moving your firebaseConfig into the environment file so you can have different ones for dev and production.
app.module.ts
import { environment } from '../environments/environment';
...
imports: [
...
AngularFireModule.initializeApp(environment.firebaseConfig),
...

In ionic how to set storage to login information so when restarting the app takes directly to the home page

I am using the ionic framework. How do I set storage to login information so if the app restart the user can go to the home page when filling the login information again and again.
import * as firebase from 'firebase/app';
import { Storage } from '#ionic/storage';
#Injectable({
providedIn: 'root'
})
export class AuthenticationService {
constructor(public storage: Storage) {}
loginUser(value){
firebase.auth().signInWithEmailAndPassword(value.email, value.password)
.then(() => {
console.log('Log In Successful, UID: ' + value.uid + 'Email: ' +
value.email);
this.storage.set('Email', value.email);
this.storage.set('Password', value.password);
})
}
}
Ref. My github Url
authentication.service.ts
import { Injectable } from '#angular/core';
import { Router } from '#angular/router';
import { Storage } from '#ionic/storage';
import { ToastController, Platform } from '#ionic/angular';
import { BehaviorSubject } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class AuthenticationService {
authState = new BehaviorSubject(false);
constructor(
private router: Router,
private storage: Storage,
private platform: Platform,
public toastController: ToastController
) {
this.platform.ready().then(() => {
this.ifLoggedIn();
});
}
ifLoggedIn() {
this.storage.get('USER_INFO').then((response) => {
if (response) {
this.authState.next(true);
}
});
}
login() {
var dummy_response = {
user_id: 'manzoor.alam#thinktac.com',
user_name: 'manzoor'
};
this.storage.set('USER_INFO', dummy_response).then((response) => {
this.router.navigate(['dashboard']);
this.authState.next(true);
});
}
logout() {
this.storage.remove('USER_INFO').then(() => {
this.router.navigate(['login']);
this.authState.next(false);
});
}
isAuthenticated() {
return this.authState.value;
}
}
In auth-guard.service.ts
import { Injectable } from '#angular/core';
import { AuthenticationService } from './authentication.service';
import { CanActivate } from '#angular/router';
#Injectable({
providedIn: 'root'
})
export class AuthGuardService implements CanActivate {
constructor( public authenticationService: AuthenticationService) { }
canActivate(): boolean {
return this.authenticationService.isAuthenticated();
}
}
App.component.ts file
import { Component } from '#angular/core';
import { Platform } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { AuthenticationService } from './services/Authentication.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent {
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar,
private router: Router,
private authenticationService: AuthenticationService
) {
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
this.authenticationService.authState.subscribe(state => {
if (state) {
this.router.navigate(['dashboard']);
} else {
this.router.navigate(['login']);
}
});
});
}
}
In app-routing.module.ts
import { NgModule } from '#angular/core';
import { PreloadAllModules, RouterModule, Routes } from '#angular/router';
import { AuthGuardService } from './services/auth-guard.service';
const routes: Routes = [
// { path: '', redirectTo: 'home', pathMatch: 'full' },
// { path: 'home', loadChildren: './home/home.module#HomePageModule' },
// { path: 'login', loadChildren: './login/login.module#LoginPageModule' },
// { path: 'dashboard', loadChildren: './dashboard/dashboard.module#DashboardPageModule' },
{ path: '', redirectTo: 'login', pathMatch: 'full' },
{ path: 'login', loadChildren: './login/login.module#LoginPageModule' },
{
path: 'dashboard',
loadChildren: './dashboard/dashboard.module#DashboardPageModule',
canActivate: [AuthGuardService]
// Here canActivate is a method inside the AuthGuardService which return boolen type values
}
];
#NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
],
exports: [RouterModule]
})
export class AppRoutingModule { }
Please Ref. My github url more details github Url
Use Router Guard.
A Guard is just an Angular service - or injectable - that controls the behavior of the router in a maintainable way. Let’s generate it with the CLI:
ionic generate guard guards/login
The guard contains a special canActivate method that we are required to implement that must return or resolve to a boolean value. Because Ionic Storage is Promise-based, we can just make it an async function. Its job is to read the loginComplete value from the device storage. If true it allows the route to active, but if false it will block the route and redirect to the login.
// ...omitted
import { Storage } from '#ionic/storage';
#Injectable({
providedIn: 'root'
})
export class LoginGuard implements CanActivate {
constructor(private storage: Storage, private router: Router) {}
async canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Promise<boolean> {
const isComplete = await this.storage.get('loginComplete');
if (!isComplete) {
this.router.navigateByUrl('/login');
}
return isComplete;
}
}
Applying the Guard
app-routing.module
import { Routes, RouterModule } from '#angular/router';
import { LoginGuard } from './guards/login.guard';
const routes: Routes = [
{
path: '',
loadChildren: './tabs/tabs.module#TabsPageModule',
canActivate: [LoginGuard] // <-- apply here
},
{
path: 'login',
loadChildren: './login/login.module#LoginPageModule'
}
];
#NgModule(...)
export class AppRoutingModule {}
Login page
import * as firebase from 'firebase/app';
import { Storage } from '#ionic/storage';
#Injectable({
providedIn: 'root'
})
export class AuthenticationService {
constructor(public storage: Storage) {}
loginUser(value){
firebase.auth().signInWithEmailAndPassword(value.email, value.password)
.then(() => {
console.log('Log In Successful, UID: ' + value.uid + 'Email: ' +
value.email);
this.storage.set('Email', value.email);
this.storage.set('Password', value.password);
this.storage.set('loginComplete', true);
})
}
}
Hope it helps you :)
Ref url: AngularFirebase

Change the RootPage

I am new to Ionic and I have a problem trying to push a rootpage on Ionic 3
On app.component.ts
import { Component } from '#angular/core';
import { LoginPage } from '../pages/login/login';
import { LoggedinPage } from '../pages/loggedin/loggedin';
import firebase from 'firebase';
#Component({
template: `<ion-nav [root]="rootPage"></ion-nav>`
})
export class MyApp {
rootPage: any;
var state = firebase.auth().onAuthStateChanged(function(user) {
if (user) {
this.rootPage = LoginPage;
//console.log(this.rootPage);
//from here i can see that the this.rootpage is defined.
} else {
this.rootPage = LoggedinPage;
}
console.log(this.rootPage);
//the rootpage is not defined outside of the funtion
});
}
What I want to do, id to redirect users that are already loggedin to the LoggedIn Page.
in app.component.ts
rootPage: any; is mistake, can you use rootPage: any = 'targetPage';
if you use menu rootPage: any = 'menuPage'; and chose rootPage in menuPage.ts ;
export class MenuPage {
rootPage = 'targetPage';
Need to change code following manner:
import {Component, ViewChild} from '#angular/core';
import {Nav} from 'ionic-angular';
import { LoginPage } from '../pages/login/login';
import { LoggedinPage } from '../pages/loggedin/loggedin';
import firebase from 'firebase';
#Component({
template: `<ion-nav [root]="rootPage"></ion-nav>`
})
export class MyApp {
rootPage: any;
#ViewChild(Nav) nav: Nav;
var state = firebase.auth().onAuthStateChanged(function(user) {
if (user) {
this.nav.setRoot(LoginPage);
//console.log(this.rootPage);
//from here i can see that the this.rootpage is defined.
} else {
this.nav.setRoot(LoggedinPage);
}
console.log(this.rootPage);
//the rootpage is not defined outside of the funtion
});
}
You should set userdata after login and clear on logout. and while setting rootPage you can check whether userdata does exist or not. And on initializeApp function of app.component.ts
initializeApp() {
this.platform.ready().then(() => {
this.rootPage = localStorage.getItem('userData') ? MyDashboardPage : LoginPage;
});
}

Adding Dragular to Angular2 Application: document is not defined

I am fairly new to Angular2 and I am having issues adding Dragula to my application. When I run the application an error is thrown prior to loading the home page:
Exception: Call to Node module failed with error: Prerendering failed because of error: ReferenceError: document is not defined
The error message mentions Prerending which I suspect is in relation to the project using asp-prerender-module.
I've tried to follow official tutorials from Dragula and forum posts. Below are my app.module and component file snippets (... denotes summarised code):
app.module.ts
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { UniversalModule } from 'angular2-universal';
import { AppComponent } from './components/app/app.component'
...
import { SearchComponent } from './components/search/search.component';
import { BrowserModule } from '#angular/platform-browser';
import { CommonModule } from '#angular/common';
import { FormsModule } from '#angular/forms';
import { Injectable } from '#angular/core';
import { DragulaModule } from 'ng2-dragula';
#NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
...
SearchComponent
],
imports: [
UniversalModule,
BrowserModule,
FormsModule,
DragulaModule,
CommonModule,
RouterModule.forRoot([
{ path: '', redirectTo: 'home', pathMatch: 'full' },
...
{ path: 'search', component: SearchComponent },
{ path: '**', redirectTo: 'home' }
])
]
})
export class AppModule {
}
search.component.ts
import { Component } from '#angular/core';
import { Http } from '#angular/http';
import { SearchService } from '../../services/search.service';
import { DragulaService } from 'ng2-dragula';
#Component({
selector: 'search',
template: require('./search.component.html'),
providers: [SearchService, DragulaService]
})
I suspect I am missing an a step when including Dragula, but I cannot figure out where. I have included both dragula (^3.7.2) and ng2-dragula (^1.3.0) in my package.json file.
your DragulaService initialization is wrong!! check Dragula documentation link
search.component.ts
import { Component } from '#angular/core';
import { Http } from '#angular/http';
import { SearchService } from '../../services/search.service';
import { DragulaService } from 'ng2-dragula';
#Component({
selector: 'search',
template: require('./search.component.html'),
providers: [SearchService]
})
expoert searchcomponent{
constructor(private dragulaService: DragulaService) {
console.log('DragulaService created');
}
}
Now you can play with drag and drop
If you want more control over drag and drop you can add events and options to dragulaService.
constructor(private dragulaService: DragulaService) {
dragulaService.drag.subscribe((value) => {
console.log(`drag: ${value[0]}`);
this.onDrag(value.slice(1));
});
dragulaService.drop.subscribe((value) => {
console.log(`drop: ${value[0]}`);
this.onDrop(value.slice(1));
});
dragulaService.over.subscribe((value) => {
console.log(`over: ${value[0]}`);
this.onOver(value.slice(1));
});
dragulaService.out.subscribe((value) => {
console.log(`out: ${value[0]}`);
this.onOut(value.slice(1));
});
}
private onDrag(args) {
let [e, el] = args;
// do something
}
private onDrop(args) {
let [e, el] = args;
// do something
}
private onOver(args) {
let [e, el, container] = args;
// do something
}
private onOut(args) {
let [e, el, container] = args;
// do something
}

Unable to broadcast messages from http extender class to App Component in Angular 2

project Structure
Error Information
This is the error i am getting , when i broadcast the message from http extender service to the app component.
Loading Interceptor(http extender)
this is my http extender ,i am unable to broadcast the messages to App component from here ,but i am able to broadcast the messages from the child components to App component ,please see the image for the error information and project structure
import { Injectable } from '#angular/core';
import { Http, RequestOptions, RequestOptionsArgs, Response, ConnectionBackend } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { EventsEmitter } from './eventsEmitter';
#Injectable()
export class LoadingInterceptor extends Http {
private currentRequests: number = 0;
public constructor(_backend: ConnectionBackend, _defaultOptions: RequestOptions, private eventsEmitter: EventsEmitter) {
super(_backend, _defaultOptions);
}
public get(url: string, options?: RequestOptionsArgs): Observable<Response> {
this.incrementRequestCount();
var response = super.get(url, options);
response.subscribe(null, error => {
this.decrementRequestCount();
}, () => {
this.decrementRequestCount();
});
return response;
}
private decrementRequestCount() {
if (--this.currentRequests == 0) {
this.eventsEmitter.broadcast('loading-complete');
}
}
private incrementRequestCount() {
if (this.currentRequests++ == 0) {
this.eventsEmitter.broadcast('loading-started');
}
}
}
App Component
I am listening the events broadcasted in the app component to show the loader gif on the screen
import { Component } from '#angular/core';
import { EventsEmitter } from './assets/scripts/services/eventsEmitter';
import { ToasterService } from 'angular2-toaster';
#Component({
selector: 'my-app',
templateUrl:'app/app.component.html'
})
export class AppComponent {
private toasterService: ToasterService;
private message: any;
private active: any;
constructor(toasterService: ToasterService, private eventsEmitter: EventsEmitter) {
this.toasterService = toasterService;
this.eventListners();
}
eventListners() {
this.eventsEmitter.on<string>('loading-complete')
.subscribe(message => {
this.active = false;
});
this.eventsEmitter.on<string>('loading-started')
.subscribe(message => {
this.active = true;
});
}
}
Event Emitter
this is the event emittter i am using to broadcast the events
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
interface EventsEmitterInterface {
key: any;
data?: any;
}
export class EventsEmitter {
private _eventBus: Subject<EventsEmitterInterface>;
constructor() {
this._eventBus = new Subject<EventsEmitterInterface>();
}
broadcast(key: any, data?: any) {
this._eventBus.next({ key, data });
}
on<T>(key: any): Observable<T> {
return this._eventBus.asObservable()
.filter(event => event.key === key)
.map(event => <T>event.data);
}
}
App Module
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { LocationStrategy, HashLocationStrategy } from '#angular/common';
import { HttpModule, JsonpModule, Http, RequestOptions, XHRBackend, RequestOptionsArgs, Response, ConnectionBackend} from '#angular/http';
import { AppRoutingModule } from './app.routes';
import { AppComponent } from './app.component';
import { LoginComponent } from './components/login/login.component';
import { LoadingInterceptor } from './assets/scripts/services/loadingInterceptor';
import { EventsEmitter } from './assets/scripts/services/eventsEmitter';
import { ToasterModule, ToasterService } from 'angular2-toaster';
#NgModule({
imports: [AppRoutingModule, BrowserModule, FormsModule, ReactiveFormsModule, HttpModule, JsonpModule, ToasterModule ],
declarations: [AppComponent, LoginComponent],
bootstrap: [AppComponent],
providers: [EventsEmitter,LoadingInterceptor,
{
provide: Http,
useFactory: (xhrBackend: XHRBackend, requestOptions: RequestOptions, eventsEmitter: EventsEmitter) => new LoadingInterceptor(xhrBackend, requestOptions, eventsEmitter),
deps: [XHRBackend, RequestOptions]
},{ provide: LocationStrategy, useClass: HashLocationStrategy }]
})
export class AppModule { }
I am stuck here for many days, it would be really helpful if you could help me resolve this issue
You forgot to add EventsEmitter dependency within your useFactory provider:
deps: [XHRBackend, RequestOptions]
It shoul be:
deps: [XHRBackend, RequestOptions, EventsEmitter]
That's why your LoadingInterceptor constructor gets undefined for EventsEmitter dependency

Resources