Ionic Passing Data from Child to Parent Page

In Ionic, we can use NavController push method to sent data from parent to child page.
this.navCtrl.push(‘childPage’, { “ParentData“: parentdata });

If we want to send data from child to parent, then we can’t use NavController or NavParam to sent data back to the parent page.

We can use event class from ionic-angular. The Events is a publish-subscribe style event system for sending and responding to application-level events across your app.

Step 1: Define publishing event in a child page 

import { Events } from 'ionic-angular';
....
....

this.events.publish('employee:img', this.profileImg);

 

Step 2. In parent page, we have to create listen to the event in viewDidLoad() we will define listener event

ionViewDidLoad() {
	// Get data from child page
	this.event.subscribe('employee:img', (photo) => {
	this.profilePhoto = photo;
}); 

Adding an android back button in Ionic.

Here we will learn how to handle the default mobile’s back button which allows us to popup to the parent page and allow us to exit from the application when there is nothing to pop up a page.

We can achieve android mobile back button through 3rd plugins, like ionic-hardware-buttons. This approach is fine for a project which had only a few pages but if our project has lot of pages, then we have to add

 @BackButton()
    public onBackButton() {
        alert('Back button pushed!');
        return false;
    }

To all the page we have to add above code in typescript to handle back button.

There is another approach, without 3rd plugins. The Platform service can be used to get information about your current device and orientation.  We can uses platform.registerBackButtonAction(fn, priority)

The back button event is triggered when the user presses the native platform’s back button, also referred to as the “hardware” back button. This event is only used within Cordova apps running on Android and Windows platforms. This event is not fired on iOS since iOS doesn’t come with a hardware back button in the same sense an Android or Windows device does.

Registering a hardware back button action and setting a priority allows apps to control which action should be called when the hardware back button is pressed. This method decides which of the registered back button actions has the highest priority and should be called.

import { App, Nav, Platform, MenuController, Events, AlertController } from 'ionic-angular';

@Component({
  templateUrl: 'app.html'
})
export class RupeeBooks {
  @ViewChild(Nav) nav: Nav;


  constructor(
    private app: App,
    private platform: Platform,
    ....
  ) {
    this.nav.setRoot('HomePage');
    platform.ready().then(() => {
      this.splashScreen.hide();
      this.statusBar.styleDefault();
    });

    platform.registerBackButtonAction(() => {
      let nav = app.getActiveNavs()[0];
      let activeView = nav.getActive();

      if (activeView.name !== 'HomePage') {
        if (nav.canGoBack())
          nav.pop();
      }
      else {
        platform.exitApp();
        // Add toast or confirm code over here
      }
    });
  }

Ionic Signature drawing without 3rd party plugin

We can add a signature on our ionic project without and with npm package like angular2-signaturepad. In this example, we are creating simple ionic apps allowing a user to write a signature on our application without angular2-signaturepad. We allow a user to write a signature and save in Base64 png and which we can save in our database as a string.
In this example we are learning touch event, touch events interfaces are relatively low-level APIs that can be used to support application-specific multi-touch interactions such as a two-finger gesture. Touch event will work only on devices with touches screen support and this signature will not work on the desktop browser.

  1. The touchstart event occurs when the user touches an element.
  2. touchmove event occurs when a user moves the finger over an element – works only in touchscreen devices.

Steps 1: Create a new project
ionic start signaturePad blank

Step 2: Add the user interface in home.html,
We have to define a canvas element where we are writing our signature on it.

<ion-header>
  <ion-navbar color="primary">
    <ion-title>
      Ionic Canvas Signature
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding no-bounce>
  <div #fixedContainer ion-fixed>
    <canvas #signatureCanvas (touchstart)="startDrawing($event)" (touchmove)="moved($event)"></canvas>
    <ion-grid>
      <ion-row>
        <ion-col col-6>
          <button ion-button color="danger" (click)="clearPad()">Clear</button>
        </ion-col>
        <ion-col col-4 offset-2>
          <button ion-button color="secondary" (click)="savePad()">Save</button>
        </ion-col>
      </ion-row>
    </ion-grid>
  </div>
  <img src='{{signatureImg}}' />
</ion-content>

Step 3: Add css rule 

page-home {
    canvas {
        display: block;
        border: 1px solid rgb(187, 178, 178);
    }
    .color-block {
        height: 40px;
    }
}

Step 4: Add Typescript code to draw signature on canvas and save in base64 formats.

import { Component, ViewChild, Renderer } from '@angular/core';
import { NavController, Platform, Content } from 'ionic-angular'; 
 
@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  // Canvas stuff
  @ViewChild('signatureCanvas') canvasEL : any;
  //Reference Canvas Object
  private canvasElement: any;
  //Reference the context for Canvas Element
  private _CONTEXT : any;
 
  saveX: number;
  saveY: number;
  signatureImg: any;
  
  // Make Canvas sticky at the top stuff
  @ViewChild(Content) content: Content;
  @ViewChild('fixedContainer') fixedContainer: any;

  constructor(public navCtrl: NavController, public renderer: Renderer, private plt: Platform) {
  }
 
  ionViewDidEnter() {
    // Get the height of the fixed item
    let itemHeight = this.fixedContainer.nativeElement.offsetHeight;
    let scroll = this.content.getScrollElement();
 
    itemHeight = Number.parseFloat(scroll.style.marginTop.replace("px", "")) + itemHeight;
    scroll.style.marginTop = itemHeight + 'px';
  }
 
  ionViewDidLoad() {
    this.canvasElement = this.canvasEL.nativeElement;
    this.canvasElement.width = this.plt.width() + '';
    this.canvasElement.height = 200;
  }
 
  startDrawing(ev) {
    var canvasPosition = this.canvasElement.getBoundingClientRect();
   
    this.saveX = ev.touches[0].pageX - canvasPosition.x;
    this.saveY = ev.touches[0].pageY - canvasPosition.y;
  }
   
  moved(ev) {
    var canvasPosition = this.canvasElement.getBoundingClientRect();
   
    let ctx = this.canvasElement.getContext('2d');
    let currentX = ev.touches[0].pageX - canvasPosition.x;
    let currentY = ev.touches[0].pageY - canvasPosition.y;
   
    ctx.lineJoin = 'round';
    ctx.strokeStyle = '#000000';
    ctx.lineWidth = 5;
   
    ctx.beginPath();
    ctx.moveTo(this.saveX, this.saveY);
    ctx.lineTo(currentX, currentY);
    ctx.closePath();
   
    ctx.stroke();
   
    this.saveX = currentX;
    this.saveY = currentY;
  }
   
   
  savePad() {
    var dataUrl = this.canvasElement.toDataURL();
    this.signatureImg = dataUrl;
    let ctx = this.canvasElement.getContext('2d');
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // Clears the canvas

  }

  clearPad() {
    this._CONTEXT = this.canvasElement.getContext('2d');
    this._CONTEXT.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);
  }
}

 

