Make Ionic2 Controllers global - ionic-framework

I need alertCtrl: AlertController, sanitizer: DomSanitizer, modalCtrl: ModalController, toastCtrl: ToastController on several places in my App. Is there a way to make them global available or do I really have to forward them through all classes, in my case through 4 constructors?

If you declare providers in a module, they will be forwarded to all components under this module. Then, they could be considered as global if you declare them in the app.module.
If what you want is to not import them into each component that need them, the only option I see is to wrap them into a factory provider or a custom one and then import only this new provider :
EDIT : Coding
Global provider example
Test environment :
Cordova CLI: 6.2.0
Ionic Framework Version: 2.0.0-rc.3
Ionic CLI Version: 2.1.8
Ionic App Lib Version: 2.1.4
Ionic App Scripts Version: 0.0.45
ios-deploy version: Not installed
ios-sim version: Not installed
OS: Linux 3.19
Node Version: v6.9.1
Xcode version: Not installed
App
./src/app/app.module.ts :
import { NgModule, ErrorHandler } from '#angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { DefaultModal } from '../modals/default/default.modal';
import {GlobalProvider} from '../providers/global.provider'
#NgModule({
declarations: [
MyApp,
HomePage,
DefaultModal
],
imports: [
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage,
DefaultModal
],
providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}, GlobalProvider]
})
export class AppModule {}
Modal
./src/modals/default/default.modal.html :
<ion-header>
<ion-navbar>
<ion-title>{{nav_params.title}}</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-list-header>
Global controller :
</ion-list-header>
<ion-item *ngFor="let controller of nav_params.global_provider_names">
{{controller}}
</ion-item>
</ion-list>
</ion-content>
./src/modals/default/default.modal.scss :
default_modal {
}
./src/modals/default/default.modal.ts :
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { NavParams } from 'ionic-angular';
#Component({
selector: 'default-modal',
templateUrl: 'default.modal.html'
})
export class DefaultModal
{
nav_params
constructor(
private nav : NavController
, private _nav_params : NavParams
)
{
this.nav_params =
{
title : this._nav_params.get(
"title"
)
, global_provider_names : this._nav_params.get(
"global_provider_names"
)
}
}
}
Home page
./src/pages/home/home.html :
<ion-header>
<ion-navbar>
<ion-title>
Home page
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<button
ion-button
(click)="present_alert()"
>
Present alert
</button>
<button
ion-button
(click)="present_modal()"
>
Present modal
</button>
</ion-content>
./src/pages/home/home.scss :
page-home {
}
./src/pages/home/home.ts :
import { Component } from '#angular/core'
import { DefaultModal } from '../../modals/default/default.modal'
import { GlobalProvider } from '../../providers/global.provider'
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(
private _global_provider : GlobalProvider
)
{
}
present_alert()
{
let alert = this._global_provider.alert_controller.create(
{
title: 'Alert title'
, subTitle: 'Alert subtitle'
, buttons:
[
'Dismiss'
]
}
)
alert.present()
}
present_modal()
{
let modal = this._global_provider.modal_controller.create(
DefaultModal
, {
title : 'Modal title'
, global_provider_names : Object.keys(
this._global_provider
)
}
)
modal.present()
}
}
Global provider
./src/providers/global.provider.ts :
import {Injectable} from '#angular/core'
import {AlertController} from 'ionic-angular'
import {ModalController} from 'ionic-angular'
import {ToastController} from 'ionic-angular'
#Injectable()
export class GlobalProvider
{
constructor(
public alert_controller : AlertController
, public modal_controller : ModalController
, public toast_controller : ToastController
)
{
}
}
Hope this helps!

Related

Ionic 3 : pass provider's variables to ion-input

