No provider for XXX in app.js

Hello there,

I’m having troubles to use a custom provider AuthService (which uses another custom provider Api) in app.js
Console logs that odious error “no provider for Api!

I’ve tried to declare _auth with @ViewChild decorator, as the “sidemenu” template does ( @ViewChild(AuthService) _auth: AuthService ) but then i get this error “TypeError: Cannot read property ‘authenticated’ of undefined” (note that authenticated is a AuthService function) in MyApp’s constructor.

I’m sure it’s a silly noob mistake…

Here’s is the code…

    //APP.TS

    import { Component, ViewChild } from '@angular/core';
    import { App, ionicBootstrap, Platform, Nav, Modal, Menu } from 'ionic-angular';
    import { StatusBar } from 'ionic-native';
    import {provide} from '@angular/core';
    import {Http} from '@angular/http'
    import {AuthHttp, AuthConfig} from 'angular2-jwt';
    import {Type} from '@angular/core';

    import {AuthService} from './providers/auth-serv/auth-serv';

    import { Page1 } from './pages/page1/page1';
    import { DiscoverPage } from './pages/discover/discover';
    import { LoginPage } from './pages/login/login';



    @Component({
        templateUrl: 'build/app.html',
        providers: [
            AuthService,

            provide(AuthHttp, {
                useFactory: (http) => {
                    return new AuthHttp(new AuthConfig(), http);
                },
                deps: [Http]
            })
        ]
    })

    class MyApp {

        @ViewChild(Nav) nav: Nav;
        @ViewChild(Menu) menu: Menu;



        rootPage: any = DiscoverPage;
        isLoggined: Boolean = false;
        pages: Array<{ title: string, component: any }>

        constructor(private platform: Platform, private _auth: AuthService) {
            this.initializeApp();

            this.isLoggined = this._auth.authenticated();

            this.pages = [
                { title: 'Page uno', component: Page1 },
                { title: 'Discover', component: DiscoverPage }
            ];

        }

        initializeApp() {
            this.platform.ready().then(() => {

                StatusBar.styleDefault();
            });
        }

        openLogin() {
            this._auth.showLockLogin();
        }

        openRegister() {
            this._auth.showLockRegister();
        }

        openPage(page) {
            this.nav.setRoot(page.component);
        }
    }

    ionicBootstrap(MyApp);

AUTH-SERV.TS

    // AUTH-SERV.TS
    import { Storage, LocalStorage } from 'ionic-angular';
    import { AuthHttp, JwtHelper, tokenNotExpired } from 'angular2-jwt';
    import { Injectable, NgZone, Component } from '@angular/core';
    import { Observable } from 'rxjs/Rx';

    import { Api } from '../api/api';


    // Avoid name not found warnings
    declare var Auth0Lock: any;

    @Injectable()
    @Component({
        providers:[Api]
    })
    export class AuthService {
        jwtHelper: JwtHelper = new JwtHelper();
        lock = new Auth0Lock('pEjOdUrwqAycw5ctUHXo5rZ71jS4BcW7', 'petify.eu.auth0.com');
        refreshSubscription: any;
        user: Object;
        zoneImpl: NgZone;

        constructor(private authHttp: AuthHttp, zone: NgZone,
                    private _api: Api, private _storage: Storage)  {
            this.zoneImpl = zone;
            // If there is a profile saved in local storage
            this._storage.get('profile').then(profile => {
                this.user = JSON.parse(profile);
            }).catch(error => {
                console.log(error);
            });
        }


        public authenticated() {
            // Check if there's an unexpired JWT
            return tokenNotExpired();
        }


        public showLock() {
            // Show the Auth0 Lock widget
            this.lock.show({
                authParams: {
                    scope: 'openid offline_access',
                    device: 'Mobile device'
                },
                connections: ['facebook', 'google-oauth2']
            },
            (err, profile, token, accessToken, state, refreshToken) => {
                if (err) {
                    alert(err);
                }
            

                var user = this.auth02Petify(profile);

             
            });
        }
        public showLockLogin() {
            // Show the Auth0 Lock widget
            this.lock.showSignin({
                authParams: {
                    scope: 'openid offline_access',
                    device: 'Mobile device'
                },
                connections: ['facebook', 'google-oauth2']
            },
            (err, profile, token, accessToken, state, refreshToken) => {
                if (err) {
                    alert(err);
                }
                // If authentication is successful, save the items
                // in local storage
                console.log(profile);
                console.log(state);

                var user = this.auth02Petify(profile);
                console.log(user);

                // this.local.set('profile', JSON.stringify(profile));
                // this.local.set('id_token', token);
                // this.local.set('refresh_token', refreshToken);
                // this.zoneImpl.run(() => this.user = profile);
                // // Schedule a token refresh
                // this.scheduleRefresh();
            });
        }

        public showLockRegister() {
            // Show the Auth0 Lock widget
            this.lock.showSignup({
                authParams: {
                    scope: 'openid offline_access',
                    device: 'Mobile device'
                },
                connections: ['facebook', 'google-oauth2']
            },
            (err, profile, token, accessToken, state, refreshToken) => {
                if (err) {
                    alert(err);
                }
                // If authentication is successful, save the items
                // in local storage

                let user = this.auth02Petify(profile);

                this._api.params = JSON.stringify(user);
                this._api.post('register')
                    .subscribe(
                        data => {
                             console.log(data);
                             this._storage.set('profile', data);

                        },
                        error => { console.log(error); })

                // this.local.set('profile', JSON.stringify(profile));
                // this.local.set('id_token', token);
                // this.local.set('refresh_token', refreshToken);
                // this.zoneImpl.run(() => this.user = profile);
                // // Schedule a token refresh
                // this.scheduleRefresh();
            });
        }


        public logout() {
            this._storage.remove('profile');
            this._storage.remove('id_token');
            this._storage.remove('refresh_token');
            this.zoneImpl.run(() => this.user = null);
            // Unschedule the token refresh
            this.unscheduleRefresh();
        }


        auth02Petify(auth_profile){

            let user = {
                email : "",
                name  : "",
                type : 0
            }

            switch (auth_profile.identities[0].connection)
            {
                case undefined:
                    alert('invalid connection (_utils.auth02Petify)');
                    break;

                case "facebook":
                        user.email = auth_profile.email;
                        user.name  = auth_profile.name;
                        user.type  = 2; //google plus
                        break

                case "google-oauth2":
                    user.email = auth_profile.email;
                    user.name  = auth_profile.name || auth_profile.nick_name;
                    user.type  = 4; //google plus
                    //@TODO: get country, city, etc
                    break;

                default:
                    return;
            }

            return user;
        }
    }