Calculate Base64 Image Size

In this articles, we will get exact length Base64 photo from ionic native Camera|Gallery in Kilobytes.
Base64 encodes three bytes to four characters. Sometimes, padding is added in the form of one or two ‘=’ characters.

To get the length of bytes we use the formula:

(3 * (LengthInCharacters / 4)) - (numberOfPaddingCharacters)

Step 1: Create and add an ionic native-camera plugin

Step 2: Add Typescript code to calculate base64 image size in KiloBytes in home.ts

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;
  public base64Str: any;
  private kbytes: number;
  constructor(private camera: Camera, public navCtrl: NavController) {
  }

  async takePhoto(sourceType) {
    try {
      const options: CameraOptions = {
        quality: 50,
        targetHeight: 300,
        targetWidth: 400,
        destinationType: this.camera.DestinationType.DATA_URL,
        encodingType: this.camera.EncodingType.JPEG,
        saveToPhotoAlbum: false,
        correctOrientation: true,
        mediaType: this.camera.MediaType.PICTURE,
        sourceType: sourceType
      }
      const result = await this.camera.getPicture(options);
      this.image = `data:image/png;base64,${result}`;
      console.log(this.image);
      this.base64Str = this.image.split(',');

      if (this.calculateImageSize(this.base64Str[1]) > 50 ){
        alert("Reduce the size of image");
      }
    }
    catch (err) { 
      console.error(err);
    }
  }

  calculateImageSize(base64String){
    let padding, inBytes, base64StringLength;
    if(base64String.endsWith("==")) padding = 2;
    else if (base64String.endsWith("=")) padding = 1;
    else padding = 0;

    base64StringLength = base64String.length;
    console.log(base64StringLength)
    inBytes =(base64StringLength / 4 ) * 3 - padding;
    console.log(inBytes);
    this.kbytes = inBytes / 1000;
    return this.kbytes;
  }

}

