![]() |
Ionic is build on Angular and I will assume you are at least moderately familiar with Angular and the basics of web applications. If you need some help with Angular, I recommend reading up from Todd Motto's post AngularJS Tutorial: A Comprehensive 10,000 Word Guide. It is also assumed you have NodeJS installed.
During this guide you will learn how to build a stock tracking app. You can preview the completed app here and see the whole project on GitHub at gnomeontherun/ionic-definitive-guide. You can resize the browser to see how it would appear on mobile, or if you are using Chrome you can use the device emulator feature.
Ionic, the missing hybrid app SDK
Ionic is built for hybrid apps, which are mobile apps that are written with HTML, CSS, and JavaScript instead of the native platform languages (Java for Android, Swift for iOS). When building a native app, you have access to the SDK which includes interface components such as tabs and complex lists. These are the interface controls that you are familiar with from using mobile apps, and Ionic provides a comprehensive set of components for building hybrid apps.
However, Ionic is really more than just interface components. It also:
- provides a fantastic CLI utility for managing projects.
- leverages SASS to easily customize components.
- is built and maintained by a professional team, with a strong community behind it.
- incorporates a pluggable architecture for including 'ions' (additional components and features).
- has a large set of icons.
Setup for Ionic
First things first, we need to get Ionic setup. For this tutorial we will be previewing in a browser, not on a mobile device (though you could if you follow the Ionic guide for details on emulating and loading to a device). You need to have Node installed on your system before you can install Ionic (Note: io.js may not work properly). Run this command in the terminal/command line prompt:
- $ npm install -g ionic
Ionic components & services
Before we jump into building our app, I wanted to give you a quick overview of Ionic's primary features. Ionic provides two primary features: components and services.
Ionic Components
Components are the user interface elements you declare using markup and CSS classes such as tabs, headers, slideshows, side menus, and more. These components either just CSS classes (like CSS frameworks like Bootstrap) or Angular directives. Some of the CSS components (input, card, button) don't provide additional features, but Ionic provides nicer styling that works well on mobile. The directive components (sidemenu, list, slidebox) are available as HTML tags.
- <!-- Card: CSS Component Example -->
- <div class="list card">
- <div class="item">Basic card!</div>
- </div>
- <!-- SlideBox: Directive Component Example -->
- <ion-slide-box slide-interval="10000" does-continue="true">
- <ion-slide>Slide 1</ion-slide>
- <ion-slide>Slide 2</ion-slide>
- </ion-slide-box>
Ionic Services
Services are programmatic user interface elements that are declared in JavaScript, and are provided using Angular's services architecture. These are typically used in your controllers, and provide interface elements that have a limited display time (such as modals, popups, loaders). Just like Angular services, Ionic services all start with a $ and are very clearly named like you see in this example.
- function Controller($scope, $ionicSlideBoxDelegate) {
- $scope.next = function() {
- $ionicSlideBoxDelegate.next();
- }
- $scope.previous = function() {
- $ionicSlideBoxDelegate.previous();
- }
- }
- <button ng-click="next()">Next</button>
- <button ng-click="previous()">Previous</button>
- function Controller($timeout, $ionicLoading) {
- $ionicLoading.show({
- template: 'Loading'
- });
- $timeout(function() {
- $ionicLoading.hide();
- }, 2000);
- }
Starting the Ionic project
Let the fun begin! The first thing is to generate a new project. The Ionic CLI we installed before will help us do this.
- $ ionic start stocks https://github.com/ionic-in-action/starter
- $ cd stocks
- $ ionic serve
Setting up Sass for styling
Ionic comes with a very helpful feature for customizing the default components and color presets using Sass. It is also recommended that you write any custom styles in the same way to take advantage of the variables and auto-generation provided by Ionic.
Sass support is not enabled by default in a new project. The following command will setup your project with Sass support.
- $ ionic setup sass
This app needs some styling, so you'll need to replace the contents of scss/ionic.app.scss file with the following
- // Override variables
- $light: #eee;
- $lighter: #fff;
- $darker: #363636;
- $assertive: #B33F33;
- $balanced: #70AB23;
- $positive: #366091;
- // The path for our ionicons font files, relative to the built CSS in www/css
- $ionicons-font-path: "../lib/ionic/fonts" !default;
- // Include all of Ionic
- @import "www/lib/ionic/scss/ionic";
- // Dark theme for backgrounds.
- .view, .pane, .modal {
- background: $darker;
- }
- // Style the form inside of the footer bar
- .bar-search {
- padding: 0;
- form {
- display: block;
- width: 100%;
- }
- .item {
- padding: 3.75px 10px;
- }
- }
- // Make the item-dark style default by extending it back on top of item
- .item {
- @extend .item-dark;
- }
- //
- .item-reorder .button.icon {
- color: $light;
- }
- // Make inputs nicer on dark
- .item-input {
- input {
- margin-right: 30px;
- padding-left: 5px;
- background: $darker;
- color: $light;
- }
- .input-label {
- color: $light;
- }
- }
- .item-input-wrapper {
- background: $darker;
- input {
- color: $lighter;
- }
- }
- // Make toggler nicer on dark
- .toggle .track {
- background-color: $dark;
- border-color: $darker;
- }
- .toggle input:checked + .track {
- background-color: $positive;
- border-color: $positive;
- }
- // Remove a bottom border
- .tabs-striped .tabs {
- border-bottom: 0;
- }
- // Allow the tabs to be as wide as needed
- .tab-item {
- max-width: none;
- }
- // Styles for the quote component
- .quote {
- background: $darker;
- padding: 5px;
- border-radius: 4px;
- display: block;
- position: absolute;
- top: 1px;
- right: 16px;
- text-align: center;
- width: 90px;
- height: 50px;
- color: $lighter;
- .spinner svg {
- margin-top: 6px;
- }
- &.positive {
- background: $balanced;
- color: $light;
- }
- &.negative {
- background: $assertive;
- color: $light;
- }
- .quote-change {
- font-size: 0.8em;
- color: $light;
- }
- }
This will setup all of the styles for the app. It is best to start a project setting up Sass in your project at the start, though you can do it anytime. Next you will start getting the base navigation setup.
Add Ionic's navigation components
Navigation is core to all apps, and Ionic provides several components that can be useful for navigation. In this example, you will use the ionTabs and ionNavView components to have tabs at the bottom to navigate between views. The ionSideMenus component is often used as well to expose a list of links for navigation.
Ionic is built using the popular ui-router project, which is an enhanced replacement for Angular's core ngRoute component. Ionic adds another layer of enhancements on top of ui-router, which is baked into the Ionic components and services. It leverages the idea of declaring states, which is a place in the app that describes the associated controller, view, template, and possibly other details. It will become more clear as we see some examples.
The ionNavView component is typically the center of an Ionic app's navigation, and works with several other components to allow you to craft intuitive navigation. Open up the www/index.html file, and update the body of the HTML file with the following.
- <body ng-app="App">
- <!-- The ionNavBar updates the title and buttons as the application state changes -->
- <ion-nav-bar class="bar-positive">
- <!-- The ionNavBackButton knows when to show or hide based on current state -->
- <ion-nav-back-button></ion-nav-back-button>
- </ion-nav-bar>
- <!-- Primary ionNavView which will load the views -->
- <ion-nav-view></ion-nav-view>
- </body>
Now if you save these changes and look at the browser, you'll now see a blue navbar along the top. The ionNavBar is gray by default, but with the class bar-positive added it adopts a new color. There is a set of color presets that many components can adopt, and you'll see them sprinkled in throughout the example.
This app isn't very impressive yet, because we haven't defined any states to actually load (hence the blank screen). Let's get the first state setup.
Add the tabs state
It is time to add the tabs state's template. You will declare the template which will contain the tabs component with two tabs for the tabs.quotes and tabs.portfolio states. You'll need to create a new file at www/views/tabs/tabs.html and add the following markup.
- <!-- ionTabs wraps the ionTab directives -->
- <ion-tabs class="tabs-icon-top tabs-dark tabs-striped">
- <!-- Quotes tab -->
- <ion-tab title="Quotes" icon-on="ion-ios-pulse-strong" icon-off="ion-ios-pulse" ui-sref="tabs.quotes">
- <!-- ionNavView for the quotes tab -->
- <ion-nav-view name="quotes"></ion-nav-view>
- </ion-tab>
- <!-- Portfolio tab -->
- <ion-tab title="Portfolio" icon-on="ion-ios-paper" icon-off="ion-ios-paper-outline" ui-sref="tabs.portfolio">
- <!-- ionNavView for the portfolio tab -->
- <ion-nav-view name="portfolio"></ion-nav-view>
- </ion-tab>
- </ion-tabs>
Now create www/views/tabs/tabs.js and add the following JavaScript that declares the 'tabs' state. Be sure to also add a script tag to the index.html file after the app.js file to load this file.
- angular.module('App')
- .config(function($stateProvider) {
- $stateProvider
- .state('tabs', {
- abstract: true,
- url: '/tabs',
- templateUrl: 'views/tabs/tabs.html'
- });
- });
Sadly, yet again, the screen is blank. Remember, the tabs view is abstract so you can only see it when you navigate to a child tab state. That means the next step is to create the first child tab state, so the tabs will appear and some very interesting things will start to happen.
Add the services
But wait! You will need some Angular services to help manage data for this app, and I don't want to spend a lot of time on them. You can look through the comments to see how they work, and they should be familiar to Angular developers. The first is a simple service to help manage data in localStorage, and the second is a service to load stock quotes from Yahoo! Finance. If you are not familiar with Angular and creating services, it is best to take a moment and review the Angular services documentation.
First create the file www/js/localstorage.js with the content in the code below. Be sure to add a script tag to index.html.
- angular.module('App')
- .factory('LocalStorageService', function() {
- // Helper methods to manage an array of data through localstorage
- return {
- // This pulls out an item from localstorage and tries to parse it as JSON strings
- get: function LocalStorageServiceGet(key, defaultValue) {
- var stored = localStorage.getItem(key);
- try {
- stored = angular.fromJson(stored);
- } catch(error) {
- stored = null;
- }
- if (defaultValue && stored === null) {
- stored = defaultValue;
- }
- return stored;
- },
- // This stores data into localstorage, but converts values to a JSON string first
- update: function LocalStorageServiceUpdate(key, value) {
- if (value) {
- localStorage.setItem(key, angular.toJson(value));
- }
- },
- // This will remove a key from localstorage
- clear: function LocalStorageServiceClear(key) {
- localStorage.removeItem(key);
- }
- };
- });
- angular.module('App')
- .factory('QuotesService', function($q, $http) {
- // Create a quotes service to simplify how to load data from Yahoo Finance
- var QuotesService = {};
- QuotesService.get = function(symbols) {
- // Convert the symbols array into the format required for YQL
- symbols = symbols.map(function(symbol) {
- return "'" + symbol.toUpperCase() + "'";
- });
- // Create a new deferred object
- var defer = $q.defer();
- // Make the http request
- $http.get('https://query.yahooapis.com/v1/public/yql?q=select * from yahoo.finance.quotes where symbol in (' + symbols.join(',') + ')&format=json&env=http://datatables.org/alltables.env').success(function(quotes) {
- // The API is funny, if only one result is returned it is an object, multiple results are an array. This forces it to be an array for consistency
- if (quotes.query.count === 1) {
- quotes.query.results.quote = [quotes.query.results.quote];
- }
- // Resolve the promise with the data
- defer.resolve(quotes.query.results.quote);
- }).error(function(error) {
- // If an error occurs, reject the promise with the error
- defer.reject(error);
- });
- // Return the promise
- return defer.promise;
- };
- return QuotesService;
- });
(continue)
If you found this post interesting, follow and support us.
Suggest for you:
Android Application Programming - Build 20+ Android Apps
The Complete Android Developer Course: Beginner To Advanced!
Android: From Beginner to Paid Professional
The Complete Android Developer Course - Build 14 Apps
Python For Android Hacking Crash Course: Trojan Perspective
No comments:
Post a Comment