I have this simple provider:
import { Injectable } from "#angular/core";
#Injectable()
export class DevicesService {
public check_string : any;
constructor(){
this.check_string = "Provider enabled";
}
getStatusString() { return this.check_string; }
}
and I am trying to pass that check_string variable to a ion-input in my home.ts:
<strong><ion-input round id="stringstatus" type="text" [(ngModel)]="stringstatus"></ion-input></strong>
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { DevicesService } from '../../providers/devicefactory/devicefactory';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public stateString : string;
constructor(public navCtrl: NavController, private deviceProvider : DevicesService) {
this.stateString = this.deviceProvider.check_string;
//this.stateString = this.deviceProvider.getStatusString();
}
}
I tried both two ways, direct pass variable and getting return function but once I run app it shows blank page.. what I could have missed?
Thanks a lot to all
Cheers!
Try using deviceProvider.getStatusString(). Without using this in constructor;
constructor(public navCtrl: NavController, private deviceProvider : DevicesService) {
this.stateString = deviceProvider.getStatusString();
}
You can directly set it in your ngModel :
[(ngModel)]="deviceProvider.check_string"
or
[(ngModel)]="deviceProvider.getStatusString()"
Hello Rameez and saperlipopette,
I tried as both of you obtaining this:
devicefactory.ts
import { Injectable } from "#angular/core";
//import { BluetoothLE } from '#ionic-native/bluetooth-le';
#Injectable()
export class DevicesService {
public ble_status : boolean;
public check_string : any;
// public BLE : BluetoothLE
constructor(){
this.ble_status = false;
//this.BLE.initialize();
//this.BLE.isEnabled().then(result => { this.ble_status = result.isEnabled; });
this.check_string = "Provider enabled";
}
getStatus() { return this.ble_status; }
getStatusString() { return this.check_string; }
enableBLE() {
//if (this.ble_status) this.BLE.enable(); else this.BLE.disable();
if (this.ble_status) this.check_string = "Provider enabled"; else this.check_string = "Provider disabled";
}
}
app.module.ts
import { NgModule, ErrorHandler } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { HoergerateApp } from './app.component';
import { AboutPage } from '../pages/about/about';
import { ContactPage } from '../pages/contact/contact';
import { HomePage } from '../pages/home/home';
import { TabsPage } from '../pages/tabs/tabs';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { SettingsPage } from '../pages/settings/settings';
import { DevicesService } from '../providers/devicefactory/devicefactory';
#NgModule({
declarations: [
HoergerateApp,
AboutPage,
SettingsPage,
ContactPage,
HomePage,
TabsPage
],
imports: [
BrowserModule,
IonicModule.forRoot(HoergerateApp)
],
bootstrap: [IonicApp],
entryComponents: [
HoergerateApp,
AboutPage,
SettingsPage,
ContactPage,
HomePage,
TabsPage
],
providers: [
StatusBar,
SplashScreen,
DevicesService,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {
}
home.html
<ion-header>
<ion-navbar>
<ion-title>Home</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h2>Welcome to Ionic!</h2>
<p>
This starter project comes with simple tabs-based layout for apps
that are going to primarily use a Tabbed UI.
</p>
<p>
Take a look at the <code>src/pages/</code> directory to add or change tabs,
update any existing page or create new pages.
</p>
<p>
Check bluetooth status:<br>
<strong><ion-input round id="ble_state" type="text" [(ngModel)]="ble_state"></ion-input></strong>
</p>
</ion-content>
home.ts
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { DevicesService } from '../../providers/devicefactory/devicefactory';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public ble_state : string;
constructor(public navCtrl: NavController, public deviceProvider : DevicesService) {
//this.ble_state = ( this.deviceService.ble_status ? "Bluetooth is enabled" : "BLuetooth is disabled" );
//this.ble_state = deviceProvider.check_string;
this.ble_state = deviceProvider.getStatusString();
}
}
Before I put also directly in [(ngModel)] but it goes for blank page..... I think it's related something about passing variables maybe because if I comment that:
this.ble_state = deviceProvider.getStatusString();
the app appears working...
Maybe it's related about ionic and cordova installation platforms or dependencies even if it didn't reported any errors during compilation?
Thanks

Unexpected directive 'Slides' imported by the module 'AppModule'. Please add a #NgModule annotation