Step 3: Add User Interface in home.html

<ion-header>
  <ion-navbar color="primary">
    <ion-title>
      ID Card
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <img [src]="image" *ngIf="image">
  <p *ngIf="kbytes">Image size: {{ kbytes}} KB</p>
  <ion-row class="center">
    <ion-col width-50>
      <button ion-button (click)="takePhoto(1)">Show Camera</button>
    </ion-col>
    <ion-col width-50>
      <button ion-button (click)="takePhoto(0)">Show Album</button>
    </ion-col>
  </ion-row>
</ion-content>

How to Implement Toast in Ionic

Ionic comes with a number of components, including modals, popups, and cards.  Ionic ToastController can be used to display information for the short period of time by using ToastController.  The toast is commonly used to provide feedback, error/ other messages about a particular task’s status or to simply display a short message on top of app’s content. The Toast message can be displayed either on the top of the screen, middle and on the bottom area.

The Ionic makes it easy to implement toast on your app’s. follow the below steps to implement toast in your ionic app.

Step 1: Create a project to implement ToastController

ionic start toastExample blank

Step 2: Import the ToastController and add ToastController code in Typescript

We have to import ToastController from ionic-angular and the instance of ToastController have to be into ou constructor as the property. In this example, we are using ToastController to display message on

  1. Display Toast message when the mouse cursor comes over image
  2. Display ToastController message over different position – ionic ToastController example code from ionic documentation.
  3. Display different ToastController message when all form fields are filled or not filled.

    ionic ToastController
    ionic ToastController

Add the following code in home.ts file

import { Component, OnInit } from '@angular/core';
import { ToastController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  imgToast: HTMLElement;
  name: string;
  brithday: any;

  constructor(public toastCtrl: ToastController) {
    console.log("value of name : ", this.name);
    this.brithday = new Date().toISOString();
  }

  ngOnInit() {
    this.imgToast = document.getElementById('imgSection');
    this.imgToast.addEventListener('mousemove', ev => {
      let toast = this.toastCtrl.create({
        message: 'On MouseOver event on an image',
        duration: 2000,
        position: 'middle'
      });
      toast.present(toast);
    });
  }

  showToast(position: string) {
    let toast = this.toastCtrl.create({
      message: 'Mmmm, buttered toast',
      duration: 1000,
      position: position
    });
    toast.present(toast);
  }

  showToastWithCloseButton() {
    const toast = this.toastCtrl.create({
      message: 'Your files were successfully saved',
      showCloseButton: true,
      closeButtonText: 'Ok'
    });
    toast.present();
  }

  showLongToast() {
    let toast = this.toastCtrl.create({
      message: 'Example of showing long toast',
      duration: 4000,
    });
    toast.present();
  }

  save() {
    console.log("Name in save : ", this.name);
    console.log("Birthday in save : ", this.brithday);
    if(this.name != null && this.brithday != null){
      let toast = this.toastCtrl.create({
        message: 'User profile was saved successfully',
        position: 'bottom',
        duration: 3000
      });
      toast.present();
    }
    else {
      let toast = this.toastCtrl.create({
        message: 'User profile field is not filled',
        position: 'bottom',
        duration: 3000
      });
      toast.present();
    }

  }
}

When creating a new toast notification using the method create(), we can pass an object to configure the toast notification. The following configuration properties are supported by ToastController.

  1. message – Message to display.
  2. duration – Number of milliseconds before the toast is dismissed.
  3. position – Position to show the toast; possible values are top, middle and bottom.
  4. showCloseButton – Whether to show a button to close the toast.
  5. closeButtonText – Text of the close button.
  6. dismissOnPageChange – Whether to dismiss the toast when navigating to a different page.

Step 3: We need to add following code in the home.html template 