API.TS

    import { Injectable } from '@angular/core';
    import { Http , Headers} from '@angular/http';
    import 'rxjs/add/operator/map';

    @Injectable()
    export class Api {

        private api_host: string;
        data: any;
        method: string;
        params: string;
        headers: Headers;

        constructor(private http: Http) {
            this.data = null;
            this.api_host = "http://localhost/petFinder/api";
            this.method = "GET";
            this.params = null;
            this.headers = null;
            this.headers = new Headers();
            this.headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
        }


        get(api_method:String) {
            return this.http.get(this.api_host+"/"+api_method, {headers: this.headers} )
              .map(res => res.json())
        }


        post(api_method:String) {
            return this.http.post(this.api_host+"/"+api_method, this.params, {headers: this.headers} )
              .map(res => res.json())
        }

}

Have you tried

providers: [
            AuthService,
            {
             provide:AuthHttp, 
             useFactory: (http) => {
                    return new AuthHttp(new AuthConfig(), http);
              },
              deps: [Http]
            }

See https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#factory-providers

thanks itlr, but that didn’t work, still getting that ‘No provider for Api!’ error…
I’m stuck here

anyone can help?? it’s really frustrating

You need to import and add Api as a provider in app.ts.

tnx 4 your answer, but i don’t undertand why i have to add ‘Api’ to app.ts providers, that provider is used in AuthService (but not directly in app.ts), i’m missing something.

After adding Api to app.ts providers another error show up, ‘No provider for Storage’ grrr, well i do the same; add Storage to app.ts providers

@Component({
    templateUrl: 'build/app.html',
    providers: [
        provide(AuthHttp, {
          useFactory: (http) => {
            return new AuthHttp(new AuthConfig(), http);
          },
          deps: [Http]
        }),
        Storage,
        Api,
        AuthService,

    ]
})

resulting in another error: “Uncaught Can’t resolve all parameters for Storage: (?, ?).” i’m googling it right now, some people talk about using forwardRef in da constructor, in my case it should be something like this …

AUTH-SERV.TS

constructor(private authHttp: AuthHttp, zone: NgZone,
                private _api: Api, @Inject(forwardRef(()  => Storage)) private _storage: Storage)  {
        this.zoneImpl = zone;
        // If there is a profile saved in local storage
        this._storage.get('profile').then(profile => {
            this.user = JSON.parse(profile);
        }).catch(error => {
            console.log(error);
        });
    }

but it’s not working…keep getting that “parameters error”

Storage error fixed thanks to this posts