I'm trying to build a very simple app (ionic 3.19): using phone camera to take pictures clicking a button, saving them in an array and then displaying like a carousel through Slides component. But getting an error as the title. The code:
app.module.ts, where import Slide from ionic-angular
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 { Slides } from 'ionic-angular';
import { Camera } from '#ionic-native/camera';
#NgModule({
declarations: [
MyApp,
HomePage
],
imports: [
BrowserModule,
Slides,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage
],
providers: [
StatusBar,
SplashScreen,
Camera,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {}
home.ts, containing the function for taking the pictures
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { Camera, CameraOptions } from '#ionic-native/camera';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public image: string = null;
public base64Image: string[];
public extraOptions : {};
constructor(private camera: Camera) {
this.base64Image = new Array();
this.extraOptions = {
pager: true,
paginationClickable: true,
spaceBetween: 30,
centeredSlides: true,
autoplay: 2000
}
}
takePicture() {
let options: CameraOptions = {
destinationType: this.camera.DestinationType.DATA_URL,
targetWidth: 1000,
targetHeight: 1000,
quality: 100
}
this.camera.getPicture( options )
.then(imageData => {
this.image = 'data:image/jpeg;base64,${imageData}';
this.base64Image.push(imageData);
let iData = this.base64Image.map(o => o).join(', ');
console.log("iData is " + iData);
})
.catch(error =>{
console.error( error );
});
}
}
home.html:
<ion-header>
<ion-navbar>
<ion-title>
Manage your photos!
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<button ion-button block (click)="takePicture()">Photo</button>
<!--<img [src]="image" *ngIf="image" />-->
<div *ngIf="base64Image.length == 0"> <br/><br/> Click on the camera icon to take pictures!</div>
<ion-slides pager autoplay="true" pager="true" [options]="extraOptions" *ngIf="base64Image.length > 0">
<ion-slide *ngFor="let image of base64Image">
<img [src]="image" />
</ion-slide>
</ion-slides>
</ion-content>
Any ideas? Thank you very much!
No need to import Slides in app.module.ts, import them directly in the component:
import { Slides } from 'ionic-angular';
and dont't forget to add Slides as ViewChild in component:
#ViewChild(Slides) slides: Slide
Read more on official docs.

Error: Template parse errors: in Ionic 3

When I run ionic serve i'm getting the following error below. Why I'm I getting the error? Does it have to do with IonicModule.forRoot(MyApp)?
This is my .html component:
<ion-header>
<ion-navbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list inset>
<ion-item *ngFor="let bill of bills">
<h2>{{bill.bill_no}}</h2>
</ion-item>
</ion-list>
</ion-content>
bills.ts
import { Component } from '#angular/core';
import { IonicPage, IonicModule , NavController, NavParams } from 'ionic-angular';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '#angular/common/http';
import { Api } from '../../providers/api/api';
import { BillServiceProvider } from '../../providers/bill-service/bill-service';
/**
* Generated class for the BillsPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
#IonicPage()
#Component({
selector: 'page-bills',
templateUrl: 'bills.html',
})
export class BillsPage {
bills: any;
// constructor(public navCtrl: NavController, public navParams: NavParams) {
// }
constructor(public navCtrl: NavController, public BillServiceProvider: BillServiceProvider ) {
this.getBills();
// .subscribe(data => {
// console.log('my data: ', data);
// },
// ionViewDidLoad() {
// console.log('ionViewDidLoad BillsPage');
}
getBills() {
this.BillServiceProvider.getBills()
.then(data => {
this.bills = data;
console.log(this.bills);
});
}
// openDetails(bill){
// this.navCtrl.push('BillDetailsPage', {bill: bill});
// }
}
app.module.ts
import { BillsPage } from './../pages/bills/bills';
import { HttpClient, HttpClientModule } from '#angular/common/http';
import { ErrorHandler, NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { Camera } from '#ionic-native/camera';
import { SplashScreen } from '#ionic-native/splash-screen';
import { StatusBar } from '#ionic-native/status-bar';
import { IonicStorageModule, Storage } from '#ionic/storage';
import { TranslateLoader, TranslateModule } from '#ngx-translate/core';
import { TranslateHttpLoader } from '#ngx-translate/http-loader';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { Items } from '../mocks/providers/items';
import { Settings, User, Api } from '../providers';
import { MyApp } from './app.component';
import { PaymentServiceProvider } from '../providers/payment-service/payment-service';
import { BillServiceProvider } from '../providers/bill-service/bill-service';
// The translate loader needs to know where to load i18n files
// in Ionic's static asset pipeline.
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
export function provideSettings(storage: Storage) {
/**
* The Settings provider takes a set of default settings for your app.
*
* You can add new settings options at any time. Once the settings are saved,
* these values will not overwrite the saved values (this can be done manually if desired).
*/
return new Settings(storage, {
option1: true,
option2: 'Ionitron J. Framework',
option3: '3',
option4: 'Hello'
});
}
#NgModule({
declarations: [
MyApp,
BillsPage
],
imports: [
BrowserModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [HttpClient]
}
}),
IonicModule.forRoot(MyApp),
IonicStorageModule.forRoot()
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
BillsPage
],
providers: [
Api,
Items,
User,
Camera,
SplashScreen,
StatusBar,
{ provide: Settings, useFactory: provideSettings, deps: [Storage] },
// Keep this to enable Ionic's runtime error handling during development
{ provide: ErrorHandler, useClass: IonicErrorHandler },
PaymentServiceProvider,
BillServiceProvider
]
})
export class AppModule { }