<ion-header>
  <ion-navbar color="primary" text-center>
    <ion-title>
      Ionic Toast Example
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <ion-card>
    <img id="imgSection" src="assets/imgs/toast.jpg">
  </ion-card>

  <button ion-button block (click)="showToast('top')">Show Toast Top Position</button>
  <button ion-button block (click)="showToast('bottom')">Show Toast Bottom Position</button>
  <button ion-button block (click)="showLongToast()">Show Long Toast</button>
  <button ion-button block (click)="showToastWithCloseButton()">Show Toast W/ Close Button</button>
  
  <ion-grid>
    <ion-item>
      <ion-label fixed>Name</ion-label>
      <ion-input class="right" type="text" name="ngModel" [(ngModel)]="name"></ion-input>
    </ion-item>
    <ion-item>
      <ion-label>Birthday</ion-label>
      <ion-datetime displayFormat="MM/DD/YYYY" [(ngModel)]="birthday" presentWith="min"></ion-datetime>
    </ion-item>
    <button ion-button color="secondary" block (click)="save()">Save</button>
  </ion-grid>

</ion-content>




In the example below, we have use toastController to display notification message we user profile data is an update to Firebase database.

  editProfileInfo(){
    this.db.list('/profiles/').update(this.navParams.get('userId'), this.profileRef).then( data => {
      let toast = this.toastCtrl.create({
        message: 'Additional User Profile Add successful',
        duration: 3000,
        position: 'top'
      });
    
      toast.onDidDismiss(() => {
        console.log('Dismissed toast');
      });
    
      toast.present();
    });

 

Install ionic in Ubuntu

Installing Node in Ubuntu or Fixing npm permission:

  1. First, we need to add ppa file to our Ubuntu package archive
  2. First, we need to install the curl and then we can install
    curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
    sudo apt-get install -y nodejs

Fixing npm permissions – Configuring the node to the local user, so that we don’t have to use sudo command. You may receive an EACCES error when you try to install a package globally. This indicates that you do not have permission to write to the directories that npm uses to store global packages and commands.

You can fix this problem using one of three options:

  1. Change the permission to npm’s default directory.
  2. Change npm’s default directory to another directory.
  3. Install Node with a package manager that takes care of this for you.

Option 1: Change the permission to npm’s default directory

Find the path to npm’s directory: By running command below will display /usr/local for many systems, WARNING: If the displayed path is just /usr, switch to Option 2 or you will mess up your permissions.

npm config get prefix

If the display path is not /usr then we need to change the owner of npm’s directories to the name of the current user (your username!):  This changes the permissions of the sub-folders used by npm and some other tools (lib/node_modules, bin, and share).

sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}




Option 2: Change npm’s default directory to another directory

There are times when you do not want to change ownership of the default directory that npm uses (i.e. /usr) as this could cause some problems, for example if you are sharing the system with other users. Instead, you can configure npm to use a different directory altogether. In our case, this will be a hidden directory in our home folder.

2.1 Make a directory for global installations:
   mkdir ~/.npm-global

2.2 Configure npm to use the new directory path in command mode:
npm config set prefix ‘~/.npm-global’

2.3 Open or create a ~/.profile file and add this line at last line of the file:
export PATH=~/.npm-global/bin:$PATH

2.4 Back on the command line, update your system variables:
source ~/.profile

Test: Download a package globally without using sudo.
npm install -g ionic cordova

Ionic Angular Material Integration

We can integrate Angular Material in Ionic easily, we have to follow Configuration certain step

