Chapter 14. Creating an E-Commerce Application Using the Ionic Framework

In this chapter, we will bring together all the knowledge that we accumulated in this book until now and implement it in an easy-to-use Ionic framework, which can be applied in our own projects.

In particular, in this chapter, we will build on the work that has already been done in Chapter 3, Creating an API, and we will use this work with an Ionic project, which will be accessible through an Android or iOS smartphone.

Designing our application

As part of the application development process, it is important that we understand how we will structure our application and connect it to the product API in order to achieve our final goal of creating a basic e-commerce application.

For this particular project, we will work on two main screens—the product's list items, the controller, and the product page. In addition to this, we will also focus on creating a basic functional side menu and a rudimentary purchasing option, which is nonfunctional at this stage.

Creating an Ionic project

We will start off our project by creating a project based on one of the Ionic starter templates that we didn't have an opportunity to use in the previous chapters. The side menu templates provide us with a side menu, a list item's view, and a list item's detailed view. This template should give us the necessary groundwork to create the ideal e-commerce application.

Open your terminal and input the following command:

$ ionic start grocerApp sidemenu

The preceding command will create a project folder with the sidemenu project. In order to further understand how this template works, we encourage you to first navigate to the project folder and then input the following command:

$ ionic serve --lab

This will open the browser of your choice and give you a side-by-side view of how the application will look on an Android and iOS device:

Creating an Ionic project

Implementing our designs

When implementing our designs, we need to reflect the necessary changes within the app's code. We will first start off by modifying our controllers.

We will first begin by navigating to app.js, which is available at the path www/js/app.js.

We will replace the existing code in app.js with the following:

angular.module('starter', ['ionic', 'starter.controllers'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
  // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
  // for form inputs)
  if (window.cordova && window.cordova.plugins.Keyboard) {
    cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    cordova.plugins.Keyboard.disableScroll(true);

  }
  if (window.StatusBar) {
    // org.apache.cordova.statusbar required
    StatusBar.styleDefault();
  }
});

.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider

  .state('app', {
    url: '/app',
    abstract: true,
    templateUrl: 'templates/menu.html',
    controller: 'AppCtrl'
  })

  .state('app.search', {
    url: '/search',
    views: {
      'menuContent': {
      templateUrl: 'templates/search.html'
    }
  }
})

state('app.products', {
  url: '/products',
  views: {
    'menuContent': {
    templateUrl: 'templates/products.html',
    controller: 'ProductsCtrl'
  }
}
})

.state('app.single', {
  url: '/products/:productId',
  views: {
    'menuContent': {
    templateUrl: 'templates/product.html',
    controller: 'ProductCtrl'
    }
  }
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/app/products');
});

The aforementioned code will allow us to implement the different screens that form a part of our app, namely the products page, the individual product, and the search functionality, which will not be implemented in the current version of the application.

The next step in our modification stage is to implement the necessary changes in our app controllers, which are based in the controllers.js file. Go ahead and replace the existing code with the following:

angular.module('starter.controllers', [])

.controller('AppCtrl', function($scope, $ionicModal, $timeout) {

  // Form data for the login modal
  $scope.loginData = {};

  // Create the login modal that we will use later
  $ionicModal.fromTemplateUrl('templates/login.html', {
    scope: $scope
  }).then(function(modal) {
    $scope.modal = modal;
  });

  // Triggered in the login modal to close it
  $scope.closeLogin = function() {
    $scope.modal.hide();
  };

  // Open the login modal
  $scope.login = function() {
    $scope.modal.show();
  };

  // Perform the login action when the user submits the login form
  $scope.doLogin = function() {
    console.log('Doing login', $scope.loginData);

    // Simulate a login delay. Remove this and replace with your login
    // code if using a login system
    $timeout(function() {
      $scope.closeLogin();
    }, 1000);
  };
})

.controller('ProductsCtrl', function($scope) {
  $scope.products = [
    { title: 'Apples', id: 1 ,price:1.00, image:'http://loremflickr.com/30/30/apples'},
    { title: 'Carrots', id: 2,price:2.00, image:'http://loremflickr.com/30/30/carrots' },
    { title: 'Tomatoes', id: 3 ,price:3.00, image:'http://loremflickr.com/30/30/tomatoes'},
    { title: 'Pears', id: 4, price:1.50, image:'http://loremflickr.com/30/30/pears' },
    { title: 'Grapes', id: 5, price:1.00, image:'http://loremflickr.com/30/30/grapes' },
    { title: 'Plums', id: 6, price: 2.50, image:'http://loremflickr.com/30/30/plums' },
    { title: 'Olives', id:7, price: 0.50, image:'http://loremflickr.com/30/30/olives'}
  ];
})