Ionic 2 and Mathjax : Can't bind to 'MathJax' since it isn't a known property of 'div'. ("

I try to use MathJax in my ionic 2 application. I have an error message when I try to build
E:\Users\Renaud\Applisionic\QCM>ionic cordova build android --prod --release
Running app-scripts build: --prod --iscordovaserve --externalIpRequired --nobrowser
[09:56:52] build prod started ...
[09:56:52] clean started ...
[09:56:52] clean finished in 4 ms
[09:56:52] copy started ...
[09:56:52] ngc started ...
Error: Template parse errors:
Can't bind to 'MathJax' since it isn't a known property of 'div'. ("
<ion-content>
<div MathJax [ERROR ->][MathJax]="formulae">{{formulae}}</div>
<button ion-button block color="secondary" (click)="goToR"): ng:///E:/Users/Renaud/Applisionic/QCM/src/pages/adversaire/adversaire.html#11:14
My directive is define in math-jax.ts :
import {Directive, ElementRef, Input, Component} from '#angular/core';
#Directive({
selector: '[MathJax]'
})
export class MathJaxDirective {
#Input('MathJax') MathJaxInput: string;
constructor(private el: ElementRef) {
}
ngOnChanges() {
console.log('>> ngOnChanges');
this.el.nativeElement.innerHTML = this.MathJaxInput;
console.log(this.MathJaxInput);
eval('MathJax.Hub.Queue(["Typeset",MathJax.Hub, this.el.nativeElement])');
}
}
My HTML file adversaire.html :
<ion-content>
<div MathJax [MathJax]="formulae">{{formulae}}</div>
</ion-content>
The file adversaire.ts :
import { Component } from '#angular/core';
#IonicPage({
name: "adversaire"
})
#Component({
selector: 'page-adversaire',
templateUrl: 'adversaire.html'
})
export class AdversairePage {
formulae : String ;
constructor() {
this.formulae="`sum_(i=1)^n i^3=((n(n+1))/2)^2`";
}
My directive is delare in 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 { AppReno } from './app.component';
import { HomePage } from '../pages/home/home';
import { MathJaxDirective } from '../directives/math-jax/math-jax';
#NgModule({
declarations: [
AppReno,
HomePage,
MathJaxDirective,
],
imports: [
BrowserModule,
IonicModule.forRoot(AppReno),
],
bootstrap: [IonicApp],
entryComponents: [
AppReno,
HomePage,
],
providers: [
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler},
]
})
export class AppModule {}

how do I create a modal view in ionic 2?