ionic new angularMaterial blank

  1. npm install –save @angular/material @angular/cdk @angular/animationse
  2. Adding a custom copy script,  Copy the file copy.config.js file and past in new location with folder name config in the root folder. Ionic includes a copy script file that is called during the build process when you run 
    ionic serve

    and it’s responsible for moving certain resources from to

    node_modules

     the www folder,

  3. Rename the copy.config.ts to copy-custom-libs.js: append the following code along with existing code at the end.
      copyAngularMaterialCss: {
        src: ['{{ROOT}}/node_modules/@angular/material/prebuilt-themes/indigo-pink.css'],
        dest: '{{WWW}}/assets/css'
      }
    }
  4. Open index.html of root folder, add following code in <head>
    <link href=”assets/css/indigo-pink.css” rel=”stylesheet”/>
  5. Last but not least, we need to instruct Ionic that we want to use our new copy script as opposed to the one that is included already. For that, we need to open our package.JSON file and add the following section We can restart our apps, we can use material theme indigo-pink.cs in our apps.
     "config": {
        "ionic_copy": "./config/copy-custom-libs.js"
      },

     Registering material module in app.module.ts file 

    @NgModule({
      declarations: [
        MyApp,
        HomePage
      ],
      imports: [
        MatButtonModule,
        MatSnackBarModule,
        MatFormFieldModule,
        MatInputModule,
        IonicModule.forRoot(MyApp)
      ],

    Note: When using latest angular-material we may get a runtime error if the error is related to rxjs, then we have to install the latest or rxjs 5.5.0.



    Add the following code in src/pages/home/home.html 

    <ion-header>
      <ion-navbar>
        <ion-title>
          IonicAngular Material
        </ion-title>
      </ion-navbar>
    </ion-header>
    <ion-content>
      <mat-form-field>
        <input matInput value="Disco party!" placeholder="Message" #message>
      </mat-form-field>
      
      <mat-form-field>
        <input matInput value="Dance" placeholder="Action" #action>
      </mat-form-field>
      
      <button mat-button (click)="openSnackBar(message.value, action.value)">Show snack-bar</button>
    
      <h3>Raised Buttons</h3>
      <div class="button-row">
        <button mat-raised-button>Basic</button>
        <button mat-raised-button color="primary">Primary</button>
        <button mat-raised-button color="accent">Accent</button>
        <button mat-raised-button color="warn">Warn</button>
        <button mat-raised-button disabled>Disabled</button>
        <a mat-raised-button routerLink=".">Link</a>
      </div>
    </ion-content>

    Add the following code in src/pages/home/home.ts 

    import { Component } from '@angular/core';
    import { NavController } from 'ionic-angular';
    import {MatSnackBar} from '@angular/material';
    
    
    @Component({
      selector: 'page-home',
      templateUrl: 'home.html'
    })
    export class HomePage {
    
      constructor(public navCtrl: NavController, public snackBar: MatSnackBar) {
      }
    
      openSnackBar(message: string, action: string) {
        this.snackBar.open(message, action, {
          duration: 2000,
        });
      }
    
    }

 



Ionic Tutorial

    1. Install ionic in Ubuntu
    2. Ionic List
    3. Ionic Slider
    4. Adding Left and Right menu
    5. Custom Tag or Component & If and Else in Ionic 3
    6. Custom Directive – Custom input Directive
    7. Creating a Custom Pipe
    8. Navigation multiple page with state parameter
    9. Ionic Multiple page and Ionic Sliding -1
    10. Ionic ToastController
    11. Ionic InAppBrowser Plugin
    12. Ionic Modal Component and Multiple page
    13. Embedded full screen video background
    14. Ionic Content – Social sharing plugin
    15. Adding the Font-awesome and Font to Ionic
    16. Ionic Local Storage
    17. Ionic Lazy Loading
    18. Form in ionic
    19. Ionic Form Validation
    20. Ionic Formbuilder
    21. Shared Service to provide data to multiple pages
    22. Ionic – Camera and Photo Gallery



  1. Ionic Local Storage
  2. Retrieving Static JSON data through HTTP Module
  3. Saving Memories – Storing the pictures
  4. Implement PayPal in Ionic WooCommerce
  5. Build a Real-Time Tutorial App with Ionic & Firebase
  6. Ionic CRUD operation on Firebase through AngularFirebase 2
  7. Ionic Uploading Image from Gallery to Firebase
  8. Ionic Camera Photo Upload in Firebase
  9. Ionic 3 Gmail Login with Firebase
  10. Ionic 3 Facebook Login with Firebase
  11. How to used D3 in Ionic 3
  12. How to add chart from chart.js to Ionic Apps
  13. Ionic Testing
  14. Ionic Getting location Latitude and Longitude
  15. Ionic Angular Material Integration

 



Project in Ionic

  1. Go Offline – add to do list on PouchDb
  2. Famous Quotes – Ionic Apps
  3. Weather – Chart Apps
  4. How to add Leaflet Map in Ionic -3
  5. How to add Google Map and Multiple Marker using Ionic 3
  6. Ionic Data Storage – For MovieList

Implement PayPal in Ionic WooCommerce

Note : Incomplete Code

The PayPal is one the most popular and reliable mode of the payment transaction in mobile and web technology. In Ionic, we can easily integrate PayPal and other transaction modes in ionic apps. The Ionic framework provides Cordova plugin to implement PayPal in ionic.
In this example, we will learn how to integrate PayPal sandbox method in the ionic app backend supported by Woocommerce site.

We have to follow certain steps to achieve our task.

  1. First, we need to have a PayPal account. In the PayPal developer account, we need to create an app in PayPal. Click on the dashboard, we have the option to create new REST API app.
  2. Every app has a Client ID, we will use the sandbox API credential. We need to use sandbox client API later. For the real application, we have to use live credential.
  3. In Account section, we can create any number of an account with a balance to test the working of PayPal through sandbox method.
  4. We have to install the following plugin
    $ ionic cordova plugin add com.paypal.cordova.mobilesdk
    $ npm install --save @ionic-native/paypal
  5. We have to register the PayPal provider in app.module.ts file.
    import { PayPal } from '@ionic-native/paypal';
    
      providers: [
        ...
        PayPal,
        {provide: ErrorHandler, useClass: IonicErrorHandler}
      ]

In HTML template we have to add, following code

<ion-header>
  <ion-navbar color="primary">
    <ion-title>Paypal</ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
  <ion-list>
    <ion-item>
      <ion-label>Payment Method</ion-label>
      <ion-select [(ngModel)]="paymentMethod">
        <ion-option *ngFor="let p of paymentMethods" value="{{p.method_id}}">
          {{ p.method_title}}
        </ion-option>
      </ion-select>
    </ion-item>
  </ion-list>
</ion-content>

<ion-footer>
  <button ion-button block color="danger" (click)="placeOrder()">Place Order</button>
</ion-footer>

 

Add the following code in paymentPage.ts

import { Component } from '@angular/core';
import { NavController, NavParams, AlertController } from 'ionic-angular';
import { Storage } from '@ionic/storage';
import * as WC from 'woocommerce-api';
import { HomePage } from '../home/home';
import { PayPal, PayPalPayment, PayPalConfiguration } from '@ionic-native/paypal';

@Component({
  selector: 'page-checkout',
  templateUrl: 'checkout.html',
})
export class CheckoutPage {

  WooCommerce: any;
  newOrder: any;
  paymentMethods: any[];
  paymentMethod: any;
  billing_shipping_same: boolean;
  userInfo : any; 

  constructor(public navCtrl: NavController, public navParams: NavParams, 
    public storage: Storage, public alertCtrl: AlertController, public payPal: PayPal) {
    this.newOrder = {};
    this.newOrder.billing_address = {};
    this.newOrder.shipping_address = {}
    this.billing_shipping_same = false;

    this.paymentMethods = [
      { method_id: "bacs", method_title: "Direct Bank Transfer"},
      { method_id: "cheque", method_title: "Cheque Payment"},
      { method_id: "chod", method_title: "Cash on Delivery"},
      { method_id: "paypal", method_title: "Paypal" }];

    this.WooCommerce = WC({
      url: "http://*****************.us",
      consumerKey: "********************************",
      consumerSecret: "****************************"
    });
  }


  placeOrder(){

    let orderItems: any[] = [];
    let data: any = {};

    let paymentData: any = {};

    this.paymentMethods.forEach( (element, index) => {
      if(element.method_id == this.paymentMethod ){
        paymentData = element;
      }
    });

    data = {
      payment_details : {
        method_id: paymentData.method_id,
        method_title : paymentData.method_title,
        paid: true
      },

      billing_address : this.newOrder.billing_address,
      shipping_address : this.newOrder.shipping_address,
      customer_id : this.userInfo.id || '',
      line_items: orderItems
    };

    if(paymentData.method_id == "paypal"){
      this.payPal.init({
        PayPalEnvironmentProduction: 'YOUR_PRODUCTION_CLIENT_ID',
        PayPalEnvironmentSandbox: '******************************'
      }).then(() => {
        // Environments: PayPalEnvironmentNoNetwork, PayPalEnvironmentSandbox, PayPalEnvironmentProduction
        this.payPal.prepareToRender('PayPalEnvironmentSandbox', new PayPalConfiguration({
			
          // Only needed if you get an "Internal Service Error" after PayPal login!
          //payPalShippingAddressOption: 2 // PayPalShippingAddressOptionPayPal
		  
        })).then(() => {

          this.storage.get("cart").then((cart) => {

            let total = 0.00;
            cart.forEach((element, index) =>{
              orderItems.push({ product_id: element.product.id, quantity: element.qty });
              total = total + (element.product.price * element.qty);
            });

            let payment = new PayPalPayment(total.toString(), 'USD', 'Description', 'sale');
            this.payPal.renderSinglePaymentUI(payment).then(( response ) => {
              // Successfully paid

              alert(JSON.stringify(response));

              data.line_items = orderItems;

              let orderData: any = {};

              orderData.order = data;

              this.WooCommerce.postAsync('orders', orderData, (err, data, res) => {
                alert("Order placed successfully !");

                let response = (JSON.parse(data.body).order);
                  this.alertCtrl.create({
                    title: "Order Placed Successfully",
                    message: "Your order has been placed successfully. Your order number is " + response.order_number,
                    buttons: [{
                      text: "OK",
                      handler: () => {
                        this.navCtrl.setRoot(HomePage);
                      }
                    }]
                  }).present();
              })

          })
       }, () => {
            // Error or render dialog closed without being successful
			
          });
        }, () => {
          // Error in configuration
		  
        });
      }, () => {
        // Error in initialization, maybe PayPal isn't supported or something else
			
      });
    } else {
      this.storage.get("cart").then( (cart) => {
        
        cart.forEach( (element, index) => {
          orderItems.push({
            product_id: element.product.id,
            quantity: element.qty
          });
        });

        data.line_items = orderItems;

        let orderData: any = {};

        orderData.order = data;

        this.WooCommerce.postAsync("orders", orderData).then( (data) => {
          let response = (JSON.parse(data.body).order);

          this.alertCtrl.create({
            title: "Order Placed Successfully",
            message: "Your order has been placed successfully. Your order number is " + response.order_number,
            buttons: [{
              text: "OK",
              handler: () => {
                this.navCtrl.setRoot(HomePage);
              }
            }]
          }).present();

        })
      })
    }
  }
  ionViewDidLoad() {
    console.log('ionViewDidLoad CheckoutPage');
  }

}

 

How to add Leaflet Map in Ionic -3

In most of the apps, maps are one of the most useful tools for users when included in an app. In the last example, I had added Google map in ionic. In this example, we learning how to add Leaflet map in Ionic 3.

The Leaflet is a widely used open-source JavaScript library used to build web mapping applications. it is one of the most popular JavaScript mapping libraries and is used by major websites such as FourSquare, Pinterest, and Flickr.

Step 1: Step up the project

ionic start leafletIonic tabs
npm install leaflet --save

Step 2: Set up the Tabs Template

We don’t need to test this app on real device, we can test on the browser. First, we modify the existing code of the tab.html. Replace existing code with the following code in pages/tabs/tabs.html

<ion-tabs>
  <ion-tab [root]="tab1Root" tabTitle="Leaflet 1" tabIcon="locate"></ion-tab>
  <ion-tab [root]="tab2Root" tabTitle="Leaflet 2" tabIcon="locate"></ion-tab>
  <ion-tab [root]="tab3Root" tabTitle="All Map" tabIcon="map"></ion-tab>
</ion-tabs>

We will rename the existing page to the new name, in first two tab page we will display the different location and different design for each page and last page we will displaying multiple markers.

Modify the tabs.ts file

import { Component } from '@angular/core';
import { LeafletPage } from '../leaflet/leaflet';
import { Leaflet2Page } from '../leaflet2/leaflet2';
import { AllMapPage } from '../allMap/allMap';

@Component({
  templateUrl: 'tabs.html'
})
export class TabsPage {

  tab1Root = LeafletPage;
  tab2Root = Leaflet2Page;
  tab3Root = AllMapPage;

  constructor() {}
}

Step 3: Set up First Leaflet design 

Add the following code in src/pages/leaflet/leaflet.html

<ion-header>
  <ion-navbar color="primary">
    <ion-title>Leaflet Map Design 1</ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
  <div class="map-container">
    <div id="mapId" style="width: 100%; height: 100%">
    </div>
  </div>
</ion-content>

Add the following code in src/pages/leaflet/leaflet.ts

import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';

import L from "leaflet";

@Component({
  selector: 'page-leaflet',
  templateUrl: 'leaflet.html'
})
export class LeafletPage {
  map: L.Map;
  center: L.PointTuple;

  constructor(public navCtrl: NavController, public navParams: NavParams) {}

  ionViewDidLoad() {
    console.log('ionViewDidLoad MapPage');
    this.center = [28.644800, 77.216721];
    this.leafletMap();
  }

  leafletMap(){
    this.map = L.map('mapId', {
      center: this.center,
      zoom: 13
    });

    var position = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', {
      attribution: 'edupala.com © ionic LeafLet'
    }).addTo(this.map);

    var marker = new L.Marker(this.center);
    this.map.addLayer(marker);

    marker.bindPopup("<p>Tashi Delek.<p>Delhi</p>");
  }
}