.controller('ProductCtrl', function($scope, $stateParams) {
});

As you can see in the preceding code, we declared an array of products. At this point in time, this declares a product title through the title variable, the product ID through id, and price through price. Last but not least, in order to spice things up, we also added a link to a thumbnail image generator supported by http://loremflickr.com.

The current setup will not reflect in the frontend of our mobile application because we haven't done the necessary changes in the HTML files.

We will first rename playlist.html and playlists.html to product.html and products.html respectively. We can find both of these files at the www/templates/playlist.html and www/templates/playlists.html path.

We will then navigate to the menu.html file, which is available at the www/templates/menu.html path.

We will replace the existing code in the preceding path with the following:

<ion-side-menus enable-menu-with-back-views="false">
  <ion-side-menu-content>
    <ion-nav-bar class="bar-stable">
      <ion-nav-back-button>
      </ion-nav-back-button>

      <ion-nav-buttons side="left">
        <button class="button button-icon button-clear ion-navicon" menu-toggle="left">
        </button>
      </ion-nav-buttons>
    </ion-nav-bar>
    <ion-nav-view name="menuContent"></ion-nav-view>
  </ion-side-menu-content>

  <ion-side-menu side="left">
    <ion-header-bar class="bar-stable">
      <h1 class="title">Shop Menu</h1>
    </ion-header-bar>
    <ion-content>
      <ion-list>
        <ion-item menu-close href="#/app/search">
          Search
        </ion-item>
        <ion-item menu-close href="#/app/products">
          Products
        </ion-item>
        <ion-item menu-close href="#">
          Basket
        </ion-item>
      </ion-list>
    </ion-content>
  </ion-side-menu>
</ion-side-menus>

In the preceding code, we replaced the old reference to different template files with the more recent ones, which reflect our most recent changes.

Following this, we will proceed and modify the product.html file to to give our application a more product-like appearance. In addition to this, this page will also include an image placeholder, Product Description, Price, and a rudimentary Add to Basket button. In future iterations of the application, this will allow users to add a product to a virtual shopping basket when they wish to buy the necessary items. We will replace the existing code in product.html with the following:

<ion-view view-title="Product">
  <ion-content>
    <h1>Product</h1>
    <img src="http://loremflickr.com/380/160/fruits,vegetables">
    <br>
      <p>Product Description</p>
    <br>
      <p>Price</p>
    <button class="button button-balanced">
      Add to Basket
    </button>
  </ion-content>
</ion-view>

In the final step of modifying the HTML files, we will need to modify the products.html file to show the product title and product image using AngularJS. Replace the existing code with the following:

<ion-view view-title="The Grocer Shop">
  <ion-content>
    <ion-list>
      <ion-item ng-repeat="product in products">
        <a class="item item-thumbnail-left" href="#/app/products/{{product.id}}">
          <img src={{product.image}}>
          <h2>{{product.title}}</h2>
          <p>EUR {{product.price}} per kilogram</p>
        </a>
      </ion-item>
    </ion-list>
  </ion-content>
</ion-view>

In the aforementioned code, we extracted the product.image and product.title declared in app.js and reproduced it in the ion-view tag. We also personalized it and included the currency and how much the product costs per kilogram.

Setting up the product API

What we have implemented until now is a very simplified version of what we would like to achieve. Since we want to create projects that use MongoDB, Node.js and Ionic, we should take the opportunity to create an application that connects to our locally stored backend with a view of using this knowledge to connect to Internet-based servers powered by Node.js and MongoDB.

In order to take advantage of this section, you will need to follow the instructions available in Chapter 3, Creating an API, that are required to set up your very own Node.js server and include a basic set of data.

Once you've performed all the necessary steps, go ahead and find out what the current entries on our server are by first running the mongodb database. We will do this by first navigating to the order_api folder and running the following command:

sudo mongod

We shall start the Node.js server in our terminal by using the following command:

node api.js

If you adhered to the instructions given in Chapter 3, Creating an API, the following message will appear:

Up, running and ready for action!

At this point, we will open the installed REST client and pass the following command:

http://localhost:8080/api/products

If you have a response similar to the one as follows, then you should consider your attempt at creating a server to be successful:

[
  {
    "_id": "55be0d021259c5a6dc955289",
    "name": "Apple",
    "price": 2.5
  },
  {
    "_id": "55be0d541259c5a6dc95528a",
    "name": "Oranges",
    "price": 1.5
  },
  {
    "_id": "55be0d6c1259c5a6dc95528b",
    "name": "Pear",
    "price": 3
  },
  {
    "_id": "55be0d6c1259c5a6dc95528c",
    "name": "Orange",
    "price": 3
  }
]

Connecting the product API to our Ionic app

Once you have managed to get a response from the server and have the server and database up and running, you need to replace the existing array in the app.js file with the one from the local host.

Since the web server is based locally, you will need to enable cross-origin resource sharing, which is currently attainable in the easiest way through Google Chrome and by enabling the CORS (cross-origin Resource sharing) Chrome extension, which is available at https://goo.gl/oQNhwh. The extension is also available at the Chrome Web Store if you look for Allow-Control-Allow-Origin: *.

We will first start off our project by navigating to the ionic.project file, which is available in the root folder, and adding the following code to ionic.project:

"proxies": [
    {
      "path": "/api",
      "proxyUrl": "http://cors.api.com/api"
    }
  ]

The http://cors.api.com/api URL here acts as a placeholder URL in order to enable local development and cross-origin resource sharing.

This modification will help us add a proxy URL, which will allow cross-origin resource sharing.

We will also modify the gulpfile.js file by adding two variables and two tasks, as follows:

var replace = require('replace');
var replaceFiles = ['./www/js/app.js'];

gulp.task('add-proxy', function() {
  return replace({
    regex: "http://cors.api.com/api",
    replacement: "http://localhost:8080/api",
    paths: replaceFiles,
    recursive: false,
    silent: false
  });
})

gulp.task('remove-proxy', function() {
  return replace({
    regex: "http://localhost:8080/api",
    replacement: "http://cors.api.com/api",
    paths: replaceFiles,
    recursive: false,
    silent: false
  });
})

To make sure that the gulpfile functions correctly, we encourage you to make sure that gulp is installed correctly by running the following command:

sudo npm install gulp -g

Using gulp, we will also need to install replace. This is a gulp dependency, which will allow us to add the proxy functionality to the project by allowing for string replacement. This can be enabled by running the following command:

sudo npm install --save replace

In order to facilitate cross-origin resource sharing in Ionic, we will also need to use a factory method, which will be done by creating a new JavaScript file entitled services in the www/js folder, which contains the following code:

angular.module('starter.services', [])
factory('Api', function($http, ApiEndpoint) {
  console.log('ApiEndpoint', ApiEndpoint);

  var getApiData = function() {
    return $http.get(ApiEndpoint.url + '/products');
  };

  return {
    getApiData: getApiData
  };
})

In order to create the preceding code, we will need to reference services.js in the index.html file and app.js file. We will add the following code to the index.html head tag:

<script src="js/services.js"></script>

In addition to this, we will update the app.js file to include our new constant, which has already been referenced in the services.js file. This will be updated as follows:

angular.module('starter', ['ionic', 'starter.controllers','starter.services'])

.constant('ApiEndpoint', {
  url: 'http://localhost:8080/api'
})

Note

In order to facilitate your coding experience, we uploaded all our code to the GitHub repository, which is available at https://github.com/stefanbuttigieg/nodejs-ionic-mongodb/tree/master/chapter-14.

The connection of our locally created REST API to our Angular controller will be made available to the user by updating the product controller entitled ProductsCtrl. The code needs to be updated as follows:

.controller('ProductsCtrl', function($scope, Api) {
  $scope.products = null;
  Api.getApiData().then(function(result) {
          $scope.products = result.data;
  });
})

This code modification removes the JSON array and replaces it with code that extracts data from the JSON available on the local web server and makes it available in our controller. The finishing touch has to be implemented through the products.html file. Here, we will update the file to contain a generic image placeholder. We will make slight modifications to the products.html file to make it work with our very own JSON file:

<ion-view view-title="The Grocer Shop">
  <ion-content>
    <ion-list>
      <ion-item ng-repeat="product in products">
        <a class="item item-thumbnail-left" href="#/app/products/{{product.id}}">
          <img src="http://placehold.it/30x30">
          <h2>{{product.name}}</h2>
          <p>EUR {{product.price}} per kilogram</p>
        </a>
      </ion-item>
    </ion-list>
  </ion-content>
</ion-view>

Once the preceding code is implemented, feel free to navigate to the root folder of the grocerApp software and run the following command:

ionic serve --lab

The final app should look like this:

Connecting the product API to our Ionic app
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.178.9