The documentation shows you how to open the modal, but isn't clear on what kind of page you're supposed to be passing to the open() method
example from docs:
import { Component } from '#angular/core';
import { ModalController, ViewController } from 'ionic-angular';
constructor(public modalCtrl: ModalController) {
}
presentContactModal() {
let contactModal = this.modalCtrl.create(ContactUs);
contactModal.present();
}
It isn't clear how where the 'ContactUs' object comes from, there is no import for it.
This example linked to here: https://ionicframework.com/docs/api/components/modal/ModalController/
import { Component } from '#angular/core';
import { ModalController, ViewController } from 'ionic-angular';
#Component(...)
class HomePage {
constructor(public modalCtrl: ModalController) { }
presentContactModal() {
let contactModal = this.modalCtrl.create(ContactUs);
contactModal.present();
}
}
///////////////below is the Contact us component which is define with in Homepage
#Component(...)
class ContactUs {
constructor(public viewCtrl: ViewController) {
}
dismiss() {
this.viewCtrl.dismiss();
}
}
The easiest way is to generate a modal content page:
ionic g ModalPage
Then you have to open modal-content.module.ts if the command creates this file, you have to change
imports: [
IonicModule.forChild(ModalPage),
],
TO :
imports: [
IonicModule.forRoot(ModalPage),
],
Then you have to add some html for the modal structure:
<ion-header>
<ion-toolbar>
<ion-title>
GO OUT
</ion-title>
<ion-buttons start>
<button ion-button (click)="dismiss()">
<span ion-text color="primary" showWhen="ios">Cancel</span>
<ion-icon name="md-close" showWhen="android,windows"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<p> This is a modal test!!!! </p>
</ion-content>
Then you have to import in the declarations and entryComponents of the app module.
import { ModalPage } from '../pages/modal-page/modal-page';
#NgModule({
declarations: [
MyApp,
HomePage,
Main,
ModalPage
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp),
HttpModule
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage,
ModalPage
],
providers: [
StatusBar,
SplashScreen,
Device,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
Then in the page you want to execute the modal you have to add a function to the element you want to use to fire it.
<div full large class="button-el btn-goOut" (tap)="openModal()">
In the page you want to use the modal you have to import :
import { ModalPage } from '../modal-page/modal-page'
Important: this element should not be in the constructor, to call the modal you only have to do like this:
openModal(){
let modal = this.modalCtrl.create(ModalPage);
modal.present();
}
You can find a working example here in the docs repository.
It isn't clear how where the 'ContactUs' object comes from, there is
no import for it.
ContactUs is just another page, you can use any page from your app to create a modal with it.
import { Component } from '#angular/core';
import { ModalController, Platform, NavParams, ViewController } from 'ionic-angular';
#Component({
templateUrl: 'template.html'
})
export class BasicPage {
constructor(public modalCtrl: ModalController) { }
openModal(characterNum) {
let modal = this.modalCtrl.create(ModalContentPage, characterNum);
modal.present();
}
}
#Component({
template: `
<ion-header>
<ion-toolbar>
<ion-title>
Description
</ion-title>
<ion-buttons start>
<button ion-button (click)="dismiss()">
<span ion-text color="primary" showWhen="ios">Cancel</span>
<ion-icon name="md-close" showWhen="android, windows"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item>
<ion-avatar item-left>
<img src="{{character.image}}">
</ion-avatar>
<h2>{{character.name}}</h2>
<p>{{character.quote}}</p>
</ion-item>
<ion-item *ngFor="let item of character['items']">
{{item.title}}
<ion-note item-right>
{{item.note}}
</ion-note>
</ion-item>
</ion-list>
</ion-content>
`
})
export class ModalContentPage {
character;
constructor(
public platform: Platform,
public params: NavParams,
public viewCtrl: ViewController
) {
var characters = [
{
name: 'Gollum',
quote: 'Sneaky little hobbitses!',
image: 'assets/img/avatar-gollum.jpg',
items: [
{ title: 'Race', note: 'Hobbit' },
{ title: 'Culture', note: 'River Folk' },
{ title: 'Alter Ego', note: 'Smeagol' }
]
},
{
name: 'Frodo',
quote: 'Go back, Sam! I\'m going to Mordor alone!',
image: 'assets/img/avatar-frodo.jpg',
items: [
{ title: 'Race', note: 'Hobbit' },
{ title: 'Culture', note: 'Shire Folk' },
{ title: 'Weapon', note: 'Sting' }
]
},
{
name: 'Samwise Gamgee',
quote: 'What we need is a few good taters.',
image: 'assets/img/avatar-samwise.jpg',
items: [
{ title: 'Race', note: 'Hobbit' },
{ title: 'Culture', note: 'Shire Folk' },
{ title: 'Nickname', note: 'Sam' }
]
}
];
this.character = characters[this.params.get('charNum')];
}
dismiss() {
this.viewCtrl.dismiss();
}
}
In the example below, ModalContentPage is used to create the modal. Please notice that it's recommended to include just one component per file, so ideally you'd create the page to use as a modal in a different file.