Add the following code in leaflet.scss

page-leaflet {
    .map-container {
        position: absolute;
        top: 0px;
        bottom: 0px;
        width: 100%;
        height: 100%;
    }
}

 

Step 4: Set up Second Leaflet design 




Add the following code in src/pages/leaflet2/leaflet2.html


<ion-header>
  <ion-navbar color="primary">
    <ion-title>Leaflet Design 2</ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
  <div class="container-map">
    <div id="mapId2" style="width: 100%; height: 100%">
    </div>
  </div>
</ion-content>

Add the following code in src/pages/leaflet2/leaflet2.ts

import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import L from "leaflet";

@Component({
  selector: 'page-leaflet2',
  templateUrl: 'leaflet2.html'
})
export class Leaflet2Page {
  map: L.Map;
  center: L.PointTuple;

  constructor(public navCtrl: NavController, public navParams: NavParams) {}

  ionViewDidLoad() {
    console.log('ionViewDidLoad MapPage');
    this.center = [12.972442, 77.594563];
    this.leafletMap();
   
  }

  leafletMap(){
    this.map = L.map('mapId2', {
      center: this.center,
      zoom: 13
    });

    var positron = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
      attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <a href="http://cartodb.com/attributions">CartoDB</a>'
    }).addTo(this.map);

    var marker = new L.Marker(this.center);
    this.map.addLayer(marker);

    marker.bindPopup("<p>Tashi Delek - Nmasta Bangalore.</p>");
   }
 }

