Famous Quotes – Ionic Apps


We are building quotes apps, our apps by default will display all the quotes from one JSON file and we can type to find quotes from a particular author.

What are we learning?

  1. Use HTTP REST call to read a JSON file containing all quotes in quotes.ts.
  2. Sharing the quotes on social networking twitter through cordova-plugin-x-socialsharing.
  3. Uploading the data file i.e quotes.JSON in www/assets/data/quotes.json.
  4. Passing data between different page.
  5. From angular side, we control the search through
     <!-- Displaying all quotes when isfiltered is false -->
     <ion-list *ngIf="!isfiltered">
     
     <!-- Displaying all the filter or one match with search result -->
     <ion-list *ngIf="isfiltered">

 

Let’s build the apps, following all the steps as 

Step 1: Creating the apps through blank template and adding two more page as

>>ionic start QuotesApp blank

Adding two more page
>>ionic generate page quotes-list
>>ionic generate page quotes-detail

 

Step 2: Remove the default home page and replace rootPage value from homePage to QuotesListPage in the app.components.ts

import { Component } from '@angular/core';
.....
import { HttpModule } from '@angular/http';
import { QuotesListPage} from '../pages/quotes-list/quotes-list';

@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  rootPage:any = QuotesListPage;

and we also need to add the reference in app.modules for our two new page and also add SocialSharing provider which we will install the plugin for twitter sharing

import { BrowserModule } from '@angular/platform-browser';
.....
import { QuotesListPage} from '../pages/quotes-list/quotes-list';
import { QuotesDetailPage } from '../pages/quotes-detail/quotes-detail';

@NgModule({
  declarations: [
    MyApp,
    QuotesListPage,
    QuotesDetailPage
  ],
  imports: [
    BrowserModule,
    HttpModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    QuotesListPage,
    QuotesDetailPage
  ],
  providers: [
    SocialSharing,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

 

Step 3: Making a REST HTTP Request, our apps will read a JSON file which contains all the quotes and its details. An HTTP call is used to retrieve the JSON file content and loads the JSON to a local variable. We need to import HTTP module and Rxjs (Reactive Extensions Library for JavaScript). This is a library for composing asynchronous and event-based programs using observables. We are including the map operator in our class, which we will use to manage the JSON return. This is used to transform the return object of collection. Add the following code in pages/quotes-list/quotes-list.ts ,

import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';
import {QuotesDetailPage} from '../quotes-detail/quotes-detail';


@Component({
  selector: 'page-quotes-list',
  templateUrl: 'quotes-list.html',
})
export class QuotesListPage {
  quotesList = [];
  filteredQuotes = [];
  isfiltered: boolean ;

  constructor(private http:Http, public navCtrl: NavController, public navParams: NavParams) {
    this.isfiltered = false;
    this.http.get('assets/data/quotes.json')
    .map(res => res.json())
    .subscribe(
      data => {
        this.quotesList = data.quotes;
      },
      err => console.log("error is "+err), // error
      () => console.log('read quotes Complete '+ this.quotesList) // complete
    );
  }

  searchQuotes(event) {
    if(event.target.value.length > 2) {
      var filteredJson = this.quotesList.filter(function (row) {
        if(row.author.indexOf(event.target.value) != -1) {
          return true
        } else {
          return false;
        }
      });
      this.isfiltered = true;
      this.filteredQuotes = filteredJson;
    }
  }

  itemTapped(event, quote) {
    console.log(quote);
    this.navCtrl.push(QuotesDetailPage, {
      quote: quote
    });
  }

}

Note: quotesList is the variable defined to contain the JSON object. filteredQuotes is the variable which will contain the search results. When we click on any one quote, we will navigate to quotes-detail page with full quotes with author information.

Step 4: Adding the search result, now we will add the search bar to search quote through author name.  Add the following code in pages/quotes-list/quotes-list.html 

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

<ion-content padding>
  <ion-input type="text" placeholder="Search Quotes..." (input)="searchQuotes($event)"></ion-input>

  <ion-list *ngIf="!isfiltered">
    <ion-item *ngFor="let quote1 of quotesList" (click)="itemTapped($event,quote1)">
      <h2>{{quote1.author}}</h2>
      <p class="item-description">{{quote1.quote}}</p>
    </ion-item>
  </ion-list>

  <ion-list *ngIf="isfiltered">
    <ion-item *ngFor="let quote of filteredQuotes" (click)="itemTapped($event,quote)">
      <h2>{{quote.author}}</h2>
      <p class="item-description">{{quote.quote}}</p>
    </ion-item>
  </ion-list>
</ion-content>

The search box when we type more than 2 characters, searchQuotes() is called for searching the JSON object, it will filter the quotes from the quotesList variable. The first ion-list is displayed when the isfiltered value is false, to display the entire list of quotes. The second ion-list is displayed when the isfiltered value is true, to display only the filtered list of quotes.

Step 5: Adding Social Sharing plugin of ionic

$ ionic cordova plugin add cordova-plugin-x-socialsharing
$ npm install --save @ionic-native/social-sharing

Add following code in  pages/quotes-list/quotes-details.html, here we are displaying th quote author and quote in detail and clicking on share twitter will call twitterShare() method to share on twitter apps.

<ion-header>
  <ion-navbar color="primary">
    <ion-title>Quotes Detail</ion-title>
  </ion-navbar>
</ion-header>
<ion-content padding>
  <p>{{quoteDetail.quote}}</p>
  <h4> - {{quoteDetail.author}}</h4>

  <ion-item (click)="twitterShare()">
    <ion-icon>
      <i class="fa fa-twitter" aria-hidden="true" style="color:#1da1f2"></i>- Share on Twitter
    </ion-icon>
  </ion-item>
</ion-content>

Add following code in pages/quotes-list/quotes-details.ts, we are retrieving quote detail and author information through nav params in constructor from the quotes-list.ts page method  itemTapped(event, quote)

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

@Component({
  selector: 'page-quotes-detail',
  templateUrl: 'quotes-detail.html',
})
export class QuotesDetailPage {
  quoteDetail: {quote:'', author:''};
  constructor(public navCtrl: NavController, public navParams: NavParams, private socialSharing: SocialSharing) {
    this.quoteDetail = navParams.get('quote');
  }

  twitterShare(){
    console.log("in twitter share");
    let quote: string = this.quoteDetail.quote;
    this.socialSharing.shareViaTwitter(quote.substring(0,110)+"..",null,"http://ionicframework.com/img/homepage/ionicview-icon_2x.png")
    .then((data )=>{
      alert("Success "+data);
    },
    (err)=>{
    alert("failed "+err)
    })
  } //End of the twitterShare
}

 

Step 6: Format of our quotes.JSON in www/assets/data/quotes.json as

{
  "quotes": [
    {
      "quote": "Angular 1 is a framework. Angular 2 is a platform.",
      "author": "Brad Green"
    },
    {
      "quote": "React is a scalpel, Angular is an operating room.",
      "author": "Corinna Cohn"
    }
	.....
	...
	]
}