Chapter 1.Hybrid Mobile Apps
Mobile application development is becoming one of the most important skills that a developer can possess. Over the past decade, we have seen an explosion of mobile devices—phones, tablets, and now wearables—that have given rise to a whole ecosystem of mobile applications. We are now living in an age of mobile apps. But learning how to create them is still a challenge. Typically, a developer will need to learn and master each platform’s specific development language: Objective-C or Swift if you are creating iOS-based applications, or Java if you are creating Android-based applications. Wouldn’t it be nice if there were a solution that allowed for one shared language that we could use across multiple platforms? There is: by leveraging the shared language of the web and some incredible frameworks, developers can now develop their applications in one code base and deploy it to a wide range of mobile platforms. This is known as a hybrid mobile application because it blends the native capabilities of the mobile device with the ability to develop using web technologies.
What exactly is a hybrid mobile application? Unlike traditional native mobile apps that are built using the device’s native development language. Hybrid apps are built with web technologies (HTML, CSS, and JavaScript) instead. In fact, you probably have more than one hybrid app installed on your mobile device right now.
The Ionic Framework is one of the most popular hybrid mobile application frameworks in use today. The framework has over 30,000 stars on GitHub and has been forked over 8,000 times. With the release of the next major version of the framework, it is poised to continue its growth as the go-to solution for hybrid mobile developers.
This book presents the foundations required to build Ionic applications by guiding you through the process of creating three separate applications. Each of these applications will give you insight into the various components available in the Ionic Framework, as well as an understanding of the Ionic ecosystem. Before we get into creating our first application, we need to make sure we have a good understanding of the various foundations that Ionic is built upon, as well as some of the tooling we will be using throughout this book.
What Is the Ionic Framework?
So what exactly is the Ionic Framework? Simply put, it is a user interface framework built with HTML, CSS, and JavaScript for use with hybrid mobile application development. Beyond just the user interface components, the Ionic Framework has expanded to include a robust command-line interface (CLI) and a suite of additional services such as Ionic View and Ionic Creator. We will explore each of these throughout the book.
Ionic is really a combination of several technologies that work together to make building mobile applications faster and easier. The top layer of this stack is the Ionic Framework itself, providing the user interface layer of the application. Just beneath that is Angular (formally known as AngularJS), an incredibly powerful web application framework. These frameworks then sit on top of Apache Cordova, which allows for the web application to utilize the device’s native capabilities and become a native application.
The combination of these technologies enables Ionic to deliver a robust platform for creating hybrid applications. Each of these technologies will be explored further in this book.
What’s New in Ionic?
To say the Ionic Framework underwent a major upgrade after version 1 is almost an understatement. Not only did the Ionic Framework itself evolve significantly, but one of its underlying technologies, Angular, did as well. Although some things might look the same on the surface, under the hood, there are radical changes. Ionic is almost a new framework. If you are familiar with Ionic 1, much of the component syntax will appear similar, but the code that brings them to life will be new.
IONIC VERSION 3
In March 2017, Ionic announced version 3 of the framework. This new version is more like a traditional upgrade, and not the radical change that occurred from Ionic 1 to Ionic 2. The company also announced that going forward, the framework will just be referred to as Ionic, without the version number. For clarity, in this book, we will only append a version number to Ionic to highlight something to you.
The following are some of the major improvements to the framework:
Overhauled navigation
Completely control the navigation experience of your app without being tied to the URL bar. Navigate to any page inside of any view, including modals, side menus, and other view containers, while maintaining full deep-linking capability.
Native support
There is now more native functionality directly into Ionic, making it easy to take advantage of the full power of the device without hunting down external plug-ins and code.
Powerful theming
With the new theming system, it’s easy to instantly match your brand colors and design.
Material Design
Full Material Design support for Android apps.
Windows Universal apps
Support for developing applications that will run on the Windows Universal platform.
But with these improvements to Ionic comes the added effort of learning the new version of Angular, as well as learning TypeScript. We will touch on these requirements in a later chapter.
Comparing Mobile Solutions
When needing to deliver your application to a mobile platform, there are three primary solutions that are available, each with its own strengths and weaknesses. They can be grouped into native mobile applications, mobile web applications, and hybrid mobile applications. We’ll look at each solution in a bit more detail to understand the overall mobile application landscape.
Native Mobile Applications
Typically, native code is the solution most developers think of when they need to create a mobile application. To build a native application, developers need to write in the default language for each targeted mobile platform, which is Objective-C or Swift for iOS devices, Java for Android, and C# or XAML for Windows Universal.
This type of development comes with several strong advantages over the other options. First, the development tools are tightly integrated into the device platform. Developers are able to work in IDEs that are configured to create mobile applications for that platform: Xcode for iOS, and Android Studio for Android. Second, since development is done in the native framework, all the native APIs and features are available to the developer without the need of additional bridge solutions. The third advantage is the performance of the application will be as good as possible. Since the application is running natively, there are no intermediate layers of code that can affect performance.
The primary disadvantage of native mobile application development centers around development language issues. Since quite often you will want to release your application for both iOS and Android (and possibly Windows), you will need to have proficiency in all the different languages and APIs. None of the client-side code can be reused, and it, therefore, must be rewritten. In addition, there is the technical burden of maintaining multiple code bases.
Mobile Web Applications
When the iPhone was first announced, there were no third-party applications—or even an App Store, for that matter. In fact, the initial vision was that third-party applications were only to be available as mobile web applications and not as native applications. While this is certainly not the case today, creating a mobile web app is still an option. These apps are loaded via the device’s mobile web browser. Although the line between a mobile website and mobile app can become blurred, this option is really just about creating your application using web technologies and delivering it through the device’s browser.
One of the advantages of this solution is that we can have a much wider reach with our application. Beyond iOS and Android, additional mobile platforms become available. Depending on the market that you are targeting, this may be a critical factor. Since you have direct access to your web server, the application approval process that can be tricky or slow at times for native apps is not an issue. Updating your application to add a new feature or resolve a bug is as simple as uploading new content to the server.
However, the fact that these applications run inside the native browser brings along a set of limitations. First, the browser does not have access to the full capabilities of the device. For example, there is no ability for the browser to access the contact list on the device. Second is the discoverability of the application. Users are used to going to their device’s app store and finding the app. Going to the browser and inputting a URL is not common behavior.
Hybrid Mobile Applications
A hybrid application is a native mobile application that uses a chromeless web browser (often called aWebView) to run the web application. This solution uses a native application wrapper that interacts between the native device and the WebView. Hybrid apps have a number of advantages. Like mobile web applications, the majority of the code can be deployed to multiple platforms. By developing in a common language, maintaining the code base is easier, and if you are a web developer there is no need to learn a completely new programming language. Unlike mobile web applications, we have full access to the device’s features, usually through some form of a plug-in system.
However, this solution does have some real disadvantages. Since the application is still just a web app, it is limited by the performance and capabilities of the browser on the device. The performance can vary widely. Older devices often had very poor performing mobile browsers, meaning the app’s performance was less than ideal. Although this solution is a native application, communication between the WebView and the device’s native features is done via plug-ins. This introduces another dependency in your project and no guarantee that the API will be available through this method. Finally, the other native user interface components are not available within the WebView. Your application’s entire UI/UX will be completely written by you.
The Ionic Framework takes the hybrid app approach. The team at Ionic has taken great care in recreating web-based UI components that look and feel like their native counterparts. With the framework leveraging Cordova and its plug-in library, the lack of access to the device’s capabilities are solved.
Understanding the Ionic Stack
Now that we have a general understanding of the types of mobile application development, let’s look a bit deeper into how the Ionic Framework works. Ionic applications are built as part of three layers of technology: Ionic, Angular, and Cordova.
Ionic Framework
The Ionic Framework was first launched in November 2013, and its popularity has quickly grown and continues to increase. Ionic is provided under the MIT license and is available at theIonic Framework website.
The primary feature of the Ionic Framework is to provide the user interface components that are not available to web-based application development. For example, a tab bar is a common UI component found in many mobile applications. But this component does not exist as a native HTML element. The Ionic Framework extends the HTML library to create one. These components are built with a combination of HTML, CSS, and JavaScript, and each behaves and looks like the native controls it is recreating.
Ionic also has a CLI tool that makes creating, building, and deploying Ionic applications much easier. We will be making extensive use of it throughout this book.
The Ionic platform also extends to several add-on services. These include an online GUI builder to visually lay out the interface of your Ionic applications and packaging and updating solutions. Although these Ionic services all have free developer access to test and develop with, any production use will require a monthly charge.
The main focus of the Ionic Framework is in the user interface layer and its integration with both Angular and Cordova to provide native-like experiences.
Angular
The next part of the Ionic stack is Angular (formally known as AngularJS), an open source project primarily supported by Google. Since its release in 2009, Angular has become one of the more popular web application frameworks. The goal of Angular is to provide an MVW (model-view-whatever) framework to build complex, single-page web applications. The Ionic team decided to leverage the power that this framework offers, so they built upon. For example, Ionic’s custom UI components are just Angular components. Angular is licensed under the MIT license and is available at theAngular website.
With the release of Angular 2, the framework has changed massively. This change did cause some discord within the Angular community, but many of the concerns about the new aspects of the framework have been addressed. We will explore Angular in more detail inChapter 4.
Cordova
The final element of the Ionic stack is Apache Cordova. Cordova was originally developed by Nitobi Software in 2009 as an open-source solution to build native applications using web technologies via an embedded WebView. In 2011, when Adobe Systems bought Nitobi—and along with it the PhoneGap name—the project had to be renamed. Although the project was always open source, the name was not. The open source version was eventually named Cordova (after the street where the Nitobi offices were located). As Brian Leroux, one of the founders of PhoneGap, put it: “PhoneGap is powered by Cordova. Think: Webkit to Safari.” Adobe continues to be a major contributor to Cordova (along with several other major software companies) and it is licensed under the Apache 2.0 license.
Cordova provides the interface between the WebView and the device’s native layer. The library provides a framework to bridge the gap between the two technology stacks (hence the original name of PhoneGap). Much of the functionality is handled through a system of plug-in modules, which allows the core library to be smaller. Beyond working on the two primary mobile platforms, Cordova is used on a much wider range of mobile platforms, such as Windows Phone, Blackberry, and FireOS. For a full list, seehttps://cordova.apache.org.
Beyond the library, Cordova as has its own command-line tool to assist in scaffolding, building, and deploying your mobile applications. The Ionic CLI is built atop the Cordova CLI, and we will be making use of it throughout this book.
Prerequisites for Ionic Application Development
In order to develop Ionic applications, you will need to have some additional technical skills that are not covered in this book. While you do not need to be an expert in these skills, you will need a general knowledge in order understand the concepts of Ionic development:
Understanding HTML, CSS, and JavaScript
Since Ionic applications are built using HTML, CSS, and JavaScript, you should have a fundamental understanding of how these technologies combine to build web applications. We will be using HTML to create the foundational structure of our applications. Our CSS will provide the visual styling for our applications. Finally, JavaScript will provide the logic and flow for the applications.
While we will work a modest amount with JavaScript, you will need to be familiar with its syntax and concepts like variable scoping, asynchronous calls, and events.
Understanding Angular
Beyond understanding basic HTML, CSS, and JavaScript, you will need some understanding of building web applications. In this book, we will be writing our applications with JavaScript, specifically Angular 2. This means we will be developing in ES6 and writing the code in TypeScript. For many, this is probably something that is new to you. We will cover the basics inChapter 4to get you up and running.
Access to a mobile device
It goes without saying, you are going to need an actual mobile device to install and test your applications on. In fact, you will probably need at least one device for each platform you plan to develop for. While both the iOS and Android SDKs provide emulators/simulators that allow you to see what your app looks like and functions, they are no substitute for testing on a real device.
Summary
Hopefully, now you have a better understanding of the difference between the types of mobile application solutions and how the Ionic stack is composed. In addition, you should have a clearer picture of the elements needed for Ionic development.
In the next chapter, we will demonstrate how to set up your computer to develop Ionic applications.
Chapter 2.Setting Up Our Development Environment
One of the initial challenges in developing with the Ionic Framework is the installation and setup of the several tools that Ionic requires. In this chapter, we will walk you through the process of installing all the necessary components and configurations for developing Ionic applications. The installation process can be broken down into to two main parts: the base Ionic installation, and the platform-specific SDK installations. The base installation will cover just the tools that you need to generate your first Ionic application and preview it in your browser. If you want to dive right in and start developing with Ionic, then this is all you will need to do. The second portion of the installation is about setting up your native development environment(s). Even though we are building our apps with web technologies, we will still need to have the native development environments installed on our computers. This will give us access to the emulators, as well as the ability to deploy and test the applications on our devices, and eventually submit them to the app stores.
Throughout this book, we will be using the command line to use the Ionic CLI. On macOS, we will be using the Terminal application. We recommend adding either a shortcut on the desktop or adding it to your Dock. If you are developing on a PC, I personally recommend using Git Bash (which can be installed when we install Git) instead of the default command prompt. Its command syntax is the same as in macOS, so following along with the code samples should be easier.
Installing the Ionic Framework
This section we will get the essential Ionic development environment set up, then generate our first Ionic application and preview it in our browser. You may be wondering why we want to preview our application in a browser. Remember, we are writing our application with web technologies, so it makes sense to target a browser as our first “platform.” We can leverage browser debugging tools and iterate through our development more quickly. My personal development cycle is to try to stay away from testing on a mobile device until I need to.
There are four components we need to install; inTable 2-1, you can see the software we need to get started along with their corresponding URLs.
Tool | URL |
Node.js | nodejs.org |
Git | git-scm.com |
Ionic | ionicframework.com |
Apache Cordova | cordova.apache.org |
Installing Node.js
The foundation for Ionic is built atop Node.js (often referred to simply as Node). Node is a platform that enables you to run JavaScript outside the browser. This has enabled developers to create applications and solutions that are written in JavaScript and can be run almost anywhere. Both the Ionic and Cordova CLIs are written using Node. Because of this requirement, we need this framework installed first.
To install Node, go toNode websiteand download the installer for your development platform. If you already have Node 6.X installed, you can skip this step. You will want to use the 6.X version of Node. If you have an additional need to use a later version of Node, you might want to look atNode Version Managerto allow you to easily switch between node versions.
Once Node has been installed, open the Terminal and enternode -v
. This command tells Node to report back the currently installed version:
$ node -v
$ v6.11.0
If you encounter an issue with the installation, review the documentation.
You should also make sure that npm—a package manager for node modules is up to date (note: npm actually does not stand for “node package manager”). When you install Node.js this is automatically done for you. But if you want to check which version of npm you installed:
$ npm -v
$ 3.10.10
If you need to update your installation of npm, the command is:
$ npm install npm -g
With Node and npm successfully installed, we will now install Git.
Installing Git
While you are free to choose any version control solution (Perforce, SourceSafe, or Git), the Ionic CLI leverages Git for the management of templates. In addition, I have found that for Windows users, using Git Bash makes it easier to follow along with the examples in this book.
Go tohttp://git-scm.com, and click the Download button. Go ahead and open the package file and follow the default installation.
Once the installation is complete, launch the Terminal window and verify it.
In Terminal, typegit --version
and press Enter:
$ git --version
$ git version 2.8.4 (Apple Git-73)
With Git now installed on our system, we can install the Apache Cordova CLI.
Installing the Apache Cordova CLI
Although we can install both Cordova and Ionic at the same time, I recommend installing each one individually in case there is an issue during the installation process.
The installation of Cordova CLI uses the Node package manager (npm) to perform the installation. To install it, open either your Terminal window or Git Bash, and enter the following command:
$ npm install -g cordova
Depending on your internet connection, this can take a while. For macOS users, you may encounter an issue with permissions during the installation. There are two options: rerun thenpm
command, but preface it with the sudo command. This will allow the node modules to run as the root user. Alternatively, you canconfigure your systemto solve this permission problem:
$ cordova -v
$ 7.0.1
With these tools in place, we can finally install the Ionic CLI on to our system.
Installing Ionic CLI
Just like the installation of the Cordova CLI, the Ionic CLI is also installed vianpm
. In your Terminal window, enter the following command:
$ npm install -g ionic
This install will also take some time to complete. Once the Ionic CLI has completed its installation, we will again check it by issuing theionic –v
command in our terminal:
$ ionic -v
$ 3.4.0
Now we have our base installation in place for Ionic development. However, we eventually will want to test our applications either in a device emulator or on an actual device. We will take a look at the installation of these tools shortly. But first, let’s set up a sample app and see how to preview it in our browser.
Starting a New Ionic Project
The Ionic CLI provides an easy command to enable you to set up an Ionic project:ionic start
. This CLI command will generate a basic Ionic application in the active directory. The Ionic Framework can scaffold this project via a collection of starter templates. These can come from a named template, a GitHub repo, a Codepen, or even a local directory. The named templates areblank,sidemenu, andtabs. We will explore those later in this book. For now, run the following command to create an Ionic project:
$ ionic start testApp
Since we did not define a starter template, the Ionic CLI will now present a list of starter templates that we can pick from. Select the tabs option, and press enter. The CLI will now begin the process of downloading the template and configuring the various components. It may ask you if you wish to create an Ionic.io account. For now, we can ignore this, but we will be exploring the Ionic services later in this book. Once the process is completed, we need to change the working directory to the_testApp_directory that the CLI generated:
$ cd testApp
Let’s take a quick look at the elements that were installed in this directory.
Ionic Project Folder Structure
The project directory contains quite a number of files and additional directories. Let’s take a moment to understand each item and its role:
src | This directory will contain the actual application code that we will be developing. |
---|---|
hooks | This directory contains scripts that are used by Cordova during the build process. |
node_modules | Ionic now uses npm as its module management system. The supporting libraries can be found here. |
resources | The default icons and splash screens for both iOS and Android are included. |
platforms | This directory contains the specific build elements for each installed build platform. This directory will be added once a platform is installed. |
plugins | This directory contains Cordova plug-ins. |
www | This directory contains the_index.html_that will bootstrap our Ionic application with the transpiled output from the_app_directory. |
.gitignore | A default gitignore file is generated. |
config.xml | Used by Cordova to define various app-specific elements. |
ionic.config.json | Used by the Ionic CLI to define various settings when executing commands. |
package.json | A list of all the npm packages that have been installed for the project. |
tsconfig.json | The_tsconfig.json_file specifies the root files and the compiler options required to compile the project. |
tslint.json | TypeScript linter rules. |
This is the standard structure of any Ionic project. As we add platforms and plug-ins, additional subdirectories and files will be created.
HIDDEN FILES
Any file starting with a dot on macOS will not be visible in Finder.
CHANGES FROM IONIC 1
If you have used Ionic 1, there are a number of changes that you might want to be aware of. First, Ionic is no longer using Bower for its package management. Instead, this is now handled through node modules. But the biggest difference is instead of writing your app directly within the_www_directory, your development is now done in the_src_directory.
We will explore the various elements in the project folder in a later chapter. For now, let’s just test previewing our application in a browser and ensure that we have a working development environment. For more information on migrating from Ionic 1, seeAppendix A.
PREVIEWING IN THE BROWSER
One of the advantages of building hybrid applications is that much of the development and testing can be done locally in the browser. In a traditional native application workflow, you would have to compile your application, then either run it in the emulator or go through the process of installing it on a device. The Ionic CLI has a built-in command to run the application locally in a browser. With the working directory still the one that was created by theionic start
command, enter the following command:ionic serve
. This will start a simple web server, open your browser, and load the application for us. It will also listen to changes and auto-refresh the browser whenever a file is saved.
SETTING THE PORT ADDRESS
In most cases,ionic serve
will prompt you to choose an IP address. You should usually just select the local host choice. If port 8100 is in use, you can select an alternate port by passing in the--p
flag followed by the port number you wish to use.
We should now see the starter tab Ionic application running in our browser.The Ionic tab template contains several screens, and we can navigate through them and explore some of the various components in the Ionic Framework (Figure 2-1).
Figure 2-1.Our Ionic tabs sample application
Since you are viewing your Ionic app in a browser, you can use all the developer tools that you normally use.
BROWSER OPTIONS
While you are free to use whichever browser you are comfortable with, I recommend sticking with Google Chrome. Although this is not exactly the same browser that your content will run in on your mobile devices, it is similar, and you will have fewer issues between the desktop testing and the mobile versions.
Platform Tools Installations
While we have a working development environment, eventually we will need to continue our development in emulators, and finally on-device. To do this we will need to install the native application platform tools. This section will be a bit more complex than the previous installation and specific to each platform we need to install. Thankfully, this is a one-time process; so give yourself time to complete this section.
Currently, Ionic officially supports iOS, Android, and Windows Universal.
iOS
If you plan to develop for iOS, you will need to use Xcode for both emulation and distribution of your app. Xcode is only available for Mac. While there are some solutions that sidestep the need for a Macintosh (PhoneGap Build and Ionic Package), I recommend having at least an entry-level Mac computer available for development.
To install Xcode, simply open the App Store and search for “Xcode”. The download is quite large (well over 3 GB), so make sure you have a good internet connection and disk space for installation.
Android
Unlike iOS, development for Android can be done on Windows, Mac, and Linux systems. Installation of the Android SDK can be done either via Android Studio or via the standalone SDK tools. If you want a complete IDE for Android, then download Android Studio, but we only need the SDK for our development. To download either option, go to theAndroid Developer website. Personally, we prefer to have the full IDE installed instead of just the SDK.
Installing the Android Studio or SDK will require the installation of the Java Development Kit as well. These additional installation instructions can be viewed on theAndroid Studio page.
Windows Universal
If you wish to build Windows Universal applications, you will have to do this on a Windows machine. Download and installVisual Studio 2015 Community Edition.
During the installation, select “Tools for Cross Platform Development” as well as the SDK for Windows Universal Apps.
Setting Emulators
With the base mobile SDKs installed, we can continue the installation process. For both iOS and Android development, we need to set up the appropriate device emulators. These emulators will allow you to run a virtual mobile device on your computer. We can use them to test our application quickly on various versions of an OS or device type without needing a physical device. They are slower to work with than directly testing in your browser but can enable the ability to test device specific features, such as working with the Contact database.
Emulators require some additional installation and configuration. Let’s look at the steps for each platform.
iOS
Technically, the iOS emulator is a simulator as it does not actually run the native OS, but rather simulates its execution. To install our iOS simulators, launch Xcode, then choose Preferences from the Xcode menu. In the Downloads tab, you will find a list of available simulators that can be installed. Please note that each simulator is over 1 GB is size, so make sure you have the disk space and internet connection for the download and installation. We typically only have the last two releases installed on our development machine.
Once this installation is complete, we also need to install the Command Line Tools for Xcode. From the Xcode menu, select Open Developer Tool, then the More Developer Tools option. Then locate the Command Line Tools for Xcode for your version of Xcode and download and install it.
The last piece to work with iOS simulator is to install the ios-sim node module. Open a terminal window and enter the following command:
$ npm install -g ios-sim
You might need to issue this command with sudo depending on your configuration.
The ios-sim tool is a command-line utility that launches an iOS application in Simulator.
Now we will be able to run our Ionic apps in the iOS simulator. We will look at this in just a bit.
Android
Before we can configure our Android emulator, we need to install and set up the SDK packages. If you are using the SDK only, run the following from the command line:
$ android sdk
This will launch the standalone SDK manager. This tool will allow you to download the platform files for any version of Android. Like, iOS we recommend only downloading the last two releases packages and tools.
You need to choose the following items:
Android Platform SDK for your targeted version of Android
Android Platform-Tools
Android SDK build-tools version 19.1.0 or higher
Android Support Repository (found under “Extras”)
If you are using Android Studio, from the welcome screen, select Configure, then choose SDK Manager. Then install the same components as the standalone option.
With the SDKs installed, along with the corresponding platform tools, we can now configure the Android emulator. While we can create and configure our virtual Android devices within Android Studio, you need to have an active project to do this. Rather, I suggest just using the command line to configure your virtual devices:
$ android avd
This will open the Android Virtual Device (AVD) Manager. Once it has launched, select the Device Definitions tab to choose a known device configuration. Select the Nexus 5 definition, then click the Create AVD button. A new window will open with a variety of configurations and additional details that you can set for your virtual device—screen size, which version of Android to run, etc. Once you are satisfied with your device, click OK to finish the process. You can have as many virtual devices as you would like.
ANDROID EMULATORS
The Android emulators are known to be slow to launch and use. This process has improved greatly in recent releases of the default emulator. However, you might want to look at an alternate solutionfromGenymotionfor your virtual Android needs.
Setting Up Your Devices
At some point, you will have to actually test your application on your mobile devices. Each platform has a different set of requirements for this.
iOS
While anyone can test their iOS app in the iOS simulator for free, you must be a paid member of the iOS Developer Program in order to test on a device. In the past, provisioning your iOS device for development was a complex process. Thankfully recent changes to Xcode have simplified this process.
First, directly connect your iOS device to your Mac. This process can not work via a wireless connection. Next, we need to create a temporary Xcode project. In Xcode, select New→Project from the File menu. The New Project assistant will open, then select the Single View Application choice. On the next screen, enter Demo as the Project Name, then click Next. The settings aren’t important because we are going to delete this project once we have configured the device. Select a location for the project, then click Create.
Xcode will now display the configuration window for our project. We now need to set the active scheme to our device. This is set via the Scheme control near the top-left of the Xcode window.
With your device unlocked and displaying its Home Screen, select it from the Scheme drop-down. You should have a warning that there is No Signing Identity Found. Instead of letting Xcode fix this issue, we should manually address it.
In the General settings, in the Identity panel, select your team’s name (which is probably just your name) from the drop-down list.
If you do not see your team’s name listed, you will need to add your team’s account to Xcode. To do this, select Add Account in the drop-down list. The Accounts preferences window will now open. Enter your Apple ID and password that is associated with your iOS Developer Program account, and click Add.
Once Xcode has finished logging you in and refreshing its list, close the Accounts window. Select your newly added team from the Team drop-down list.
Xcode will now display a new warning about No Matching Provisioning Profiles Found. Click the Fix Issue option and Xcode will resolve this issue.
In order to configure the provisioning profile, Xcode will need some additional information and permissions. You can just answer the question with the defaults.
Let’s validate that everything is configured correctly. Click the Run button, located in the top-left of the Xcode window, making sure that you have your iOS device selected as the target. After a few moments, this test app should launch on your device!
Now, to integrate this into our command-line tool chain, we need to install another node tool, ios-deploy. From the command line, enter the following command:
$ npm install -g ios-deploy
INSTALLATION ON EL CAPITAN
If you are running macOS 10.11 El Capitan, you may need to add the--unsafe-perm=true
flag when runningnpm install
or else it will fail. For more information on this issue seeGitHub.
For additional assistance, refer toApple’s documentation.
Android
Setting up an Android device is almost the complete opposite from setting up an iOS device. The first step is to enable developer mode on your device. Since each Android device’s user interface can vary, these are the general instructions:
- Open the Settings and scroll to the About Phone item.
- There should be a Build Number—you must tap it seven times to enable the developer mode. As you get closer to seven taps, the device should notify you how many taps are left.
- Once this is complete, you can go back to the Settings list and you’ll see a new Developer Options item.
If you encounter an issue enabling Developer Mode on your device, review the device’s user guide. Next, we need to enable USB debugging in order to deploy our apps. In the Developer Options screen, locate the USB debugging option and enable it.
Your Android device is now ready for development. You may be prompted with a dialog to confirm the pairing when you connect the device to the computer for the first time.
Adding Mobile Platforms
Although the Ionic CLI will scaffold much of our application, we might need to add in the target mobile platforms. In order to view our app in either the emulator or on-device, the corresponding platform must be installed. Open your terminal window, and make sure that your working directory is your Ionic project directory. The Ionic CLI command isionic cordova platform add [platform name]
.
IONIC CLI’S NAMESPACING
Starting Ionic CLI version 3, all commands that were using the Cordova CLI, have been namespaced to require the inclusion of cordova in the command. Ionic CLI’s Cordova functionality has been moved into a plug-in, which is installed by default with new Ionic projects and can be installed in existing Ionic projects with npm i --save @ionic/cli-plugin-cordova
.
To add the project files for Android:
$ ionic cordova platform add android
To add the project files for iOS:
$ ionic cordova
platform add ios
To add the project files for Windows:
$ ionic cordova platform add windows
By default, the iOS platform is added if you are running on a Mac, so you rarely need to install that platform manually. This command will generate all the needed files for each specific platform.
Previewing on Emulator
With a mobile platform added to our Ionic project, we can now verify that we can preview our app in the platform emulator. To run our app in an emulator, use the following command:
$ ionic cordova emulate [platform]
The Ionic CLI will begin building your app for use on that platform’s emulator. You will see a lot of output in the terminal as it goes through the process. Once it is finished, the emulator will automatically launch and run your application.
If you need to target a specific emulated device, append the command to include the--target
switch. For example, if I wanted to emulate an iPad Air, I would use:
$ ionic cordova emulate ios --target="iPad-Air"
For a list of iOS device types, use:
$ ios-sim showdevicetypes
For a list of Android devices, you will need to refer to the AVD Manager for the device names.
Once you already have the emulator up and running, you can run thecordova emulate
command again without closing the emulator. This is faster than exiting the emulator and relaunching it every time you change files because the emulator doesn’t have to reboot the OS each time.
The Ionic CLI has another very powerful feature that allows you to reload the app instantly using the live reload flag,--livereload
. This feature was a huge timesaver when working with emulators during our Ionic 1 development workflows. However, recent device security changes have currently disabled it, and it is not clear if a solution will be found.
You can also output the console logs to Terminal so you can read them more easily (see theIonic blog postabout this feature):
$ ionic cordova emulate ios -l -c
$ ionic cordova emulate android -l -c
Previewing on Device
Although the emulators do a fine job, eventually you will need to install your application on a physical device. The Ionic CLI makes it extremely easy to do so with thecordova run
command. In your terminal, enterionic cordova runplatform
.
The Ionic CLI will then begin the process of compiling the app for installation on your device. When it is finished, it will automatically install the app on the connected device. Be aware that each installation will overwrite the existing installation of the app.
For iOS deployment, you will also need the ios-deploy node module installed; otherwise, you will have to manually perform the installation via Xcode:
$ ionic cordova run ios -l -c
If you are developing for Android on a Windows machine, you might need to download and install the appropriate USB driver for your device. Check theAndroid Studio websiteto see if one is needed for your device. No additional drivers should be needed for macOS to deploy to an Android device:
$ ionic cordova
run android -l -c
If a device is not found, the Ionic CLI will then deploy your app to an emulator/simulator for that platform.
Summary
This chapter covered all the steps needed to set up your Ionic development environment. We built a first test app and previewed it locally in our browser, in an emulator, and finally on our device.
Chapter 3.Understanding the IonicCommand-Line Interface
One of the key tools that we will be using while developing our Ionic applications is theIonic command-line interface, or CLI. We touched briefly upon this tool during our initial setup, but this chapter will explore the various options this utility gives us.
First, if you have not installed the Ionic CLI, you can use npm to do so. If you are on a Macintosh, launch the Terminal application. For Windows users, launch Git Bash (or another command prompt). Then enter the following command:
$ npm install -g ionic
This will install the latest version of the Ionic CLI. The Ionic CLI is fully backward compatible with version 1 projects, which is helpful if you have already done some Ionic development.
NOTE
macOS users might need to prepend thenpm
command with sudo for the installations to work.
Once the installation of the Ionic CLI is complete, we can test its installation by building our first test application:
$ ionic start myApp [template name]
This command will create a new Ionic application in a new directory named_myApp_using the template that we pass to the command. Let’s explore the various template options that we can use.
Ionic currently has several starter templates. There are the original layout templates:blank,sidemenu, andtabs,_as well as several advanced templates:_super,conference,tutorial, andaws. If no template is passed as a parameter, then the CLI will prompt you to select an option.
Figure 3-1.The Ionic templates: blank, sidemenu, and tabs
Previously, the Ionic CLI allowed you to reference external templates by passing in a URL. This functional was disabled with the release of version 3 of the Ionic CLI. Another change was dropping the requirement to pass in the --v2
flag to generate an Ionic 2 application. By default, the Ionic CLI will alway generate the current version. If you need to generate an Ionic 1 application, you are now able to do so using the--type=ionic1
flag.
THE --TS FLAG
If you used earlier versions of Ionic 2, you might be familiar with the--ts
flag, which told the CLI to use TypeScript as the development language. Starting with beta 8, the decision was made to only support TypeScript. Thus, the need to include this flag was removed.
There are some additional command-line flags that you can pass to the command as well. By default, theionic start
command will take the name of the directory that is created and set that as the app’s name in the_config.xml_file. You are free to change this within_config.xml_at any time, but instead you can use either the–appname
or–n
flag followed by the actual application name. Since your appname will probably include spaces, your will need to use quotes around the name for this to work:
$ ionic start myApp -n "My Awesome Ionic App"
There are several other new flags that you might want to use when starting your new Ionic application. If you do not want to include any of the default dependencies when generating the application,pass in the --skip-dep
flag. By default, the Ionic CLI will now seed the starter for integration with Git. If you to override this functionality, use the --no-git
flag.Another new flag is the the --cordova
flag. Since the Ionic CLI has moved all the Cordova related functions into a sub-module, we need to install it if we are going to be working with Cordova. Don’t worry if you forget to pass in this flag, the Ionic CLI will prompt you to install it once you use a related command. You might be wondering why would we not want to include Cordova into our project—aren’t we building mobile applications and don’t we need to use Cordova as part of the process? Yes. However, you might want to use Ionic as the UI framework for a progressive web application, so you could avoid using Cordova. Another option might be using Ionic as the UI framework for anElectron-based desktop app. In either case, it is an option that is available if you need it.
Define Your Build Platforms
Once the base Ionic application has been scaffolded, we next need to add the target platform we will want to build for. The command to do this is:
$ ionic cordova platform add [
platform name
]
COMMON MISTAKE
If you try to run this command without changing your active directory into the project directory that was just created, you will get an error. Always remember to issuecd [app name]
before running any of the other Ionic CLI commands.
In the past, macOS users would have the iOS platform automatically added to the project. Starting with Ionic CLI 3, this automatic install has been removed. You will now need to manually install the iOS platform using this command:
$ ionic cordova platform add ios
To build for the Android platform, you will need to add it to the project:
$ ionic cordova platform add android
To build for the Windows Universal platform, you will need to add it to the project:
$ ionic cordova platform add windows
Remember for iOS, Android, and Windows Universal, their respective SDKs must be installed on the local machine in order to actually build for that platform. This Ionic command only configures the local project files for use by the SDKs.
If for some reason you need to remove a platform from your project, you can use:
$ ionic cordova platform remove [
platform name
]
Occasionally, something might go wrong during an installation of a plugin or during an update. One common solution is to remove the platform, then reinstall it into the project.
Managing Cordova Plugins
The installation of Cordova plugins is often one of the first things you will do after including your build platforms. Although we will touch upon using Cordova plugins and Ionic Native in a later chapter, the basic command is:
$ ionic cordova plugin add [
plugin id
]
Usually, the plugin ID is the npm domain name—for example,cordova-plugin-geolocation
. However, it could reference a local directory or a GitHub repo.
To remove an installed plugin, the command is simply:
$ ionic cordova plugin rm [
plugin id
]
If you ever need to see a listing of all the plugins you have installed in your project, use:
$ ionic cordova plugin ls
Ionic Generator
Although the Ionic CLI will scaffold your application via theionic start
command, you can then extend your app with new pages, components, providers, pipes, and more via the CLI. Thegenerate
command allows you to quickly create a boilerplate version of the element you need:
$ ionic g [page|component|directive|pipe|provider|tabs] [
element name
]
For example, if we want to create a new page for an application, the command is simply:
$ ionic g page myPage
The Ionic CLI will then create a new directory in our app directory, and generate the HTML, SCSS, and TS files for us.
A QUICK NOTE ON NAMING CONVENTIONS
Ionic 2 uses kebob-casing for filenames (e.g.,my-about-page.html) and CSS classes (e.g.,.my-about-page). It uses PascalCasing for JavaScript classes in TypeScript (e.g.,MyAboutPage).
Previewing Your Application
Often, early development can be previewed and tested locally in a browser. Although the Ionic CLI does make it fairly easy to launch your application in an emulator or on an actual mobile device, the ability to preview and debug in what is probably a very familiar environment, your browser is a real advantage.
Theionic serve
command will start a local development server, then automatically load your application into the browser. In addition, the command will start a LiveReload watcher, so as you make changes to the application, it will be automatically reloaded in the browser without you needing to manually reload it (Figure 3-2).
$ ionic serve
Figure 3-2.The Ionic tab template being run in a browser
The Ionic lab Command
With the--lab
flag passed toionic serve
, your application will be displayed in an iOS frame, an Android frame, and a Windows frame in the same browser window. This feature will let you quickly see the various platform-specific differences that may exist. To use this simply type the following (seeFigure 3-3):
$ ionic serve --lab
Figure 3-3.Ionic serve running in --lab mode
In this mode, each instance of the Ionic app will run as if on that mobile platform. So any platform-specific CSS or JavaScript will be executed. This feature can be a real timesaver during the early part of the development cycle, but it is in no way a substitute for testing on actual devices.
Specifying an IP Address to Use
If you need to specify what address the LiveReload server will run on, you can pass that value via the--address
flag, followed by the IP address:
$ ionic serve --address 112.365.365.321
Emulating Your Ionic App
Theionic cordova emulate
command will build your Ionic application and then load and run your app on the specified emulator or simulator:
$ ionic cordova emulate android
$ ionic cordova emulate ios
$ ionic cordova emulate windows
Emulators are useful for testing portions of the application that require actual device features. When launching and previewing your application in an emulator, it takes some time to initialize and then load your app.
Emulating iOS Devices
In order for the Ionic CLI to communicate with the iOS simulator, an additional node package will need to be installed. If you did not install the ios-sim package earlier, please do it now:
$ npm install -g ios-sim
Once this package is installed, the Ionic CLI will be able to compile the app and run it within the iOS simulator. If you need to target a specific iOS model, you can set the--target
flag to the specific device.
For a list of your installed devices, use the following code:
$ ios-sim showdevicetypes
Table 3-1shows the possible device types.
iPhone-5, 10.0 | iPhone-6s-Plus, 10.0 | iPad-Air-2, 10.0 |
iPhone-5s, 10.0 | iPhone-7, 10.0 | Apple-TV-1080p, tvOS 10.0 |
iPhone-6, 10.0 | iPhone-7-Plus, 10.0 | Apple-TV-1080p, tvOS 9.1 |
iPhone-6-Plus, 10.0 | iPad-Retina, 10.0 | Apple-Watch-38mm, watchOS 2.1 |
iPhone-6s, 10.0 | iPad-Air, 10.0 | Apple-Watch-42mm, watchOS 2.1 |
SUPPORTED IOS DEVICES
Although both the Apple TV and Apple Watch are listed by ios-sim, these platforms are not supported by Apache Cordova nor Ionic.
Emulating Android Devices
To emulate your Ionic application in the Android emulator, you first must have manually created an Android virtual device (AVD) to be used by the emulator. If you did not do this in the previous chapter, use:
$ android avd
This will launch the AVD Manager, a tool that you can use to create and manage various AVDs. Once you have created an AVD, the Ionic CLI will be able to launch the Android emulator and run your application. This process can take quite some time as the emulator boots up.
To target a specific Android device, you can use–-target=NAME
to run the app in the specific device you created; otherwise, the default emulator is used.
PERFORMANCE TIPS
If you are using the Android emulator, one tip for improved performance is to not close the emulator, but keep it running, and just reload the app.
Although the performance of the emulator has improved, many developers have opted for a solution fromGenymotionas an alternate to the standard Android emulator.
Running Ionic App on a Device
The Ionic CLI can also compile your Ionic application so it can run on a properly configured device:
$ ionic cordova run [
platform name
]
If no device is found to be connected to the computer, the Ionic CLI will then attempt to deploy to the emulator for that platform.
If you are deploying to an iOS device, there is an additional node module that you will need to install, ios-deploy:
$ npm install -g ios-deploy
You must also configure your iOS device for development. If you’re working with an Android device, you only need to set it to development mode.
Logging
Both theemulate
andrun
commands support the ability to remap the console logs, as well as the server logs to the Ionic CLI. To enable console logging, pass in either the--consolelogs
flag, or the short version--c
. If you want to capture the server logs, pass in the--serverlogs
flag, or the short version--s
.
CLI information
If you ever need to see the entire state of the Ionic CLI and its supporting tooling, use:
$ ionic info
Here is what my system looks like:
global packages:
@ionic/cli-utils : 1.4.0
Ionic CLI : 3.4.0
local packages:
@ionic/app-scripts : 2.0.0
@ionic/cli-plugin-ionic-angular : 1.3.1
Ionic Framework : ionic-angular 3.5.0
System:
Node : v6.11.0
OS : OS X El Capitan
Xcode : Xcode 8.0 Build version 8A218a
ios-deploy : 1.9.1
ios-sim : 6.0.0
npm : 3.10.10
When debugging an issue, this information can often be quite useful.
Summary
In this chapter we have touched on the principle Ionic CLI commands that you will typically use during your development process. There are addition commands and settings available. To see the full list, useionic --help
.
To recap the key commands that we introduced in the chapter:
Learn to scaffold your initial Ionic application with
ionic start
.Manage mobile platforms to the project with
ionic cordova platform
.Preview the application in the browser, in the emulators, and on-device with
ionic cordova run/emulate
.
Chapter 4.Just Enough Angular and TypeScript
With our basic system configured for Ionic development, we can explore another set of foundational technology that Ionic is built atop, Angular. Just as Ionic leverages Apache Cordova to act as the bridge to the native mobile platform, it uses Angular as the underpinnings of its interface layer. Since the beginning, the Ionic Framework has been built on the Angular framework.
Why Angular?
Angular is the next version of Google’s incredibly popular MV* framework. This new version of Angular was announced at the ngEurope conference in October 2014. The Angular team revealed that this version of Angular would be a significant revision. In many ways, this new Angular was a completely new framework, sharing only its name and some notional references to the original version. This announcement certainly generated a lot of concern and uncertainty about the future of the framework. This was equally true with the Ionic community and within the Ionic team itself. What were the changes that would be required? How much relearning would existing Ionic developers need to undertake to continue to work with Angular?
But as the shock wore off, it became clearer that this evolution of the Angular framework was for the better. The framework was becoming faster, cleaner, more powerful, and also easier to understand. The Angular team also took another bold gamble and looked at the web to come, not the web that was. So they decided to embrace many of the latest and emerging web standards and develop it in next generation of JavaScript.
At ngConf 2016, the Angular team announced that with release candidate 1, the framework will be simply known as Angular instead of Angular 2. More recently, the team also announced they were moving to a semantic versioning system. Meaning that version numbers will be updating a faster cadence that most have been used to. The published roadmap has a major release scheduled for every 6 months. Currently, Angular is at version 4.2.6.
So let’s take a look at some of these changes to Angular in more detail.
Components
One of the biggest changes from Angular 1 is the fact that we no longer rely on scope, controllers, or to some degree directives. The Angular team adopted a component-based approach to building elements and their associated logic. Those who have developed applications with more traditional frameworks are very familiar with this type of model. The fact is that we are developing on a platform originally designed to read physics papers and not to build applications upon.
Here is what a sample Angular component looks like:
import
{
Component
}
from
'@angular/core'
;
@
Component
({
selector
:
'my-first-component'
,
template
:
`
<
div
>
Hello, my name is {{name}}.
<
button (click)="sayMyName()"
>
Log my name
<
/button
>
<
/div
>
`
})
export
class
MyComponent
{
constructor
()
{
this
.
name
=
'Inigo Montoya'
}
sayMyName
()
{
console
.
log
(
'Hello. My name is '
,
this
.
name
,
'. ↵
You killed my father. Prepare to die.'
)
}
}
This is the exact same model that Ionic uses to generate its component library. In fact, there is nothing that prevents you from extending your Ionic application to use your own custom components.
Let’s look at this code snippet in greater detail.
First, the code imports theComponent
module from the Angular library. In Angular this is how dependency injection is handled. With Release Candidate 1 (RC1), the Angular team broke the library into smaller modules, as well as dropped the “2” suffix in the library.
Next, we use the@Component
decorator to provide some metadata about our code to the compiler. We define the custom HTML selector to use. So when we use<my-first-component></my-first-component>
, the associated template will be inserted into the DOM. Templates can come into two fashions: inline as shown here, or as an external reference. If you need to span your template across multiple lines for readability, make sure you use the backtick ( ` ) instead of a single quote ( ' ) to define the template string. We will look at templates in more detail later in this chapter.
After the decorator, we export the class definition itself,MyComponent
. Within this constructor of this class, the code sets the name variable to"Inigo Montoya"
. Unlike Angular 1, and JavaScript in general, Angular has a much tighter control over the scope of variables.
Finally, this sample class has a public method ofsayMyName
that will write a string to the console. As you work more with Ionic and Angular 2, this new method of creating components and pages will become more familiar and natural to you.
Inputs
Since Angular is built using a component model, it needs a mechanism to pass information into the component itself. This is handled via Angular’sInput
module. Let’s look at a simple component,<current-user>
, that will need to know about a user argument in order for it to perform its code. The actual markup would look like this:
<
current-user [user]="currentUser"
>
<
/current-user
>
while the component itself would look like this:
import { Component, Input } from '@angular/core';
@Component({
selector: 'current-user',
template: '
<
div
>
{{user.name}}
<
/div
>
'
})
export class UserProfile {
@Input() user;
constructor() {}
}
Within theclass
definition, there is now an@Input
binding to the user variable. With this binding in place, Angular will pass in thecurrentUser
variable into the component, thus enabling the template to render out theuser.name
value.
This is how Ionic’s components also function. We will pass in data and configuration parameters using the same system as this example.
Templates
Templates are HTML fragments that Angular combines with specific elements and attributes to generate the dynamic content. For the most part, the templating system in Angular did not change that much.
{ }: RENDERING
<
div
>
Hello, my name is {{name}}.
<
/div
>
However, unlike Angular 1, this data binding is one way. By doing so, the number of event listeners that were generated have been reduced, and thus, performance improved.
[ ]: BINDING PROPERTIES
When a component needs to resolve and bind a variable, Angular now uses the [] syntax. We touched on this earlier in this chapter when covering Inputs.
If we havethis.currentColor
in our component, we would pass this variable into our component, and Angular would ensure that the values would stay updated:
<
card-header [themeColor]="currentColor"
>
<
/card-header
>
( ): EVENT HANDLING
In Angular 1, we would use custom directives to listen for user events, like clicking an element (likeng-click
). Angular has taken a cleaner approach and just wraps the event you want to listen for in parentheses and then assigns that to a function in the component:
<
my-component (click)="onUserClick($event)"
>
<
/my-component
>
[( )]: TWO-WAY DATA BINDING
By default, Angular no longer establishes two-way data binding. If you do need to have this functionality, the new syntax is actually a shorthand notation of the binding property and the event-handling syntaxes:
<
input [(ngModel)]="userName"
>
Thethis.userName
value of your component will stay in sync with the input value.
*: THE ASTERISK
The use of the asterisk before certain directives tells Angular to treat our template in a special fashion. Instead of rendering the template as is, it will apply the Angular directive to it first. For example,ngFor
takes our<my-component>
and stamps it out for eachitem
initems
, but it never renders our initial<my-component>
since it’s a template:
<
my-component *ngFor="let item of items"
>
<
/my-component
>
Events
Events in Angular use the parentheses notation in templates and trigger methods in a component’s class. For example, assume we have this template:
<
button (click)="clicked()"
>
Click
<
/button
>
and this component class:
@Component(...)
class MyComponent {
clicked() {
}
}
Ourclicked()
method in the component will be called when the button is clicked.
In addition, events in Angular behave like normal DOM events. They can bubble up and propagate down.
If we need access to the event object, simply pass in the$event
as a parameter in the event callback function:
<
button (click)="clicked($event)"
>
<
/button
>
and the component class would become:
@Component(...)
class MyComponent {
clicked(event) {
}
}
CUSTOM EVENTS
What if your component needs to broadcast a custom event to another component? Angular makes this process quite easy.
In our component, we import theOutput
andEventEmitter
modules. Then we define our new event,userUpdated
, by using the@Output
decorator. This event is an instance of anEventEmitter
:
import {Component, Output, EventEmitter} from '@angular/core';
@Component({
selector: 'user-profile',
template: '
<
div
>
Hi, my name is
<
/div
>
'
})
export class UserProfile {
@Output() userDataUpdated = new EventEmitter();
constructor() {
// Update user
// ...
this.userDataUpdated.emit(this.user);
}
}
When we want to trigger the broadcast of the event, you simply call theemit
method on the custom event type and include any parameters to be transmitted with the event.
Now when we used this component elsewhere in our app, we can bind the event thatuser-profile
emits:
<
user-profile (userDataUpdated)="userProfileUpdated($event)"
>
<
/user-profile
>
When we import ourUserProfile
component into our new component, it can now listen for theuserProfileUpdated
event that is broadcasted:
import {Component} from '@angular/core';
import {UserProfile} from './user-profile';
export class SettingsPage {
constructor(){}
userProfileUpdated(user) {
// Handle the event
}
}
LIFE CYCLE EVENTS
Both the Angular app and its components offer life cycle hooks that give developers access to each of the critical steps as they occur. These events are usually related to their creation, their rendering, and their destruction.
NGMODULE
The Angular team reworked the method of bootstrapping your application through the use of theNgModule
function. This was done toward the end of the release candidate cycle for Angular, so it might come as a surprise to some. The@NgModule
takes a metadata object that tells Angular how to compile and run module code. In addition,@NgModule
allows you to declare all your dependencies up front, instead of having to declare them multiple times in an app:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
This code sample shows a basicapp.module.ts
file that will use theBrowserModule
to enable the Angular app to properly run in a browser, then both declare and bootstrap the AppComponent.
This module is in turn used by the_main.ts_file to perform the actual bootstrapping:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
This sample code initializes the platform that your application runs in, then uses the platform to bootstrap your AppModule. The Ionic starter templates will generate the necessary modules for you.
Another benefit of this system is it enables us to use the Ahead of Time (AoT) compiler, which provides for much faster applications.
COMPONENT INIT EVENT
When a component is created, its constructor function is called. Within the constructor, any initialization we might need to perform on the component can occur. However, if our component is dependent on information or properties from a child component, we will not have access to that data.
Angular provides thengOnInit
event in order to handle this need to wait until the component initialization is truly complete. Our component can wait for this method to be triggered by the framework. Then all our properties are resolved and available to be used by the component.
COMPONENT LIFE CYCLE EVENTS
Beyond,ngOnInit, there are several other life cycle events for a component:
ngOnDestroy
This method is called before the component is destroyed by the framework. This would be where you unsubscribe observables and detach event handlers to avoid memory leaks.
ngDoCheck
This method provides the ability to perform custom change detection.
ngOnChanges(changes)
This method is called when one of the component’s bindings have changed during the checking cycle. The method’s parameter will be an object in the format:
{
'prop': PropertyUpdate
}
ngAfterContentInit()
UnlikengOnInit
, which is called before the content has been rendered, this method is called once that content is first rendered on the view.
ngAfterContentChecked
This method is called after Angular checks the bindings of the external content that it projected into its view.
ngAfterViewInit
After Angular creates the component’s view(s), this method is triggered.
ngAfterViewChecked
The final method during the component initialization process, this will be call once all the data bindings are resolved in the component’s views.
IONIC EVENTS
Although you can use the Angular events outlined, it is recommended that you use the Ionic events instead.Table 4-1lists a description of their triggers.
Event | Description |
ionViewDidLoad |
Runs when the page has loaded. This event only happens once per page being created. If a page leaves but is cached, then this event will not fire again on a subsequent viewing. |
ionViewWillEnter |
Runs when the page is about to enter and become the active page. |
ionViewDidEnter |
Runs when the page has fully entered and is now the active page. This event will fire, whether it was the first load or a cached page. |
ionViewWillLeave |
Runs when the page is about to leave and no longer be the active page. |
ionViewDidLeave |
Runs when the page has finished leaving and is no longer the active page. |
ionViewWillUnload |
Runs when the page is about to be destroyed and have its elements removed. |
ionViewCanEnter |
Runs before the view can enter. This can be used as a sort of “guard” in authenticated views where you need to check permissions before the view can enter. |
ionViewCanLeave |
Runs before the view can leave. This can be used as a sort of “guard” in authenticated views where you need to check permissions before the view can leave. |
Pipes
Pipes, previously known as “Filters,” transform a value into a new value, like localizing a string or converting a floating-point value into a currency representation:
<
p
>
The author's birthday is {{ birthday | date }}
<
/p
>
If the birthday variable is a standard JavaScriptDate
object, it will look likeThu Apr 18 1968 00:00:00 GMT-0700 (PDT)
. Certainly not the most human-readable format. However, within the interpolation expressed in our template, our birthday value is passed through the pipe operator ( | ) to theDate
pipe function on the right, thus rendering the author’s birthday as April 18, 1968.
Angular comes with a set of commonly used pipes such asDatePipe
,UpperCasePipe
,LowerCasePipe
,CurrencyPipe
, andPercentPipe
. They are all immediately available for use in any template.
@ViewChild
Often we need to read or write child component values or call a child’s component’s method. When the parent component_class_requires that kind of access, we_inject_the child component into the parent as aViewChild
:
import {Component, ViewChild} from '@angular/core';
import {UserProfile} from '../user-profile';
@Component({
template: '
<
user-profile (click)="update()"
>
<
/user-profile
>
',
directives: [UserProfile]
})
export class MasterPage {
// we pass the Component we want to get
// assign to a public property on our class
// give it the type for our component
@ViewChild(UserProfile) userProfile: UserProfile
constructor() { }
update(){
this.userProfile.sendData();
}
}
Both theViewChild
module andUserProfile
component are injected from the Angular Core. Within theComponent
decorator, we also must set thedirectives
property to include a reference to our injected component. Our constructor contains ourViewChild
decorator that set ouruserProfile
variable to our injected component.
With those code elements in place, we are able to interact with our child component’ssendData
method.
Understanding ES6 and TypeScript
Over the past few years, web developers have seen an explosion in attempts to create “better” or more developer-centric versions of JavaScript. CoffeeScript, AtScript, Dart, ES6, TypeScript, and so on have sought to improve on standard JavaScript. Each of these languages sought to extend JavaScript by providing features and functionality aimed at modern application development. But each solution had to deal with the fact that our modern browsers use a version of JavaScript known formally as ECMAScript 5 (ES5), meaning that each solution would need to output its efforts into standard JavaScript.
In order to use either of these modern language options, our code will have to be_transpiled_into ES5-based JavaScript. If you have never heard of the term “transpiling” before, it is a process of taking the code written in one language and converting into another.
Currently, there are two primary choices if you want to use next-generation JavaScript: ES6 or TypeScript. ES6 is the next official version of JavaScript and was formally approved in June 2015, and over time it will be supported natively in our browsers. The other language option is TypeScript. Typescript is Microsoft’s extension of JavaScript that comes with powerful type-checking abilities and object-oriented features. It also leverages ES6 as part of its core foundation. TypeScript is a primary language for both Angular and Ionic application development.
Although none of our current browsers support either option, our code can be transpiled using tools like Babel or tsc. We don’t have to worry about setting up this system, as it is built into the default Ionic build process.
Variables
With ES6, the way we can define our variables has improved. We can now specify a variable by using the keywordlet
.
In ES5, variables could only be defined using the keywordvar
, and they would be scoped to the nearest function. This was often problematic, as a variable could be accessible outside of the function that it was defined in.
for (var i = 0 ; i
<
10; i++) {
console.log(i); //Output 0-9
}
console.log(i); // Outputs 10
The variablei
is still available after the loop has finished, which is not quite the expected behavior.
By using thelet
keyword, this issue is no longer a problem, and the variable is scoped to its nearest block:
for (let i = 0 ; i
<
10; i++) {
console.log(i); //Outputs 0-9
}
console.log(i); // Uncaught ReferenceError: i is not defined
Now, after the loop has executed,i
is not known to the rest of the code. Whenever possible, uselet
to define your variables.
Classes
JavaScript classes have been introduced in ES6 and are syntactical sugar over JavaScript’s existing prototype-based inheritance. The class syntax is_not_introducing a new object-oriented inheritance model to JavaScript. If you have developed using another object-oriented language like C# or Java, this new syntax should look familiar. Here is an example:
class Rocket {
landing(location) {
}
}
class Falcon extends Rocket {
constructor() {
super();
this.manufacturer = 'SpaceX';
this.stages = 2;
}
landing(location) {
if ((location == 'OCISLY') || (location == 'JRTI')){
return 'On a barge';
} else {
return 'On land';
}
}
}
class Antares extends Rocket {
constructor() {
super();
this.manufacturer = 'OrbitalATK';
this.stages = 2;
}
landing(location) {
console.log('In the ocean');
}
}
Promises
ThePromise
object is used for deferred and asynchronous computations. A Promise represents an operation that hasn’t completed yet but is expected in the future. This is exactly the type of functionality we need when interacting with remote servers or even loading local data. It provides a simpler method to handle asynchronous operations than traditional callback-based approaches.
A Promise can be in one of three states:
Pending
The Promise’s outcome hasn’t yet been determined because the asynchronous operation that will produce its result hasn’t completed yet.
Fulfilled
The asynchronous operation has completed, and the Promise has a value.
Rejected
The asynchronous operation failed, and the Promise will never be fulfilled. In the rejected state, a Promise has a_reason_that indicates why the operation failed.
The primary API for a Promise is itsthen
method, which registers callbacks to receive either the eventual value or the reason the Promise cannot be fulfilled.
Assuming we have a functionsayHello
that is asynchronous and needs to look up the current greeting from a web service based on the user’s geolocation, it may return a Promise:
var greetingPromise = sayHello();
greetingPromise.then(function (greeting) {
console.log(greeting); // 'Hello in the United States’
});
The advantage of this method is that while the function is awaiting the response from the server, the rest of our code can still function.
In case something goes wrong like if the network goes down and the greeting can’t be fetched from the web service, you can register to handle the failure using the second argument to the Promise’sthen
method:
var
greetingPromise
=
sayHello
();
greetingPromise
.
then
(
function
(
greeting
)
{
console
.
log
(
greeting
);
// 'Hello in the United States’
},
function
(
error
)
{
console
.
error
(
'uh oh: '
,
error
);
// 'Drat!’
});
IfsayHello
succeeds, the greeting will be logged, but if it fails, then the reason (i.e., error) will be logged usingconsole.error
.
Observables
Many services with Angular use Observables instead of Promises.Observables are implemented through the use of theRxJS library. Unlike a Promise, which resolves to a single value asynchronously, an observable resolves to (or emits) multiple values asynchronously (over time).
In addition, Observables are cancellable and can be retried using one of the retry operators provided by the API, such asretry
andretryWhen
. Promises require the caller to have access to the original function that returned the Promise in order to have a retry capability.
Template Strings
One of the features of Angular is its built-in templating engine. In many cases, these templates are stored as external files. However, there are times when keeping them inline makes more sense. The difficulty has been writing long inline templates without having to resort to using concatenation or needing to escape any single or double quotes in the string.
ES6 now supports the use of backticks at the start and end of the string:
let template = `
<
div
>
<
h2
>
{{book.name}}
<
/h2
>
<
p
>
{{book.summary}}
<
/p
>
<
/div
>
`;
Template strings do not have to remain static. You can perform string interpolation by using$(expression)
placeholders:
let user = {name:'Rey'};
let template = `
<
div
>
Hello,
<
span
>
${ user.name }
<
/span
>
<
/div
>
`;
TEMPLATE EXPRESSIONS: ES6 VERSUS ANGULAR
ES6’s template expression are only meant for string replacement. If you need to evaluate a function or test a condition, use Angular template expressions instead.
Arrow Functions
Arrow functions make our code more concise and simplify function scoping and thethis
keyword. By using arrow functions, we avoid having to type thefunction
keyword,return
keyword (it’s implicit in arrow functions), and curly brackets.
In ES5, we would have written a simplemultiply
function like this:
var multiply = function(x, y) {
return x * y;
};
But in ES6, using the new arrow function formation, we can write the same function this way:
var multiply = (x, y) =
>
{ return x * y };
The arrow function example allows us to accomplish the same result with fewer lines of code and approximately half the typing.
One common use case for arrow functions is array manipulations. Take this simple array of objects:
var missions = [
{ name:'Mercury', flights:6 },
{ name:'Gemini', flights:10 },
{ name:'Apollo', flights:11 },
{ name:'ASTP', flights:1 },
{ name:'Skylab', flights:3 },
{ name:'Shuttle', flights:135 },
{ name:'Orion', flights: 0 }
];
We could create an array of objects with just the names or flights by doing this in ES5:
// ES5
console.log(missions.map(
function(mission) {
return mission.flights;
}
)); // [6, 10, 11, 1, 3, 135, 0]
Rewriting this using the arrow function, our code is more concise and easier to read:
// ES6
console.log(missions.map(
mission=
>
mission.flights
)); // [6, 10, 11, 1, 3, 135, 0]
Types
TypeScript is a data-typed language that gives you compile-time checking. By default, TypeScript supports JavaScript primitives:string
,number,
andboolean
:
let num: number;
let str: string;
let bool: boolean;
num = 123;
num = 123.456;
num = '123'; // Error
str = '123';
str = 123; // Error
bool = true;
bool = false;
bool = 'false'; // Error
TypeScript also supports typed arrays. The syntax is basically postfixing [] to any valid type annotation (e.g.,boolean[]
):
let booleanArray: boolean[];
booleanArray = [true, false];
console.log(booleanArray[0]); // true
console.log(booleanArray.length); // 2
booleanArray[1] = true;
booleanArray = [false, false];
booleanArray[0] = 'false'; // Error!
booleanArray = 'false'; // Error!
booleanArray = [true, 'false']; // Error!
Special Types
Beyond the primitive types, there are a few types that have special meaning in TypeScript. These areany
,null
,undefined
, andvoid
:
let someVar: any;
// Takes any and all variable types
someVar = '123';
someVar = 123;
Thenull
andundefined
JavaScript literals are effectively treated as the same as theany
type:
var str: string;
var num: number;
// These literals can be assigned to anything
str = undefined;
num = null;
Typing Functions
Not only can you type variables, but you can also type the results of a function call:
function sayHello(theName: string): string {
return 'Hello, '+theName;
}
If you try to callsayHello
and assign the result to an incorrect data type, the compiler will throw an error.
:void
Use:void
to signify that a function does not have a return type:
function log(message): void {
console.log(message);
}
Summary
There is much more to cover in both Angular and TypeScript than this chapter’s very simple introduction. In all likelihood, you will be using additional resources for both of these technologies as you begin to develop more feature-complete applications. But let’s look at some of the key points we have covered in this chapter.
We looked at Angular’s new component model, its templating, the new data-binding methods, and the component life cycle. Beyond that, we also explored some new capabilities in ES6 and TypeScript, including classes, Promises, and arrow functions, as well as the ability to assign types to our variables and functions.