Add the following code in leaflet2.scss

page-leaflet2 {
    .container-map {
        position: absolute;
        top: 0px;
        bottom: 0px;
        width: 100%;
        height: 100%;
    }
}

 

Step 5: Adding multiple markers in Leaflet Map

We have created three-page in this apps, two to display the list of the single leaflet map. This page we will add multiple leaflet marker in the Leaflet map.

 

Add following data on data.JSON in www/assets/data/data.json as

 {
    "properties" : [
    {,
        "city": "Cambridge",
        "state" : "MA",
        "long": -71.10858,
        "lat": 42.35963
    },
    {
        "city": "Cambridge",
        "state": "MA",
        "long": -71.10869,
        "lat": 42.359103,
    },
    {
        "city": "Boston",
        "state": "MA",
        "long": -71.110061,
        "lat": 42.360686,
    },
    {
        "city": "Cambridge",
        "long": -71.110448,
        "lat": 42.360642
    }
    ]
 }

Add the following code in src/pages/allMap/allMap.html

<ion-header>
  <ion-navbar color="primary">
    <ion-title>
      Ionic Leaflet All Multiple Marker
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
  <div class="container-map">
    <div id="mapId" style="width: 100%; height: 100%"></div>
  </div>
</ion-content>

 

Add the following code in src/pages/allMap/allMap.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import {Http } from '@angular/http';
import 'rxjs/add/operator/map';
import L from "leaflet";

@Component({
  selector: 'page-allMap',
  templateUrl: 'allMap.html'
})
export class AllMapPage {
  propertyList = [];
  center: L.PointTuple;
  map;

  constructor(public navCtrl: NavController, private http: Http) {
    this.http.get('assets/data/data.json')
    .map(res => res.json())
    .subscribe(data => {
        this.propertyList = data.properties;
    },
    err => console.log("error is "+err), // error
      () => this.leafletMap()
    );
  }

  ionViewDidLoad() {
    this.map = L.map('mapId').setView([42.35663, -71.1109], 16);
    
    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
      attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(this.map);
  }


  leafletMap(){
    console.log("property" + this.propertyList.length);
    for (let property of this.propertyList) {
      L.marker([property.lat, property.long]).addTo(this.map)
      .bindPopup(property.city)
      .openPopup();
    }
  }
}