NullInjectorError: No provider for AddItemPage! -- Ionic 3 - ionic-framework

Error:
Error: Uncaught (in promise): Error: StaticInjectorError[AddItemPage]:
StaticInjectorError[AddItemPage]:
NullInjectorError: No provider for AddItemPage! Error: StaticInjectorError[AddItemPage]: StaticInjectorError[AddItemPage]:
NullInjectorError: No provider for AddItemPage!
at _NullInjector.get (http://localhost:8100/build/vendor.js:1276:19)
at resolveToken (http://localhost:8100/build/vendor.js:1564:24)
at tryResolveToken (http://localhost:8100/build/vendor.js:1506:16)
at StaticInjector.get (http://localhost:8100/build/vendor.js:1377:20)
at resolveToken (http://localhost:8100/build/vendor.js:1564:24)
at tryResolveToken (http://localhost:8100/build/vendor.js:1506:16)
at StaticInjector.get (http://localhost:8100/build/vendor.js:1377:20)
at resolveNgModuleDep (http://localhost:8100/build/vendor.js:10938:25)
at NgModuleRef_.get (http://localhost:8100/build/vendor.js:12159:16)
at resolveNgModuleDep (http://localhost:8100/build/vendor.js:10938:25)
at c (http://localhost:8100/build/polyfills.js:3:19752)
at Object.reject (http://localhost:8100/build/polyfills.js:3:19174)
at NavControllerBase._fireError (http://localhost:8100/build/vendor.js:48310:16)
at NavControllerBase._failed (http://localhost:8100/build/vendor.js:48303:14)
at http://localhost:8100/build/vendor.js:48350:59
at t.invoke (http://localhost:8100/build/polyfills.js:3:14976)
at Object.onInvoke (http://localhost:8100/build/vendor.js:4982:33)
at t.invoke (http://localhost:8100/build/polyfills.js:3:14916)
at r.run (http://localhost:8100/build/polyfills.js:3:10143)
at http://localhost:8100/build/polyfills.js:3:20242
When I write in HomePage:
import { AddItemPage } from './../add-item/add-item';
...
constructor(... ,private addItemPage: AddItemPage){...}
...
editItems(item){
this.addItemPage.editItem(item);
}
So I want to call a methode from AddItemPage in HomePage.
Any Solutions?

Add import to app.module.ts
...
import { AddItemPage } from '../add-item/add-item';
#NgModule({
declarations: [
MyApp,
HomePage,
AddItemPage
],
...

You're calling AddItemPage like a provider. So if AddItemPage is a page, you need to import it into app.module.ts declaration array.
Then, you want to call a method from AddItemPage in HomePage. To get access to a component and its methods, you can use the #ViewChild decorator.
export class AddItemPage {
constructor() {}
doSomething() {
//send data
}
}
import { Component, ViewChild } from '#angular/core';
import { AddItemPage } from '../add-item';
export class HomePage {
// ViewChild takes a class type or a reference name string.
// Here we are using the type
#ViewChild(AddItemPage) addItemPage: AddItemPage
constructor() { }
update() {
this.addItemPage.doSomething();
}
}
I do not know what the goal is, but I think you can do it differently.
Hope I help!

Related

I'm having the following error with my ionic application when working with the BarcodeScanner

I am developing an application to read codes that I am using the BarcodeScanner but when I execute the application on my device I get the following error
**
**Error running it on my iphone 6 using ionic DevApp Error Runtime Error Object(_WEBPACK_IMPORTED_MODULE_1_ionic_native_core_["cordova"])is not a function. (In 'Object(_WEBPACK_IMPORTED_MODULE_1_ionic_native_core_["cordova"])(this, "scan", {"callbackOrder":"reverse"}, arguments)', 'Object(_WEBPACK_IMPORTED_MODULE_1_ionic_native_core_["cordova"])'is an instance of Object)
Error that is displayed when executing it in ionic serve, ERROR TypeError: Object(...) is not a function at BarcodeScanner.scan (index.js:31) at MenuPage.webpackJsonp.101.MenuPage.scanQR (menu.ts:53) at Object.eval [as handleEvent] (MenuPage.html:17) at handleEvent (core.js:13589) at callWithDebugContext (core.js:15098) at Object.debugHandleEvent [as handleEvent] (core.js:14685) at dispatchEvent (core.js:10004) at core.js:10629 at HTMLButtonElement. (platform-browser.js:2628) at t.invokeTask (polyfills.js:3) **
at the beginning I had the error that my app-module.ts did not
recognize me the BarcodeScanner because when calling it in providers
me, TS2322: Type 'BarcodeScannerOriginal' is not assignable to type
'Provider'. Type 'BarcodeScannerOriginal' is not assignable to type
'FactoryProvider'. Property 'provide' is missing in type
'BarcodeScannerOriginal'
**
Menu.html
<ion-header class="toolbar">
<ion-navbar>
<ion-title>Scan</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding class="Scan">
<div class="row">
<div class="col">
<h2>Scan your QR Code Here</h2>
</div>
<div class="col">
<h3>{{eventTitle}}</h3>
</div>
</div>
<button ion-button block color="secondary" class="Scan-button" (click)="scanQR()" [disabled]="loading">{{buttonText}}</button>
</ion-content>
Menu.ts
import { Component } from '#angular/core';
import {Platform} from "ionic-angular";
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { SplashScreen } from '#ionic-native/splash-screen';
import { StatusBar } from '#ionic-native/status-bar';
import { ToastController } from 'ionic-angular';
import { BarcodeScanner, BarcodeScannerOptions } from '#ionic-native/barcode-scanner/ngx';
/**
* Generated class for the MenuPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
#IonicPage()
#Component({
selector: 'page-menu',
templateUrl: 'menu.html',
})
export class MenuPage {
public scannedText: string;
public buttonText: string;
public loading: boolean;
private eventId: number;
public eventTitle: string;
num: string;
// #ts-ignore
constructor(private _nav: NavController,
private _navParams: NavParams,
private _barcodeScanner: BarcodeScanner) {
}
ionViewDidLoad() {
this.eventId = this._navParams.get('eventId');
this.eventTitle = this._navParams.get('eventTitle');
this.buttonText = "Scan";
this.loading = false;
}
public scanQR() {
this.buttonText = "Loading..";
this.loading = true;
this._barcodeScanner.scan().then((barcodeData) => {
if (barcodeData.cancelled) {
console.log("User cancelled the action!");
this.buttonText = "Scan";
this.loading = false;
return false;
}
console.log("Scanned successfully!");
console.log(barcodeData);
this.goToResult(barcodeData);
}, (err) => {
console.log(err);
});
}
private goToResult(barcodeData) {
this._nav.push(ScanResultPage, {
scannedText: barcodeData.text
});
}
}
app-module.ts
import { BrowserModule } from '#angular/platform-browser';
import { ErrorHandler, NgModule } from '#angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '#ionic-native/splash-screen';
import { StatusBar } from '#ionic-native/status-bar';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import {MenuPage} from "../pages/menu/menu";
import { BarcodeScanner } from '#ionic-native/barcode-scanner/ngx';
import { HttpClientModule } from '#angular/common/http';
import { FormsModule } from '#angular/forms';
import {HttpModule} from "#angular/http";
// #ts-ignore
#NgModule({
declarations: [
MyApp,
HomePage,
MenuPage
],
imports: [
BrowserModule, HttpClientModule,
IonicModule.forRoot(MyApp),
HttpModule
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage,
MenuPage
],
providers: [
StatusBar,
SplashScreen,
BarcodeScanner,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {}
enter image description here
My guess is you are on Ionic 3 but you are using the native plugin version supported for Ionic 4.
Solution
Uninstall both cordova and ionic native plugin
$ionic cordova plugin remove phonegap-plugin-barcodescanner
$npm uninstall #ionic-native/barcode-scanner
Install version 4.
$ ionic cordova plugin add phonegap-plugin-barcodescanner
$ npm install --save #ionic-native/barcode-scanner#4
And don't append ngx at the end of the import.
import { BarcodeScanner } from '#ionic-native/barcode-scanner';
Note
If you are using Ionic 3, try following the Ionic v3 guide instead of the latest guide
Ionic v3 guide:https://ionicframework.com/docs/v3/native/barcode-scanner/
For complete explanation you can find my other answer here: https://stackoverflow.com/a/54474247/6617276

AngularFire2: you are using the development build of the firebase SDK

So i'm using the official documentation to setup and install angularfire2.
https://github.com/angular/angularfire2/blob/master/docs/install-and-setup.md
This works fine, my data is coming in but when building for production i get this error:
It looks like you're using the development build of the Firebase JS
SDK. When deploying Firebase apps to production, it is advisable to
only import the individual SDK components you intend to use.
For the CDN builds, these are available in the following manner
(replace with the name of a component - i.e. auth, database,
etc):
I tried every suggestion out there but nothing is working.
Any Ideas?
thx,
Root module
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { NoopAnimationsModule } from '#angular/platform-browser/animations';
import { RootComponent } from './rootComponent.component';
import { ROOT_ROUTES } from './root.routes';
import { BrowserModule, Title } from '#angular/platform-browser';
import { AngularFireModule } from '#angular/fire';
import { AngularFirestoreModule } from '#angular/fire/firestore';
import { environment } from '../environments/environment';
#NgModule({
declarations: [RootComponent],
imports: [
AngularFireModule.initializeApp(environment.firebase),
AngularFirestoreModule,
NoopAnimationsModule,
BrowserModule,
RouterModule.forRoot(ROOT_ROUTES)
],
providers: [Title],
bootstrap: [RootComponent]
})
export class RootModule {}
Component
import { Component, OnInit } from '#angular/core';
import { MatTableDataSource } from '#angular/material';
import { AngularFirestore } from '#angular/fire/firestore';
import { Observable } from 'rxjs';
import { ActivatedRoute } from '#angular/router';
import { Seal } from '../seals.types';
import { StudioService } from '../../../service/studio.service';
#Component({
selector: 'seals-component',
templateUrl: './seals.component.html'
})
export class SealsComponent implements OnInit {
constructor(private db:AngularFirestore, private studioService: StudioService) {
this.getData();
}
items: Observable<any[]>;
dataSource = new MatTableDataSource<Seal[]>();;
displayedColumns: string[] = ['description', 'language', 'seal', 'type'];
pID:string = 'flsjezlijlsfj';
ngOnInit() {}
getData() {
this.items = this.db.collection(`sealsDB/TNDorQMQOzoqY6P6Ej0i/seal/${this.pID}/seal/`).valueChanges();
this.items.subscribe(seals => {
this.dataSource.data = seals
})
}
}
I was having the same warning and it took me a while to figure it out that I was using the User interface from firebase/auth, along with Timestamp.fromDate() in other file.
So I added:
import * as firebase from 'firebase/app';
import { User } from 'firebase/auth';
and just
import * as firebase from 'firebase/app';
where I used
firebase.firestore.Timestamp.fromDate()
This got rid of the warning.

How to access provider members within a component in Ionic 4

I have a provider having a method getWeather() and I want to call it from home component. When I am trying to call getWeather() from home component I am getting error in console like: ERROR TypeError: Cannot read property 'getWeather' of undefined
weather.ts
import { Http } from '#angular/http';
import { Injectable } from '#angular/core';
import "rxjs/add/operator/map";
#Injectable()
export class WeatherProvider {
constructor(public http: Http) {
console.log('Hello WeatherProvider Provider: ');
}
getWeather() {
return this.http.get('https://samples.openweathermap.org/data/2.5/forecast?q=London,us&appid=b6907d289e10d714a6e88b30761fae22').map(res=>res.json());
}
}
home.ts
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { WeatherProvider } from "../../providers/weather/weather";
//import { HttpModule } from "#angular/http";
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
weather:any;
constructor(public navCtrl: NavController, private wp:WeatherProvider) {
}
ionViewWillEnter() {
this.weather.getWeather().subscribe(weather=>{
console.log(weather)
})
}
}
The error is gone after restarting the ionic dev server. I don't know why the ionic is behaving like this.

how to get realtime JSON from endpoint in Ionic App

Followed the content of the url to implement dynamic menu items using JSON file stored under /assets/data. The menu is working fine with stored JSON file. Now I need to dynamically retrieve the JSON of same format in real time from a Salesforce API and display its content.
Can someone please suggest what changes I need to make here? should the json path in getMainMenu() method be replaced with the actual Saleforce API?
Below is the data-service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import 'rxjs/add/operator/map';
/*
Generated class for the DataServiceProvider provider.
See https://angular.io/guide/dependency-injection for more info on providers
and Angular DI.
*/
#Injectable()
export class DataServiceProvider {
constructor(public http: Http) {
console.log('Hello DataServiceProvider Provider');
}
getMainMenu(){
return this.http.get('assets/data/mainmenu.json')
.map((response:Response)=>response.json().Categories);
}
}
and app.component.ts
import { Component, ViewChild } from '#angular/core';
import { Nav, 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 { ListPage } from '../pages/list/list';
import { DataServiceProvider } from '../providers/data-service/data-service'
#Component({
templateUrl: 'app.html'
})
export class MyApp {
#ViewChild(Nav) nav: Nav;
rootPage: any = HomePage;
pages: any[]; //Array<{title: string, component: any}>;
mainmenu: any[];
constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen, public dataService: DataServiceProvider) {
this.initializeApp();
this.dataService.getMainMenu().subscribe((Response)=>{
this.mainmenu = Response;
console.log(this.mainmenu);
});
// used for an example of ngFor and navigation
this.pages = [
{ title: 'Home', component: HomePage },
{ title: 'List', component: ListPage }
];
}
initializeApp() {
this.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.
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
openPage(page) {
// Reset the content nav to have just this page
// we wouldn't want the back button to show in this scenario
this.nav.setRoot(page.component);
}
toggleSection(i) {
this.mainmenu[i].open = !this.mainmenu[i].open;
};
toggleItem(i,j) {
this.mainmenu[i].SubCategories[j].open = !this.mainmenu[i].SubCategories[j].open;
};
}
It looks like you will need to update the url in the getMainMenu method to that of your api. There might be some other changes you will need to make, such as adding authentication headers, but if the data coming from the api is the same as whats stored in the assets folder, your component shouldn't care "where" the data comes from.

ReflectiveInjector throws InvalidProviderError

I am trying to inject 2 services into generic classes using ReflectiveInjector as seen in this SO
The first time I call ReflectiveInjector on DebugService it works completely fine, however if I then replace this with CourseService, I recieve the following InvalidProviderError:
Uncaught InvalidProviderError_nativeError: Error: Invalid provider - only instances of Provider and Type are allowed, got: undefined
This is the generic class where I am trying to inject the services.
Media.ts
////////////////////////////////////////////////////////////////////////////////////////
import { ReflectiveInjector } from '#angular/core';
// other imports
////////////////////////////////////////////////////////////////////////////////////////
import { CourseService , DebugService } from 'app/services';
//other imports
////////////////////////////////////////////////////////////////////////////////////////
export class Media {
private sanitizer: DomSanitizer;
private courseService: CourseService;
private debug: DebugService;
constructor(_audio: File[], _images: File[], _videos: File[] ) {
// works fine
var injector = ReflectiveInjector.resolveAndCreate([DebugService]);
this.debug = injector.get(DebugService);
// throws InvalidProviderError
var injector2 = ReflectiveInjector.resolveAndCreate([CourseService]);
this.courseService = injector2.get(CourseService);
}
The 2 services are as follows:
debug.service.ts
////////////////////////////////////////////////////////////////////////////////////////
import { Injectable } from '#angular/core';
////////////////////////////////////////////////////////////////////////////////////////
import { environment } from '../../environments/environment';
////////////////////////////////////////////////////////////////////////////////////////
#Injectable()
export class DebugService {
constructor() {
/*stuff*/
}
}
course-service.service.ts
////////////////////////////////////////////////////////////////////////////////////////
import { Injectable, EventEmitter, Output } from '#angular/core';
import { Router } from '#angular/router';
import { Title, DomSanitizer, SafeResourceUrl, SafeUrl} from '#angular/platform-browser';
////////////////////////////////////////////////////////////////////////////////////////
import { DebugService } from 'app/services';
////////////////////////////////////////////////////////////////////////////////////////
#Injectable()
export class CourseService {
#Output() preloadData = new EventEmitter<any>();
// Constructor 1 - called on instantiation of class
constructor(
private sanitizer: DomSanitizer,
private router: Router,
private titleService: Title,
private debug: DebugService
) { /*stuff*/ }
These services were successfully being used in the Media class prior, when I was manually passing CourseService and DebugService as params to the Media constructor, however wanted to get away from this as it seemed very 'clunky' compared to this more streamlined approach.
i.e.
export class Media {
/*stuff*/
constructor(_audio: File[], _images: File[], _videos: File[], _courseService: CourseService, _debugService: DebugService ) { /*stuff*/ }
}
Media is currently defined within another class's constructor:
var preloader = new Preloader(
new Media(
// Audio Files
[
new File(0, './app/assets/video/Example1.mp3')
],
// Image Files
[
],
// Video Files
[
new File(0, './app/assets/video/Example1.mp4')
]
)
//...