Вы находитесь на странице: 1из 59

Introduction

Hi, this is Steve Michelotti. Welcome to Building Mobile Apps with Ionic 2, Angular 2,
and TypeScript. The first version of the Ionic framework bursts on the scene a couple
years ago and quickly became the most popular framework in the world for building
cross-platform mobile apps. The Ionic framework enables developers to build mobile
apps installed from an app store using web technologies they're already familiar with,
such as JavaScript, HTML, and CSS. In this course we'll explore Ionic 2, built on top of
Angular 2 and TypeScript, which is an exciting new version of the framework that
revolutionized building cross-platform mobile apps. This will be a code focused course
in which we'll build an app from scratch. This is a preview of the app we'll build
throughout the course. It is an app for basketball tournaments which enables coaches and
parents of players to easily see the schedule and standings for each tournament. Here we
have the home page, which is a My Teams page where we can bookmark teams we're
following as well as find new teams, for example, by clicking the Find A Tournament
button. We see a list of tournaments, we can select the individual tournament, then we
can see the list of teams in that tournament and select a team. From here we can to the
team detail screen for that team and flip between standings, where we can see wins and
losses, and back to the team itself. Here we can add the team as a favorite, essentially
bookmarking them, which means anytime we go back to the home screen we can now see
that team that we just added as a favorite and directly get back to them anytime we want.
We can see that team's schedule of games and click on an individual game to see the game
detail from that game, including score and location, and we have some buttons here to get
mapping as well as driving directions to the game. We will build this entire app from
scratch during this course. You'll also see examples throughout the course of Ionics multi-
platform theming, for example, in this screen right here you can see some differences
between the Android app on the left compared to the iOS app on the right, in terms of
things like the Back button, icon styles, and even the segment control, switch the view
between a single division or all divisions. You'll see all these and more during this course.

Course Overview

Here is an overview of what you can expect from this course. In this first brief module
I'll start out by giving a brief conceptual overview of what Ionic is and some key
differentiators that make Ionic 2 very compelling. In the Getting Started module, I'll show
you how you can install Ionic and create your first project. I'll also show you how to
quickly get up and running by running your app in the browser, in an emulator, or on the
device itself. We'll then turn our attention to navigation and how it works in Ionic 2, which
has completely changed compared to Ionic 1. We'll also look at navigation parameters,
side menu navigation, tabs, and also some advanced navigation concepts. In the next
module we'll see how to work with HTTP and Lifecycle Events. I'll show you how you
can retrieve data in your app using either promises or reactive extensions, you also see
how we can use the Ionic Lifecycle Events to load data at the appropriate times. We'll
then start our journey into several of the foundational components in Ionic 2. These
include Ionic lists, buttons, cards, date time, toggle, toasts, and more. In the next module
we'll dive even deeper into Ionic 2 components, going beyond the basics. We'll look at
more advanced components and concepts, including virtual scrolling for significantly
enhanced performance, pull to refresh, the segment component, mapping, and driving
directions. Ionic Native is a library that allows us to access native features of the mobile
device. If you're familiar with the first version of Ionic, Ionic Native is the follow up to
the popular ngCordova library. Using Ionic Native, I'll show you how to use geolocation,
the device camera, the barcode scanner, local notifications, and more. In the final module
I'll show you how you can customize your Ionic 2 app by putting some finishing touches
on it prior to deploying to an app store. These include custom colors for your app's theme,
app metadata, and how to generate app icons and splash screens for your app.

What Is Ionic?

Before we start diving into all the code examples, it's important for us to answer the
question - what is Ionic? In short, Ionic is a mobile optimized open source framework for
building cross-platform apps, such as Android and iOS, using familiar web technologies,
like HTML, JavaScript, and CSS. But let's go a little deeper with our definition.
Historically when an app designer wanted to deploy on multiple platforms they would
have to write one version for iOS using Objective-C, another version for Android using
Java, and perhaps even another version for Windows using C#. This approach certainly
does not lend itself well to efficiency, reuse, or maintenance. And few companies can
afford such an approach. Ionic enables developers to build the app once using the
development tools they're already familiar with and deploy it on multiple platforms. Ionic
has always been built on top of Angular. The first version was built on top of Angular 1.
Now we have Ionic 2 that is built on top of Angular 2. So not only are we reusing our
knowledge of general web technologies, but we're also able to leverage our knowledge
specifically of the Angular framework. This is also beneficial because we can realize all
the usability and performance improvements of Angular 2, and also it hooks us into the
larger Angular developer community. Ionic has always been based on being able to
seamlessly integrate with Cordova. The Cordova library is what enables us to access the
native features on the device from our JavaScript or TypeScript code. What is Cordova
you ask? Let's take a closer look. First you heard me mention that Cordova enables us to
access native features on the device, these are things like geolocation, the device camera,
the accelerometer, vibrating the device and much, much more. These features actually
have native APIs on each platform that must be called. The Cordova library normalizes
these calls and provides a simply JavaScript wrapper around these native API calls so that
they may be called from JavaScript code. Cordova is specifically designed to be used for
mobile apps being built using HTML, JavaScript, and CSS. These are true mobile apps
that are natively installed from an app store, not just a mobile optimized website that
looks okay on a mobile devices browser. Cordova has now been around for many years
and there is a huge and thriving ecosystem of high quality plug-ins. We can leverage these
plug-ins inside of our Cordova-based apps. Cordova has millions of downloads over the
last few years, the library continues to mature and increase in quality. This is yet another
reason why it's ideal to be used inside of Ionic apps. Later in this course we'll look at
Ionic Native, which is the Ionic library we use to easily interact with Cordova.

Why Ionic 2?

Ionic 2 is essentially a rewrite of the already very successfully Ionic 1 framework. So


why did the Ionic team create this new version? There are several reasons. First, Ionic 2
is built on top of Angular 2, which is a significant departure from Angular 1. Building on
top of Angular 2 enables Ionic 2 to benefit from numerous enhancements including
performance increases, a more standard way of writing and building apps, particularly if
you're using TypeScript, including dependency injection, components, and modules. The
first version of the Ionic framework utilized UI router, while this is certainly a powerful
router for Angular 1 apps, the navigation in Ionic 2 is overhauled to be much more
powerful and flexible using a navigation stack in a natural way to move from screen to
screen. Another new feature in Ionic 2 is automatic platform theming, for example the
framework will detect if you're on an Android device and render an Android style theme,
and similarly an iOS style theme if you're on an iOS device. You'll see numerous
examples of that throughout this course. The Ionic team continues to improve the build
system that they provide, utilizing tools like Gulp for building, serving, and live reload,
TypeScript for compilation, SASS for CSS compilation, and NPM for package
management. Ionic 2 makes developing a mobile app truly enjoyable. The Ionic team has
looked at optimizing every aspect of performance for Ionic 2 as compared with Ionic 1.
Some examples include aggressive caching for much better screen navigation
performance and virtual lists to enable scrolling of extremely long lists to have native-
like performance. Without a doubt Ionic 2 is an extremely compelling new version of the
framework. If you are currently using Ionic 1, I already have a course in the Pluralsight
library dedicated to the first version of Ionic. That is a course you should watch if you're
already building an Ionic 1 app. However, if you're about to start an Ionic 2 app or already
have, this course is the place you want to be. In fact, the app we'll build in this course is
similar, but not identical to, the app built in the first course. I did this intentionally for the
people that are migrating so they can see how things have changed. However, this isn't a
migration course, we're covering Ionic 2 from scratch in this course. So if you have no
previous experience with Ionic, that's fine too. This course is the right starting place if
you're starting out with Ionic 2 today.

Helpful Prerequisites

There are a couple prerequisites for this course that I strongly recommend you have. We'll
be using TypeScript throughout this course to build our app. There are several TypeScript
courses already in the Pluralsight library. In particular I recommend TypeScript
Fundamentals by Dan Wahlin and John Papa. Angular 2 is another technology that I'll be
leveraging heavily. This course assumes you already have some familiarity with Angular
2, the basics like dependency injection and how data binding works. There are also
numerous courses in the Pluralsight library already for Angular 2, any of these would be
a good start, but in particular I can recommend Angular 2 - First Look by John Papa, and
Angular 2 - Getting Started by Deborah Kurata.

Course Repository

Technology changes incredibly fast these days, that means that library APIs can change
and as a result courses like this can easily go out of date. Because of this, I've created this
GitHub repository where I'll make sure to post information containing key files you need
to have as well as information about whether the course is up-to-date and potential work
arounds you can use if it's not.

What We Will Be Building

You've already seen a brief demo of the app itself that we'll be building throughout this
course. Here is a quick look at the screens. Our home page will be a My Teams page
where we can save bookmarks to the teams that we're following. If we want to follow
more teams we can first find a tournament and then once we find a tournament we can
select a team from the teams list. Once we navigate to the Team Home screen for a
particular team, we'll eventually build our app up to having a tabbed layout on the screen
that enables us to switch back and forth between Team Detail and Standings information
for the tournament. From the Team Detail we can also navigate to any of that team's
games to see game detail. From there we'll be able to view a map to the game as well as
get driving directions. We'll see this diagram a few times throughout the course, but I
think it's a good mental model to have in mind from the start. You have seen a preview
of the app we will be building and you now have an understanding of what Ionic is. Now
let's get started into our journey of building mobile apps with the Ionic 2 framework.

Getting Started with Ionic 2


Overview

In this module we'll get up and running with Ionic 2. First I'll show you how easy it is to
install Ionic. Once Ionic is installed we'll create our first project. Once we've created our
first project, we'll need different ways to test it, we'll start by testing it in the browser. I'll
then show how you can test on an actual emulator. And of course, there's absolutely no
substitute for testing on the device itself, I'll show you how to do that here. I'll also show
how easy it is to use a tool called Ionic View to test on a device. Once we're comfortable
testing the app, I'll walk you through the basic code structure of an Ionic app. I'll also
show you some of the built in support that Ionic has for platform-specific displays.
Finally, we'll add some basic Hello World style code in the application we just created.
Let's get started now.

Installing Ionic 2

Ionic development is based around a Node.js command line tool, therefore the first thing
is that we need to have Node installed locally. If you don't already have Node installed,
just go to the nodejs.org website and grab the appropriate installer. Regardless if you're
on a Mac or Windows machine, Node will work just fine. Here the Node.js site has
detected that I'm on a Windows machine and presented me with the options for download,
either of these versions are fine. I've already installed Node, so I'm not going to take the
time to do that again here. If you download the installer, it's a simple installer, you can
just click through to get it installed quickly. As an alternative to running the installer, I
highly recommend checking out the 2.5 minute clip entitle Getting Node.js, which is part
of John Papa's Pluralsight course on build automation with Gulp.js, which is shown in the
link on the screen here. In just 2.5 minutes you'll get any additional information you'll
need for installing Node on Windows or on OS X without me repeating everything here.
With the assumption that I now have Node installed, I'm going to run a typical npm install
command to install Ionic. I'm going to use the -g switch to install it globally, so I'll say -
g ionic, then I'm going to add an @beta onto the end. Now you see that I've added this
@beta to this command, that is because at the time of this recording Ionic is in one of the
final beta stages for Ionic 2, so this is still required. If you're viewing this after the official
release of Ionic 2, this @beta may not be required. If you have any doubt simply check
the I documentation page shown here for the installation command. So I'm going to go
ahead and install it now, and that's all there is to it. Now that Ionic is installed, we're ready
to start creating apps.

Starting a New Project


To start a new project we simply use the Ionic command line tool. I'll type the command
now to start a new project. Now I've just typed out a multi-part command, so let's take a
closer look at each distinct part. The first argument is the command we want to run, in
this case start for starting a new project. Next we have the name of the application, which
here is Ionic-tabs-app. Then we have the application type, in this case we're using the tabs
template, but there are others like the blank template and the side menu template, which
I'll show a little later. Then I have some switches indicating v2 for Ionic 2 and ts for
TypeScript. It is possible to build Ionic 2 apps with just regular JavaScript, but I'll be
using TypeScript throughout this course. Let's execute this command now. And just like
that, our new application has been scaffolded and the supported npm packages have been
installed locally as well. Now I'm going to CD into the directory that was just created,
which is called ionic-tabs-app because that's what we named the application, and I'm just
going to open it in Visual Studio Code. You can use whatever editor you want, I prefer
Visual Studio Code, it's a great cross-platform editor and it works whether you're on a
Windows machine or a Mac, and you can see right here I can just open this directory and
we can see the code structure. We'll dive into the code structure quite a bit throughout
this course, but right now I just want you to see that this application has been fully
scaffolded for us just by running that one command.

Run App with Browser

Now that we have our application set up, let's look at the different ways we can run and
test our app. The simplest and most common way is to test our app in a local desktop
browser. First I'm just going to type Ionic. If we run Ionic with no command line
arguments, we'll get a helpful menu showing various features. For example, you'll see the
start command we ran to start a new project. Right under it we'll see the serve command,
which lets us test in a local browser, let's do that now. The Ionic serve command will
compile TypeScript and scss locally and then launch a web server. And here we see our
app in a desktop browser. When we first see our app in a browser it looks a little funny
in a full screen desktop browser. So there's a couple of things we can do. First, let's hit
F12 to get the developer tools and then right over here I'm going to toggle the device
toolbar and when I do that it gives a more mobile display. The other thing I'd like to do,
since mobile apps have a more vertically oriented screen here, is I like to dock my tools
to the right side of the screen, but you can do whatever your personal preference is here.
And you can see that we have an Ionic app and we can see the tabs that we set up. So for
example, we can switch between devices, Nexus 5, Galaxy S5, and we can see these
devices right here. And here are our tabs, I have a Home tab, About, Contact. I can see
the different tabs here. We have a fully running app in the desktop browser, makes it
really easy to test. In fact, I can even switch between an iPad, and we can see it's a larger
screen, but I can still have the tabs across the bottom. So testing becomes really easy.
Now another great aspect of this is that we have live reload. So what I'm going to do here
is I'm going to come into my pages folder, specifically the home screen, the home.html,
and let me just move this move this over to the side a little bit. And right here where it
says Welcome to Ionic, you can see this corresponds to this h2 tag right over here. So I'm
going to type instead Ionic 2 Pluralsight, and just by doing that you're going to see that it
reloaded and it shows Ionic 2 Pluralsight right here. Now in my Visual Studio Code I
have auto save turned on, so just by typing that it waited for a second or so and then saved
the file, Ionic then recognized that a new file had been saved and did an automatic reload.
In fact if we come back here to the command line where we launch the Ionic serve
command, you can see right here that it noticed the HTML change for home.html. The
HTML didn't actually change for tabs, so that just showed up, but home is where it
actually changed. So we got live automatic reload and it's very easy to test the app because
we can iterate so quickly with changes and viewing our changes on the screen directly.
The other thing we get when we launch Ionic serve is some basic commands, so we can
see that we have r or restart, q for quit, and a few others as well. So I'm just going to type
q here for quit and hit Enter, and how we've stopped the Ionic serve command, we stopped
the web server. For most of this course we will be using ionic serve to test the app because
it's so quick and easy to use. However, I want to show you a few other ways you can test
your app as well. We'll do that next.

Run App with Emulator

Running the app in a browser is awesome, but there are times when you might want to
use a true emulator. I'm going to show you how to run using the Android emulator. Now
before you can run this using the Android emulator, you must have the Android SDK
installed on your machine. I'll warn you in advance, installing the Android SDK is not a
trivial process. The installation of the Android SDK or iOS SDK is beyond the scope of
this course. I would probably have to take at least 20 minutes to show you the installation
for the Android SDK alone here. Instead let me point you to a few links, first on the Ionic
installation page, which you can see here, there are some helpful notes for installing on
Linux and on Windows. So if we click these red buttons here we'll get some notes for
Linux, on Windows I see some notes here as well. I strongly recommend you read all of
this in detail and make sure you've done all these steps. Also on this tab right where,
which you can see is on the Ionic-cli-faq, we have a section here for Android SDK, it
points out a blog post, even some emulator alternatives, and also an in-depth YouTube
tutorial for how to do it. Since you can follow along with this YouTube tutorial, this is
another reason why I'm not going to repeat that content in this course here. Again, just
make sure you followed all the steps. Once we have the Android SDK installed, we're
ready to run the emulator. The first thing I'm going to do is ionic platform add android,
and this will add Android specific resources to our project, such that it can run in a native
environment. And we have this folder in here called platforms, you can see I have one for
Android and not iOS because we only did the add Android platform, and this added these
resources that you can see here in this platform's folder. The other thing we can do next
is ionic build android and this will go through the compilation steps for the Android
platform. And you can see it's using the Android SDK to compile the project (Loading).
Now that that's done, we're ready to launch the emulator. So we'll type ionic emulate
android, and we can see that we now have our app running in the emulator, Ionic 2
Pluralsight we see right here. And we can navigate to these other screens, clicking the
tabs at the bottom, so there's the About screen, the Contact screen, and the Home screen.
Remember the emulator will provide a more native environment to test your app in
comparison to just running it in a desktop browser.

Run App on Device

There is no absolutely no substitute for running on a native device itself. We may do 90%
of our development using the convenient desktop browser, but invariably there are some
environmental issues that you simply must use the native device to test, or even
performance issues that might seem fine in the desktop browser, but don't perform so well
on the native device itself. Fortunately Ionic makes it extremely easy to test on your native
device. I'm just going to type in here ionic run android, and I already have my device
connected to my machine via a USB. So I'm going to show you the output here first.
Another nice thing is that it's actually faster to deploy to your device than it is to an
emulator. This is my actual device, I'm actually holding my device in my hand and I'm
tapping around the screen, so I just tap the About and I tap the Contact and I can actually
navigate around my screen. So what you're seeing on the screen is actually my device
being reflected on the screen. There's my home screen, I can swipe around between my
different apps. We can even see right there, ionic-tabs-app, that's what was just installed
locally on my machine. I can tap that and it can pop right up. Given how easy Ionic makes
it to test on your actual device, I strongly recommend you make this a consistent part of
your development workflow.

Run App with Ionic View

The next thing I'm going to show you is how you can use a tool called Ionic View to
quickly deploy and run your app on an actual device. Here I am at apps.ionic.io and I'm
going to log in. If you don't have an account, you can click here to get started with an
account. I already have one so I'm going to just log in with it right here. Apps.ionic.io
you can think of as Ionic's cloud, and you can see I've already uploaded a couple of apps
into their cloud previously. We'll upload another app, specifically the one we've been
working with so far. But before we do that I want to show you the corresponding Ionic
View app on an actual device. Here I have a look at my iPhone and this is not an emulator,
this is actually my iPhone, I'm holding it in my hand as we speak, and you can see I'm
swiping left and right. You can see the iPhone is simply being reflected into my computer
screen here. Here at the bottom you can see that we have the app called Ionic View, which
I've previously installed from the App Store. I'm going to tap that now. I've already logged
into it, and you can see here that I have the same two apps that we just saw from my
dashboard in Ionic's cloud. Now let's upload our app. I'm simply going to type Ionic
upload, and just like it's been uploaded to the cloud. We can verify that by coming over
here and I'm just going to refresh my browser, and now we see a third app right here, the
ionic-tabs-app. Let's go look at it now on the device. Here's the Ionic View app again, I'm
just going to pull it down and refresh. Now we can see I have a third app here called ionic-
tabs-app, I'm going to tap that, and we can see I have a couple choices. I'm going to select
the choice for view app, and right there it actually pulled the app down from Ionic's cloud
and you can see I have this app now running on the device in the context of Ionic View.
And I can actually tap around to these other screens here, and in this demo I'm using an
iPhone, in my previous demo I was using an Android, so right off the bat you're already
seeing different ways to deploy to different types of devices. You can certainly using
Ionic View with Android device as well. The Ionic View is a great way to quickly share
your apps. In fact, here I am on a Windows machine, but then I uploaded to Ionic's cloud,
and then I was able to quickly deploy it to my iPhone. It's also a great way to share your
app with other people as you're developing it.

Understanding App Structure

Now that we've looked at numerous ways to test and deploy our app, let's focus on the
code. Let's start by looking through the app structure that was originally generated for us
by the Ionic start command. The app folder is where you'll be spending most of your time
when developing Ionic apps. The app.ts is the starting point for any Ionic 2 application.
You can put an initialization code here. The pages folder is where you'll put the code for
the screens you create. When I expand the home folder, you'll see I have three files, a
TypeScript file, which is your Angular component, an HTML file and a scss file, which
is optional. Here we can see home.html and this is where I put the Ionic 2 Pluralsight
message earlier that we customized. My TypeScript file, which is my component, right
here is just pretty much empty with the constructor, and then I have my scss file, currently
no classes in here. In addition to the scss files that are specific to a screen, we can see
here that in the theme folder we can also provide styling globally in our app. By default
Ionic 2 uses scss instead of CSS, of course scss compiles down to CSS. There are courses
in the Pluralsight library dedicated to scss if you want to learn more about this technology.
For now, think of scss as CSS plus. Ionic goes through a compilation process and puts
the results in the www folder. For example, here if I expand build and pages, the pages
that we saw above get compiled and copied to this location. If we think of Ionic as a single
page application, and we should, the index.html file here is the single page that contains
the rest of our application. Specifically the ion-app element that you see here contains our
application, which is initially loaded from the app.ts file I showed earlier. There are a few
key files in the root of the application structure as well that you should know about. The
config.xml is the standard configuration file for Cordova applications. The gulp file
contains some key build tasks that Ionic uses, including some of the commands you saw
me run earlier using the Ionic command line tool. You are encouraged to modify this file
if you have custom build tasks that you want to run as part of your development workflow.
John Papa has a great Pluralsight course dedicated to Gulp. The ionic.config.json file
contains some basic config values for your Ionic app. The package.json file is the standard
file Node uses to configure installed packages. Like any Node application, the
node_modules is where the npm packages used by your application will be installed.
There are also some files down here at the bottom to help you configure TypeScript.
These work in conjunction with the typings folder, which contains any TypeScript
definition files we might be using in our app. We'll look at this more closely later in the
course. The resources folder contains media for such things like icons and splash screens.
We'll also look at this more closely later. The plug-ins folder contains any native device
plug-ins we might want to use in our app, such as the camera or geolocation. We'll cover
this in depth in a later module. You already got a brief look at the platforms folder when
I compiled the app for Android a little earlier. For the most part you won't have to
manually modify anything in this folder. Those are all the major components to know
about for the project structure of an Ionic 2 application. We'll look at many of these areas
more deeply as the course progresses.

Platform-specific Display

Another key differentiator for Ionic is that it will automatically adjust to platform-specific
displays. Here I have this running in my browser and I have Galaxy S5 selected as my
device. This selects the correct resolution and tells Chrome the user agent is an Android
device. Although keep in mind, this isn't a true emulator, just the app running in our
Chrome browser. Notice the icons at the bottom all look like typical Android icons. Now
I'm going to change this to iPhone 6 and refresh my browser. Notice how the icons all
now show iOS style icons. This was just a very subtle example of the differences, there
are more obvious examples that we'll see as the course goes on, for Android and iOS
differences. These are things like how the side menu and back button look, as well as
other components.

Hello World
Up until now I've just been doing a demo app that we generated using the tabs template.
Now I'm going to start a new project based on the side menu template and we'll use this
as the basis for the app that we'll be building throughout the duration of this course. This
will be the elite schedule app that we previewed a little earlier in the course. So I'll type
a similar Ionic start command, this time the name will be elite-schedule-app, instead of
tabs we'll use the side menu template, we'll still use v2 and ts. Now let's cd into the app
that we just created and let's open it in our editor. Now actually, before we make any
changes, let's just do an Ionic serve to see what the side menu template gets us by default.
And what we can see here is we have a side menu project, we can go to page 1, which we
already saw, page 2, some master detail views, we have a back button. You can see
Android specific back button right here. We could, of course, go to iPhone 6 and then it
will look at little bit different, for example if we go here and here, now we have the iOS
looking back button. Now let's add our first code to the project, this will be the typical
Hello World. We'll come in here to our app folder, specifically page 1, we'll start with
page1.html, and we're just going to add a button and we'll say Hello inside that button,
and we're going to add a click event to that button and the event is going to be sayHello,
that's the method that we're going to call. Now of course we need to create this method,
so we're going to go into page1.ts, which is the corresponding controller, and we're going
to create sayHello and I'm simply going to say console.log('Hello, World!'). Now because
we have Ionic live reload, saving that file just automatically refreshed the browser and
we see we now have our Hello button. I'm going to click this and sure enough you can
see we have Hello World that's now been written to the console. Now we've created our
basic application, you've seen how you can add code in a Hello World fashion. This is
going to be the basis of our application that we're going to build throughout the remainder
of this course.

Summary

This module laid the foundation for many of the concepts you should understand before
starting an Ionic project as well as several concepts we'll cover in more depth as this
course progresses. I started by showing you how to install Ionic and get up and running
very quickly. I then showed how you can use the Ionic command line interface to quickly
generate and start a new project. I also showed several ways to test your Ionic app, starting
with the simplest and most common method, which is to test using your desktop browser.
I then showed how you can run your app in an emulator, as well as running it natively on
an actual device. Ionic View also provides a compelling tool to enable you to deploy your
app to your device and share it with other people during development. It's important to
understand the app structure and we covered the major structural areas of the preliminary
code structure. We also got a quick taste on some of the features Ionic provides for
platform-specific displays. Finally we created a new app based on the side menu template
and we added some basic Hello World code to this app. We'll be using this app to build
upon throughout the duration of this course.

Navigation
Overview

In this module we're going to explore how navigation works in Ionic 2. Navigation in
Ionic 2 is completely different than navigation in Ionic 1 and has been rewritten from the
ground up. We're going to start out by talking about the navigation stack in Ionic 2. This
is the foundation we need to understand first. We'll introduce the skeleton for the
navigation of our entire app and put the preliminary views in place. With our baseline
pages in place, we'll then start to actually implement navigation in our app. I'll show you
examples of how the back button works with Ionic 2. We'll also take a look at how side
menu navigation works. We'll then look at how nav bars and toolbars work. For any
navigation system it's important to understand how to pass parameters between views,
and we'll take a look at that as well. It's important to understand the basics first, but once
you have that foundation, we'll take a look at some advanced navigation topics, which
include navigation parameters with tabs and understanding how to manipulate root
navigation.

The Navigation Stack

The primary aspect to understand about Ionic 2 navigation is that it's based on a simple
stack. Besides the stack providing a natural programming API for navigation, Ionic 2 is
also doing some things for us behind the scenes that we don't even realize to improve
performance, such as page caching in the DOM. New pages are pushed onto the stack in
forward navigation and popped off the stack when navigating backwards, just like you
would think for a typical stack. Most apps will use just a single navigation stack, which
is called the root stack, however, Ionic does support multiple navigation stacks, for
example, using a tabbed layout will contain its own navigation stack, which is
independent of the root stack. I'll show you an example of this towards the end of this
module when we start getting into more advanced scenarios. Ionic 1 was based on the UI
router component. Typical use of the UI router revolved around URLs, although this
wasn't 100% required as you could use named routes only, but with Ionic 2, since it's
based on the concept of a stack, actually, URLs don't factor in at all to basic navigation.
That's not to say that Ionic 2 doesn't support URLs, it does, in the form of what we call
deep linking, which is typically used to allow a user to jump straight into a view contained
deeper inside a native app, perhaps launched from a web browser. But for our purposes
in this course, we're going to stay focused on the stack based navigation. Let's show a
basic example of Ionic stack based navigation. When the app starts up we'll need some
page as our start page, let's call this our Home Page. This will be the root of the app
because it's the first page pushed onto the root stack. Then the user navigates forward to
Page 1. We can see that Page 1 is pushed onto the top of the stack, the page on the top of
the stack is the one that is currently visible to our user. We then navigate forward once
again and Page 2 is pushed to the top of the stack and visible to our users. Then let's say
our user wants to navigate back. Page 2 is popped off the stack and now Page 1 is visible
to our user again. If the user wanted to navigate back to the Home screen, they could hit
the back button again and Page 1 would be popped off the stack and the Home would be
displayed again. This is a basic example of how stack-based navigation works and it's
conceptually no different than what we do everyday navigating in a web browser.

Create Your Page Skeletons

Before we put a bunch of empty pages into our app, let's take a look at the basic
application structure for our screen navigation. The My Teams page is going to serve as
our root home page. We'll allow users to save favorite teams and they'll appear here
almost like bookmarked teams. Any team we designate as a favorite will appear on the
My Teams page and we can tap that team to jump directly to the Team Detail page for
that team. Once we're on the Team Detail screen we can navigate to the Game screen for
any of the games that are on that team's schedule. These three screens will be the heart of
the app. But let's suppose we need to first find a team. In that case, we'll go to the fine a
tournament screen and we can select a tournament and the go to the Teams page to find
a particular team in our selected tournament. From that page we can select a team to go
to the Team Detail for that team, where we can then choose whether or not to designate
them as a favorite. Before we even get into implementing navigation, we first need to
generate several pages for these screens. Let's start with the My Teams page since we
know that's going to serve as the home page for our app. So we'll go into the pages
directory and I'm going to do a new folder and we're going to call it my-teams. Let's put
a couple of files in this folder, the first one we'll say my-teams.page.ts. This is the
TypeScript file that's going to serve as our component. Let's also generate a corresponding
HTML page (Typing). Now you can see I've just put some very basic scaffolding in here,
we have an ion-header with an ion-navbar, we have a title in here. We have a content
placeholder. For the my-teams.page we just have a component, it's an empty class with
an empty constructor. We'll fill in the details as we go. Now the next screen I want to
create is the tournaments page. Now there's a couple of ways to generate these screens,
and in fact, the Ionic cli gives you some functionality for generating these pages. I want
to show you an example of that. I'm going to come in here and type Ionic, but this time
generate page and we'll call it Tournaments. And you can see that it created these three
files for us, an HTML, a TypeScript file, similar to what you saw me do for the Teams
page, and also a scss file, and it gives you this helpful message, don't forget to put the
scss file in your app.core.scss file. Let's go see what it generated. You can see that we
now have this folder down here called tournaments, if we open HTML, we can see very
similar to what I created for the my-teams page. Tournaments.ts, same thing, very similar
empty class with a constructor that's injecting a nav controller. Now this is all well and
good and I highly recommend you use the Ionic generator if it helps you gain efficiencies,
there's a couple of things in it that you may grow a little tired of, which is these helpful
comments are great in the beginning, but then as you keep going you may not want to see
these comments all the time. There's also some extra white space in here. Also, you might
have a different convention for file names than what you have. For example, I explicitly
name each component with a .page, you might have seen this, and it didn't do it down
here, although it did actually name it tournamentsPage inside the class. If you want to use
this convention, it's fine, if you want to use a convention slightly different, like the one
I'm using, that's also fine. You should do what makes you happy here. Let me close these
pages. I'm going to show you yet another alternative. You can use a yeoman generator,
I'm going to cd into this app folder and specifically cd into my pages folder and I'm going
to use a yeoman generator that I just use locally, sm for Steve Michelotti, and then I have
a subgenerator called ionicpage and I'm going to generate a Teams page, and you can see
it just generated these multiple files. Now if you've never used yeoman before, I have an
entire Pluralsight course dedicated just to this topic, so you can view that course and learn
how to build your own custom yeoman generators. To show all the yeoman generators
here would be beyond the scope of this course, but again, I have an entire Pluralsight
course dedicated to it. But let's see what was just generated with the Teams page. We can
see the teams folder was generated, I have the teams.page.ts, it's got an empty class, no
extraneous comments, teams.page.html, generated exactly how I want to see it
implemented. It follows my preferred naming convention, which is to put the .page in the
file name. But again, you can do these however you want. Let's go generate a few others.
I'm actually going to delete the tournaments folder that was previously generated by the
Ionic tool, and let's generate a few pages (Typing). We'll generate the Tournaments page,
then we'll generate the TeamDetail page, next the Game page. You can see we're starting
to generate a whole bunch of pages in here, in fact, let's delete page 1 and 2 because that
was just there from the default project template. And because we deleted page 1 and 2,
we have to come in here and delete these two lines. I'll just leave these comment for now
so we can see what the syntax looks like. Another thing I highly recommend to do is in
the pages folder, you want to create a new file called pages.ts, this is going to make your
life a lot easier when you do your imports. And what you can see here is I have exported
each one of the components that's in the five screens that I just created. This is going to
make your life easier when you're doing imports of a certain page, and let me show you
an example of that right now. We're going to go into our app.ts file, and you can see we're
getting the red squiggles because page 1 and 2 no longer exist, so let's just remove those.
And I'm going to put a new import in here and we'll say .pages, that's that pages.ts file I
just used, and now you can see we're getting IntelliSense for the different pages we have
in there, so I'm going to say the MyTeamsPage. We're also going to remove this pages
array down here on line 15 and the root page is now going to be MyTeamsPage. We need
to remove the array here as well. Finally let's go into the app.html and I'm just going to
change where it says menu and we're going to call it Elite Schedule. Now that we've
actually put these page skeletons in place, now we're ready to actually implement
navigation.

Using the Navigation Stack

Let's implement a simple example of how we can use the navigation stack to push a new
page onto the stage, which will perform screen navigation. Here I am in the HTML of the
MyTeamsPage and I'm simply going to add a new button, we'll just make the text Find a
Tournament, and in here I am going to simply put a click event and we'll call a method
named goToTournaments. And let's just put some text right above this and it's just to tell
our user, we're not currently following any teams, but we can instruct them that they can
first select a tournament and follow teams from there. But now let's go implement the
code for the goToTournaments method. I'm going to flip over here to the my-
teams.page.ts and we'll add the method gotToTournaments. Now when we do navigation
in the Ionic framework, we need to use a nav controller, so what I'm going to do is I'm
going to do my import for the Ionic framework, which is ionic-angular, and we're going
to import a nav controller. Now we're going to use typical Angular 2 constructor injection
to inject that nav controller into our class. Notice I made this private, this is not only going
to inject it, but it's also going to give a private instance member available inside the class.
This is standard Angular 2, so this will enable us to refer to that property, this.nav, there
it is you can see it in IntelliSense, .push. And we need to push a page into the stack, so
we need to import that page next (Typing). You'll see it's our TournamentsPage here and
so we'll push the TournamentsPage onto the stack. That's all there is to it, now let's go run
the app. Here's our Find A Tournament button, which we just added, you can see we
added the text above it. I'm going to click that button and you can see it's navigated us to
the Tournaments page. Also notice that a back button has appeared here, we'll talk about
that more in a bit. Another thing to note is the URL never changed during that navigation.
So there you have it, overall you can see just how easy it was for us to implement simple
navigation using the navigation stack.

Back Navigation
One thing you saw in the last demo was that when we navigated from the MyTeamsPage
to the TournamentsPage, a back button automatically appeared on the TournamentsPage.
Let's see that again. I click Find A Tournament, we see a back button here, we can click
it, we go back to the MyTeamsPage, which of course does not have a back button because
that was our root page. The rule is that if a page has an ion-navbar element, a back button
will automatically appear if it's not the root page. To illustrate this, let's completely
reverse the order of these pages to see this in action. The first thing I'm going to do is go
to the app.ts page and I'm going to add an import for the TournamentsPage here. Then
I'm going to change the route page, instead of being MyTeamsPage, let's make the root
page that TournamentsPage. Let's now go to the tournaments.page, let's add a button
similar to what we did previously on the my-teams.page. So we need a click handler here
and we'll just call this navigate. So to the tournaments.page.ts let's add that navigate
method, and we've already injected a nav controller here, but we need to navigate to the
my-teams.page, so let's add an import for it (Typing). And we can simply come down to
the navigate and say this.nav.push(MyTeamsPage). So let's remember what we did here,
we went to the app.ts and we changed the root page to be TournamentsPage instead of
MyTeamsPage. We also added a button to the TournamentsPage, which navigated
directly to the MyTeamsPage. Let's see the app again. So we can see here is the app is
refreshed, instead of My Teams being the root home page, now the Tournaments page is
the root home page, and we have this button, Go To My Teams, and you'll notice that the
Tournaments page no longer has a back button, that's because it's now the root page. We
click Go To My Teams, now we go to the My Teams page and you can see this one does
now have a back button and we can navigate back to the Tournaments page. So this is
just an example to illustrate that the back button isn't hard coded in the navbar, it's going
to appear automatically on a navbar if it's not the root page. So let's just change everything
back to normal because we actually do want the MyTeamsPage to be the home page. So
we're going to come back here to the app.ts, let's make the MyTeamsPage the root page
once again, and now I'm going to go to the tournaments.page and instead of Go to My
Teams, I'm going to change the text here to Back, and then in the tournaments.page we
see the navigate method here, what I'm going to do instead of nav.push is I'm going to
manually go backwards by calling the pop method. Now let's run the app again. We can
see the My Teams page is now the first page, as it should be. I'll click Find A Tournament.
Now we know we can use the back button here, which automatically gets added, but
instead let's click this back button to where we manually said this.nav.pop. We're going
to click back and sure enough that pops the page off the stack and we're back to the
previous page, which is the My Teams page. So as you can see, the back button is pretty
automatic in the Ionic 2 framework. If you have a navbar on the page, the back button
will anatomically appear if it's not the root page, but in addition to that, you can always
manually navigate backwards by calling the pop method directly.

Side Menu Navigaton

Notice our side menu navigation disappeared when we added all these new pages, this is
because we need to be explicit about which pages the side menu icon will show up on.
Let's go over to the my-teams.page and make a couple of changes. First I'm going to
change this ion-navbar to ion-toolbar. Also I'm going to give this a secondary attribute so
that it has a little bit of a different color. Then above it I'm going to put an ion-navbar and
let's make this primary, and inside this we're going to have a button that has an ion-icon
inside of it. And this ion-icon, we're just going to give it a name of menu, and that is going
to be what makes the side menu icon show up, and we'll talk a little bit more about icons
in greater detail later. Also on this button, we're going to give it a menuToggle attribute,
this is going to indicate to the Ionic framework that when this button is clicked it should
toggle the menu to hide and show it. And finally, under the button we're going to put ion-
title, and inside we'll just say Elite Schedule. Now a couple other things we need to do
before we run it, let's go over to app.html, this is where the actual ion menu that represents
the side menu comes. Now previously in the app.ts file we had this pages array that I
commented out completely. So this ion-list here is doing ngFor over that pages array, but
right now it's not doing anything because we no longer have this pages variable because
we removed it previously from the app.ts. So what I'm going to do is I'm going to take
out this ngFor and we'll say this click is going to say goHome, and we'll have a second
button in here that's goToTournaments, Find a Tournament. Also above these buttons
we're going to put an ion-list-header and we'll just say navigate to show that this is the
navigation buttons for our side menu. Finally, in the app.ts we need to make sure that
goHome and goToTournaments methods are present. And we don't need this openPage
method anymore, goHome (Typing), goToTournaments. Now let's go have a look at our
side menu navigation. What we can see here now is that we actually have this icon for
the side menu. This first navbar we gave it the primary attribute, which is giving it this
nice blue color. In the toolbar we gave it the secondary attribute, that's what's giving it
the green color. If we click on this button here, we can see the side menu comes out,
there's Navigate, which is our list header, and we have these two buttons for Home and
Find a Tournament. If we go Find A Tournament, we see we go to the Tournaments page,
if we click Home, of course, it sends us right back to the home page. So this is how basic
side menu navigation works in the Ionic framework.

Navbars and Toolbars

A toolbar is a generic bar that can be used in many different ways. A navbar is a
specialized toolbar that specifically is meant to provide navigational functionality and
comes with an automatic back button. Navbars must be placed inside an ion-header
element. In a previous example we saw that I used a toolbar for this My Teams area right
here in green. Let's clean up some of the other newly added pages so that the side menu
button shows up on the correct pages. We'll also add some temporary hard coded data.
Let's start out on the my-teams.page. Right here we can see the My Teams toolbar, which
had the secondary attribute which gave it the green color we just saw. This is a good
example of just a generic toolbar. Now let's open the tournaments.page. Let's change this
title to Select a Tournament. And we don't need this back button anymore, that was just
for demonstration purposes earlier. We're going to replace that with some hard coded
data. I want to add an ion-list and inside the ion-list we're just going to put two buttons,
this first button we're going to call the March Madness Tournament and this is going to
an ion-item and we're going to give the click itemTapped. Let's copy this and let's just
give it a different tournament name, Summer Showdown. Now in the TournamentsPage
component file let's add the TeamsPage to the import and let's add that itemTapped
method, we don't need navigate anymore, so let's just rename that itemTapped. And
instead of popping it, we're just going to push the TeamsPage. Let's take a look at the app
to see what we have so far. Let's click Find a Tournament. We can see it says Select a
Tournament, there's our two hard coded teams. In fact, let's go back and make this
primary. Now we have the nice blue color where it says Select a Tournament. If we tap
either one of these teams it takes us to the Teams page. Let's go fill that in a little bit now.
We'll open up the teams.page. Let's make sure navbar says primary to give it that blue
color, and inside the ion-content we're just going to hard code a couple of teams, HC Elite
and Team Takover. Each one of these is calling an itemTapped method, let's add that to
the teams component (Typing). Let's make sure we import the team detail, and we can
just say this.nav.push. Let's take another look at our app. Find a Tournament, here's the
tournaments page, we'll select a tournament, there's teams. Notice we have the nice
primary color here on the blue navbar. We select a team, now we're in Team Detail. Let's
make sure Team Detail shows a blue color too. We'll just come in here to the ion-navbar
component and add primary. And you can see we've gotten all the way to Team Detail. It
was very easy for us to control the colors of the navbars and toolbars. The navbars get
this automatic back button, which we can hit the back button here, now we go back to
Teams, now the Tournament screen, and we can go all the way back to the My Teams
page. And here on the My Teams page we have a generic ion-toolbar, which you can see
here in green, because we used the secondary attribute. Ionic navbars and toolbars are
very easy to use and I encourage you to always make sure you have them looking the way
you want in your app.

Navigation Parameters

So far you've seen me navigate from screen and screen and I've done this without passing
any parameters. But ultimately we need the ability to pass data between screens because
we need to know which tournament or which team we selected to get to the next screen.
Let's take a look at navigation parameters now. I'm going to come in here to the
teams.page and we're going to add some hard coded data. So I've just added three hard
coded team and you see each team has an id and a name. Now I'm going to go back to the
teams HTML, let's take out this hard coded button, and on this first one we're going to
add an ngFor and we'll say let teams of teams, so it's that teams array that you just saw
me add to the teams component. Now in the itemTapped method we'll just add event and
team. So the team we're passing as that second argument is the individual team as we're
iterating through the array, and then instead of hard coding HC Elite for the team name,
we'll say team.name. Now let's flip back to the teams page and in this itemTapped method,
we'll add event and team. Now in this call to the push method, we're going to add team
as the second parameter and so that's going to be passed as a navigation parameter to the
next page. So we're going to the Team Detail page, let's open that up, and we're going to
add navParams to the import statement and we're also going to add it to what we're
injecting into the controller. Let's add a team property, and inside the constructor all we're
going to do is we're going to say this.team = this.navParams.data. And let's put a
console.log statement so we can see what we're getting (Typing). Now for the Team
Detail page, instead of just saying Team Detail, we're going to take that out and we're
going to say team.name. So when we get to the Team Detail page we should actually see
the name of that team. Let's start over. So we go Find a Tournament, now Find a Team.
Now you can see this time we have three teams because we have that hard coded array in
our TypeScript code. I'm going to click this last one for DC Thunder and what we can see
here is that we're on the Team Detail screen and we now see DC Thunder actually in the
title. It's no longer just hard coded to say Team Detail. Additionally, we can see over here
on the navParams that we have this object that has a data property and inside there's the
team we passed as a navigation parameter. It had an id of 3 and a name of DC Thunder.
So we can pass any JavaScript object we want as navParams. You will use navigation
parameters all the time in your Ionic apps, so this is a construct you want to make sure
you understand very well.

Tabs
The navigation in our app is starting to come along well now. We've got our My Teams
home page and we're able to get to the Team Detail screen. But let's say we want to
enhance the Team Detail, specifically we want to be able to show Team Detail and
Tournament Standings so we can see where a given team is ranked. When we want to
switch between two views, tabs are a great option. With our adjusted diagram we've just
introduced a new page called Team Home. We're going to put tabs on the Team Home
Page, then the Team Detail and Standings page are going to be the tabs themselves. One
of the nice features is Ionic tabs is that we just use normal pages as the tab pages, so a
given page could seamlessly be used as a normal page or a tab page. To make this happen,
we'll need to execute a couple of steps. First we need to add two new pages to our app,
one will be the Standings page, the other will be the Team Home page, which will be the
tabs container. Then we'll add the tabs to the Team Home page, which will become the
container for Team Detail and Standings. Then we'll fix-up a couple of miscellaneous
navigation issues since we're shuffling some pages around. Let's implement this all now.
First let's add these two new pages. First I'll add the Standings page, then let's add Team
Home (Typing). Now that we've added those pages, let's make sure we add the
appropriate exports (Typing). Now let's go into the team-home.page. I need to import the
two pages that we want to use for the tabs (Typing). Let's also add class members for
these two (Typing). So we have a teamDetailTab, which is just going to be the
TeamDetailPage, and similar the standingsTab will be the StandingsPage. Now in the
team-home.page.html, I'm actually going to take out the ion-content because this is where
we're going to put our tabs. Normally we put all our content inside of ion-content,
however Ionic tabs do not go inside of ion-content. You can think of them as stand alone.
Now let's add a couple of tabs, first one, ion-tab. In here we're going to add a few attributes
- tabTitle, this is going to be equal to Team. Now we need to assign a root attribute and
this is going to be assigned the properties that we added for each tab, so this one is the
teamDetailTab. And then a tabIcon for right now, we'll make this equal to basketball.
Now I'm just going to copy this and paste it right below and change the values that are
different, so this second one is going to be Standings and then this one right here is going
to be standingsPage or actually standingsTab, and then for the tabIcon let's make it
podium. Now if you're not sure where I'm getting these icons right now, don't worry, I'll
cover that in a little bit more detail a little bit later in the course. Now we need to fix up
some navigation because previously we've been navigating directly to the Team Detail
page, now we need to navigate to the Team Home page. To let's open the Teams page
right here and instead of TeamDetailPage we're going to change this to TeamHomePage
and similarly down here in the itemTapped we're going to change this to TeamHomePage.
Now just for clarity, I'm going to add a couple of titles here. I'm going to go into the team
detail HTML page and let's add an h2 that just says Team Detail, and I'm going to do the
same thing in standings. I'm just doing this temporarily because I want it to be 100% clear
which page we're on and which tabs we're seeing. Let's go run this now. We'll come to
the Tournaments page, and now on the Teams page instead of navigating to the Team
Detail, this page is now going to navigate to Team Home. So I'll click here, we see Team
Home here and Team Detail as a subpage and we can see the tabs at the bottom, Team
with a little basketball icon, and Standings with a podium icon. And if we click between
the two, we can easily see that we're clicking between these two tabs. However, one thing
that's a little bit less obvious is that the Team Detail previously had a navbar and it's
actually being hidden now. Let me prove this to you by changing the title in the Team
Detail navbar. So we'll come here to Team Detail and we're just going to change the title
here to Detail page (temp). We'll come back here and you can see it's not there, we can
even search for it. You can see I'm mouse hovering over it, it's highlighted, but it's behind
the Team Home navbar. Since it's being hidden anyway and we're using it as a tab page
from the Team Home, let's just comment it out and see what happens. So we'll come back
to Team Detail and we're just going to comment out this ion-header element completely.
Now when we flip back here, something's not right. I had the Team Detail that was
displayed right here and we don't see it anymore. The Standings is still there, but Team
Detail is not. What's happened is it's actually been pushed up, so it's actually, now the
content is hidden under the navbar. So let's see how we can fix this. Let's uncomment this
first and foremost, and at this point all we really need to do, since we're not using it, is we
need to add an empty ion-navbar. So even though we're not using it we still need a
placeholder there so that the vertical space at the top will adjust accordingly, and we'll do
the same thing for Standings (Typing). Now if we look again, we see everything's
working fine. We want the navbar shown from the Team Home, and we're seeing that,
but we also have vertical spacing correct for Team and Standings. Now one thing to
understand is this absolutely is an edge case. Normally when you're using tabs, it's your
root page so you never have to worry about this. This is an edge case because normally
you wouldn't have tabs on a non-root page. I'm intentionally trying to show you some
edges cases in this course because real world apps don't always fit into boilerplate. So the
takeaway is that this is a work around and a work around you will only have to use for
the case where tabs are on a non-root page, which is uncommon. But for now, at least we
have it displaying correctly. However, now we have a different issue and that is we've
lost our navigation parameters with the tabs. In fact, if we go back to the console and we
look at navParams, we can see that we now have this empty object and previously we had
a team that was correctly being passed in. So we need to figure out how we can fix that
now. We'll address this issue next.

Navigation Parameters with Tabs

At this point we've implemented tabs and they're looking fine, however we've lost our
navigation parameters. If we come back here, you can see I clicked DC Thunder and we
used to have DC Thunder nicely displaying in the title, and we don't see that anymore.
We need to fix that now. First of all the Team Home page needs to be aware of the
parameters, DC Thunder, but not only that we also need to make sure that these tab
subpages have access to that navigation parameter as well. The first issue is relatively
straightforward. We're going to add a team property right here at the top and we're going
to use navParams, just like we've used them previously. So I'll put it in the import
statement as well as inject it into the constructor. And in the constructor I can say
this.team = this.navParams.data. Also in team-home.page.html, instead of just saying
Team Home, we want this to say team.name. Now let's run it to make sure that what we've
done so far is working. Here we'll click DC Thunder, and sure enough we can see DC
Thunder right at the top, and actually now that I'm seeing this, I realize we don't have the
blue navbar, let's add that real quick. Okay, now we have the blue navbar there. So we've
got the Team Home knowing about the nav parameters, however, if you remember this
console statement that we put here was from the Team Detail, and this is still showing an
empty object, let's fix that next. And just to be 100% clear, let's come here under the Team
Detail, let's put an h3, and we'll say Name: is team.name. So we still have DC Thunder
there of course, but the name is empty, so just like we have nothing in the console we still
see that we have nothing displayed for the name here. Essentially what we need to have
happen here is that the team property that we know we already have access to as part of
the team page, we need to pass that into the tabs. In order to do that, what we have to do
is use the rootParams property. This attribute is how we can pass it in. So we'll just say
team right here. I'll copy that and I'll paste it right in here, so we're using the rootParams
attribute to send the team into these subpages. If we open this page right here, it's now
going to be a nav parameter, just as if we pushed in that nav parameter using the normal
nav.push method. Let's click DC Thunder, and sure enough, now we can see DC Thunder
is being passed in, not only to the Team Home page, but also to the tab subpage, and sure
enough we no longer have an empty object printed out to the console either. Although
passing parameters into tab pages isn't necessarily an everyday thing that you're going to
need to do, it's definitely important to know because in real world applications it will
come up.

A Closer Look at Root Navigation

At this point the navigation in our app is starting to look pretty good. In fact, at first glance
it looks virtually complete. However, we currently have a subtle bug that we need to fix
that involves understanding root navigation a little better. Remember, Ionic can have
multiple navigation stacks and you heard me say earlier that the tab control has its own
navigation stack. So if we look at the diagram here, the five main screens, My Teams,
Tournaments, Teams, Team Home, and Game are all within the root navigation stack.
However, the screens contained within the tabs of Team Home, which are Team Detail
and Standings, are in their own navigation stack internal to the tabs on Team Home. Let's
look at a concrete example that illustrates this and how to fix the bug that I mentioned.
Here I am on the Team Home screen, you can see I've selected the team DC Thunder, and
I could hit the back button a couple of times to get back to the home screen, but let's
suppose I want to provide a home button here so anytime that a user is on the Team Home
screen they can directly go back to the My Teams home page. Let's do that now. So here
I am on the Team Home page and what I'm going to do is after the title, in the navbar, I'm
going to add an ion-buttons group and we're just going to give an attribute of end so it
places the buttons on the right side end of the navbar. And I'm actually only going to put
one button inside. And we'll say ion-icon and name = home. And we'll give it a click
event of goHome. Now let's go add the goHome method (Typing) and let's make sure we
include My Teams Page, and we'll simply say this.nav.push(MyTeamsPage). Now let's
run the app to see what we have. So let's navigate all the way down to the Team Home
page, and here we have the Home button that we just added. I'm going to go ahead and
click this, and it does take us back to the home page, however, it's weird to have a back
button on the home page, and this isn't exactly what we wanted. We basically want the
user to start over again, which doesn't include having a back button on the home page,
which we think of as our root page. So let's first fix this issue. What I'm going to do here
is comment this out because I want you to see what the old code looked like, and we're
going to replace it with this.nav.popToRoot, and now with that in place, let's see how the
behavior changes. So here we are in our screen, let's navigate back to the Team Home,
we'll click the home button, and notice that there's no more back button, we've popped all
the way to the root, we've essentially cleared off the entire stack, popped the entire stack,
and now we can see our normal navigation side menu at the top instead of the back button.
Now in this last example we were navigating from the toolbar. Let's see what happens
when we navigate from an inner tab page, specifically we'll use the Team Detail page. So
we'll go ahead and open the team-detail.page here and I'm just going to add a button and
we'll say Go Home, this is just going to be a temporary button, we'll add a click event,
goHome, and then let's go add this goHome method (Typing). We'll need to import the
MyTeamsPage and let's initially use the same code as before,
this.nav.push(MyTeamsPage). So let's start from the beginning, we'll say Find a
Tournament, we'll go to the DC Thunder page, here's our Go Home button, which I push
the MyTeamsPage to the stack, let's click it, now we have some extremely strange
behavior. You can see that even though we're on the home page for My Teams, it is
showing DC Thunder in the main toolbar. This is happening because the tabs have their
own independent navigation stack. Again, this is an edge case because you typically don't
have tabs on a non-root page, but again, I want you to be well prepared for different
scenarios. The fix for this scenario is slightly different than the technique we used before.
To illustrate this, let's see what would happen if we attempted to use the same technique
as before with popToRoot. So let's comment this and I'm going to add
this.nav.popToRoot. Now we're going to click the Go Home button, and you can see that
nothing is happening when we click it. This is because this is an inner tab page,
specifically Team Detail is an inner tab page. So as far as the Team Detail page is
concerned, we're already at the root. What we need to do is get a handle to the nav
controller on the parent containing this page, which is the Team Home page, and we need
to pop to the root on that navigation stack. Let's do that now. So what I'll do here is
comment this out again because I want you to be able to see what the old code looked
like, and I'm going to replace it with this.nav, this time I'm going to refer to parent, which
are the tabs itself, and then parent again, which is the Team Home page, and then say
popToRoot. And that's the line of code we need. Now when you first look at that it may
look a little strange because it's parent.parent, so a trick that I use a lot is just to do a
console.log and we'll say we're outputting parent here and we'll say this.nav.parent and
this will just allow me examine that object in the Chrome dev tools. Let's go run this now.
So we'll start from the very beginning and we'll go in to the DC Thunder Team Home,
this time when we click Go Home, it correctly takes us back to the root, no back button,
and if we examine the console we could say this is the parent and this has its own parent
property here, which that you can notice, it's a nav itself. And once we're there we can
call popToRoot. So again, these are some of the subtleties that you won't always run into
on a day to day basis, but when building real world apps, when you do have a little bit
more complex scenarios, they are good to be aware of. Now our app is behaving as
desired. Although I was just showing this one for demonstration purposes, I'm not really
going to put this button in here for real, so let's remove it now. So we'll come back here
to the Team Detail, we'll remove this goHome method, we'll remove the import, and we
don't need this button anymore either because we're not going to use it in the real app.

Summary

This concludes the module on Ionic 2 navigation. We started out by looking at the Ionic
navigation stack so we could get a conceptual understanding of it first. I then generated
some more pages so we'd have several pages to navigate to and we put our page structure
in place. We then did our initial implementation by using the navigation stack API to
navigate between screens. I showed how the back button will automatically appear in the
navbar if it's not on a root page. I also showed how we can use the pop method for back
navigation. I implemented the preliminary side menu navigation and showed that the
Ionic side nav control is quite easy to use. We then looked at navbars and toolbars. I
showed a couple of demos for navigation parameters. This included basic nav parameters,
as well as how navigation parameters work when using tabs. We concluded this module
with a few more advanced topics including tabs and how tabs have their own navigation
stack. We also explore the root navigation stack in more depth, so that we know how to
handle more advanced scenarios if and when those situations arise in our app. This
concludes the module on Ionic navigation. In the next modules we're going to explore
numerous Ionic 2 components in great depth and our app becomes more robust we'll add
some more nice features to the navigation along the way.

Working with HTTP and Lifecycle Events


Overview

In this module were going to incorporate HTTP into our application. Working with HTTP
is one of the most important aspects of building a mobile app and I'll show you the best
ways to do this with Ionic 2. We're going to start by setting up our backend. We're
specifically going to use Firebase, which is a well known backend as a service. We're
then going to create a service in TypeScript that will have the responsibility in our app of
interacting with HTTP. I'll show you how you can use promises to work with HTTP data.
I'll then give you an introduction into the lifecycle vents available in an Ionic 2 app. This
will be followed by a demonstration of how you can load data as part of the lifecycle.
Working with promises is great, but with modern Angular 2 and TypeScript code RxJS
is becoming the standard for working with HTTP. I'll show you how you can do this. I'll
show you how you can use the loading component to provide a visual indication to your
user that data is being loaded in the background. I'll conclude by showing how you can
add third party libraries to your Ionic apps, specifically I'll use lodash so we can
manipulate and filter the data we're receiving over HTTP. Let's get started.

Setting up Your Backend

We're going to use Firebase, a well known backend as a service to serve as our HTTP
web API for this app. You can sign up to try Firebase for free, no credit card required,
and it's easy to get started. A full review of Firebase is well beyond the scope of this
course. In fact, Joe Eames has a couple of Firebase courses in the Pluralsight library, you
can see the URLs here. And I strongly encourage you to watch those if you want to get
more in-depth information on Firebase. Let's get our Firebase setup for our Elite Schedule
app. Here I am in the Firebase console and I want to create a new Firebase project. We'll
give it the name elite-schedule-app-i2, for Ionic 2, and Create Project. And in seconds the
Firebase has been created. I'm going to click Database. Right now my database is
completely empty. Let's seed the entire database by importing a premade JSON file. What
I'm going to do here is I'm just going to open this in Explorer and I'm going to copy and
paste a JSON file right here called elite-schedule-firebase-data.json into the root of my
project. This is a JSON file I've already created with a whole bunch of data. We're going
to import this into Firebase. I'm putting the file here in the root directory of my application
so you can access this file in the code download available for this course on the Pluralsight
website. In addition, you can also grab the file from the GitHub repository I showed you
in the first module of this course. Let's import it now. I'll come over here and I'll say
Import JSON, I'll browse through the file, and here it is right here, and we'll click Import.
And now we have a fully seeded database. I can see I have four tournaments here, Cager
Classic, Holiday Hoops Challenge, and in fact I have tournament data for each one, so
the Cager Classic starts with this GUID 3dd, and here it is down here, 3dd. So if I expand
that I can see all the games, all the locations, standings, teams, all the information for
each tournament. I'm going to go to the Rules tab and I'm going to change the read
property so that it just says read equals to true, which will enable essentially anonymous
access. If I come over to the data, for example, let's look at the data right here for this
tournament, I'm going to copy the URL. We can go to a tool like Postman, paste the URL
here, and then I'm going to end with .json extension so that it returns it as JSON, not that
HTML page. Click send, and here's all the JSON data that's coming back. One final note
about the Firebase data here, I'm using Firebase purely as a convenience mechanism for
a generic HTTP endpoint. I won't be using the Angular Firebase library and I'm not
necessarily even going to be following all the Firebase best practices. For example, you
can see in this data I'm using traditional arrays, which is not always a Firebase best
practice. Again, to learn more about these aspects of Firebase, I encourage you to watch
the Pluralsight courses I pointed out earlier. For this course, I'm just trying to have an
HTTP endpoint in place that looks like the data you'd most commonly encounter for most
web APIs.

Create Service to Interact with HTTP

Now that we have our HTTP web API in place, we want to create a service in our
TypeScript code that has the single responsibility of interacting with our HTTP data. I'm
going to come in here to the app folder and I'll create a new folder and we'll call this
shared. Inside this shared folder, we're going to create a new file and we're going to call
it elite.api.service.ts, and let's add a new service. We're going to call it EliteApi, and in
fact, I'm not going to use the word service at the very end of it here, and the first thing
with working with HTTP data is that we want to add an import, this is going to be from
angular/http, and specifically we're going to bring in the HTTP as well as the response
objects. And I want to inject this HTTP into the constructor. Now I'm going to create a
private variable called baseUrl which is the base URL for our web API. In order to get
that, I'm going to go back over to Firebase. Here's my base URL here. I'm going to copy
this, and I'm going to paste it right in here. Now similar to what I did up here in the pages
directory where I created a pages.ts, I'm going to do the same thing in the shared folder.
So I'll come in here to shared and say New File and we'll call it shared.ts and in here we're
simply going to say export * from elite-api-service, and any other new files we put in the
shared directory will add to the export statements here. Now there's a final thing we need
to do to make this available on our app. We need to go to the app.ts file here. And I'm
going to add an import for the shared directory, and of course, this is going to be the
EliteApi right here. Additionally I'm going to add an import for angular/http, specifically
HTTP_PROVIDERS. Now under the component, right here, after templateUrl, we're
going to add providers and we'll add EliteApi and HTTP_PROVIDERS. Why do we do
this? This is standard Angular 2, we're injecting these providers here so that they'll be
globally available to our entire application. Now we're ready to use our elite API service
in our individual screens.

Working with Promises

Now we're ready to add our first method to our elite API service to get HTTP data. For
this first example we'll use promises. Soon I'll show how you can also do this with RSJS,
reactive extensions. So let's add our first method, getTournaments, and what I'm going to
do in here is I'm going to say return new Promise, we'll have an arrow function here, and
we're simply going to say this.http, that HTTP property is what we injected into the
constructor, .get, so that represents an http.get. I'll use some string interpolation here so
that we have this.baseUrl/tournaments.json. Then we're going to say .subscribe and this
is the result, the response, we're going to call our resolve method, passing in
response.json. And that's it. Now we're ready to use this method in our code. However,
before we utilize it, let's take a minute to first understand Ionics lifecycle events.

Lifecycle Events Overview

Ionic 2 supports numerous lifecycle events. These are special methods that you can
implement that automatically trigger at specific times during the page lifecycle. The
ionViewLoaded event runs when the page first loads. It's important to remember that this
only happens once when the page first loads, not necessarily every time the page is
navigated to. Ionic 2 does some performance optimizations in the background and caches
pages for increased performance. So let's say you navigate back to a page you were
previously on, this event won't fire a second time because it's already loaded.
IonViewWillEnter runs for a view right before that view is navigated to and shown to the
user. This will always fire, even if the page was previously loaded. IonViewDidEnter runs
for a view right after that view is navigated to and shown to the user. Like
ionViewWillEnter, this will also fire even if the page was previously loaded.
IonViewWillLeave runs right before a view is navigated away from, and
ionViewDidLeave runs right after the view is navigated away from. IonViewWillUnload
triggers right before a particular view is about to be unloaded. Alright Ionic 2 is making
some performance optimizations with caching, it will unload a view completely, for
example, when it's popped off the navigation stack. IonViewDidUnload triggers right
after a particular view is unloaded. Again this can happen when a view is being popped
completely off the navigation stack. Let's have a look at these lifecycle events in action
and see how we can leverage them in our code to load data at the appropriate time.

Load Data Within Lifecycle

First I just want to show a contrived example so that I can illustrate when the Ionic 2
lifecycle events fire. Here I am on the Tournament page, and what I've just done is I've
added several of the lifecycle events, ionViewLoaded, ionViewWillEnter, WillLeave,
and DidUnload. And you can see each one is just doing a console log statement to tell
which event it's inside of at that moment. Now let's go navigate to that Tournaments page.
When I do, you can see the ionViewLoaded event and the ionViewWillEnter lifecycle
events were invoked. Let's now go to the next screen. We can see the ionViewWillLeave
also got logged, but you'll also notice that screen did not get unloaded. Let's now go back,
the ionViewWillEnter just got invoked. Now let me go back one more time. If I go back
all the way of course I get ionViewWillLeave, but this time I also got ionViewDidUnload
because it was popped completely off the navigation stack. So this illustrates when each
of these events fire. So one rule of thumb to keep in mind is if you want data to be loaded
when the page first loads into memory, you're going to use the ionViewLoaded event, but
if you want data to be retrieved every time the page is navigated to, even if it's just from
a simple back navigation, then you should use one of the other events such as
ionViewDidEnter. Right now we have hard coded tournaments on the Tournament page.
Let's replace these hard coded tournaments with an actual HTTP call to our web API.
Here I am back in the Tournaments page and I'm going to add an import for the EliteApi
service. The other thing I'm going to do is I'm going to add a property for tournaments. I
also want to make sure that I inject the EliteApi into the constructor (Typing). Now in the
ionViewLoaded method, let's invoke that, I'll say this eliteApi.getTournaments, then
this.tournaments = data. And I'm not even going to need these anymore, so I'm just going
to take those and delete those. So the ionViewLoaded is one I've chosen to invoke this
method. So the first time the page is loaded it will go out and make an HTTP call to get
those tournaments, however if the view is shown again on a simple back navigation, it
won't go fetch those tournaments again. Let's go to the HTML counterpart and let's add
an ngFor to this first item. I'll say let items of tournaments, that's that tournaments array
we had, and in the itemTapped we'll just add the event and the item. Now we don't want
this hard coded anymore, so we'll say item.name, and of course we need to remove this
other hard coded button. Let's flip back to the Tournaments page in the itemTapped, now
we're passing some real data, and we'll actually send that tournament that's selected has a
navigation parameter to the Teams page. Now let's rerun the app. This time when I came
into the Tournaments page I can see there's now four tournaments, no longer the hard
coded two tournaments that we previously saw. So it actually went off and made an http
call to our web API and got the tournaments. I can go to the Teams screen, and if I go
back, we still see the data there, but it didn't actually go out and refetch that data. Let me
prove that to you. Let's go to the Network tab, I'm just going to completely refresh the
app. We'll go to Find a Tournament. There's the tournaments JSON call that was just
made to get that data, we can see the data in there. Now I'm going to go to the Teams
page. Now if I go back we see tournaments.json was not re-invoked. However, if I go
back again and pop that off the stack and now come back into it, it will get re-invoked.
So this is an illustration of the Ionic 2 lifecycle events. It's good to understand the nuance
differences between some of these events so that you can load the data at the appropriate
time for your app.

Working with RxJS

At this point we've created a service that makes HTTP calls to a web API and we've
displayed that data on the Tournament screen. When we did the last example we used
regular promises, which we can see here for the getTournaments method. Now let's look
at a similar example, but this time we'll use RxJS, which has become the standard for
working with HTTP in Angular 2 apps. The first thing I'll do is I want to come in here
and add a property for current tournament, I'll just set it equal to an empty object. Right
now we have this getTournaments method, which just goes out and makes a lightweight
call to get the list of tournaments. What we want to have is another method called
getTournamentData, and for this method we're going to pass in a tournamentId and for
the given tournament id we want to go out and get all the data for that tournament, all the
games, the schedule information, the team lists, the standings. And when we retrieve it,
we're going to save it in this currentTourney variable. This time the code looks slight
different. We'll say return this.http.get, so the http.get looks actually the same, then we'll
come in and say this.baseUrl tournaments-data, and then we need to give it a specific
tournament id, that's that GUID we saw earlier on the Firebase console (Typing), we need
to add the .json extension. Then I'm going to say .map response, and the first thing is we
want to save the current tournament with the data that comes back, and then we want to
return it. Now depending on your editor, you may or may not be getting a red squiggle
on the map method right here, that's part of RxJS, let's make sure we import it. I'm actually
going to add two import statements to just import the entire RxJS library. I'm also going
to import the observable. And I'm going to import the observable because I just want to
be a little bit more explicit on the definition of this method, that it is returning an
observable of any. That's what going to allow us to use some of these methods like
subscribe. Now let's actually go utilize this method on one of the pages. We'll go to the
teams.page and let's add navParams to the import and make sure we inject it. Let's also
make sure we're injecting the EliteApi service and let's make sure we inject that too
(Typing). Now we don't need these hard coded teams anymore. Let's just make teams an
empty array. Now let's add an ionViewLoaded method and then this method is where we
want to actually make the call to the API. So we have a variable for the selected
tournament. This is the tournament that actually got passed in as a navigation parameter
(Typing). Now we can use the subscribe method of RxJS, we'll just say this.teams =
data.teams. Now let's go run our app. We'll go into the Tournaments page and I'll select
this last one, March Madness, and what we can see here is that instead of just three or
four hard coded teams, we actually made a call out to the web API and now we have a
huge list of teams because we got all that data over HTTP, and we did it using RxJS. RxJS
has extra features that you can leverage over normal promises, which has made them
popular for Angular 2 apps. Either way, as you've seen here, Ionic 2 makes it quite easy
to work with HTTP with your preferred mechanism, either promises or RxJS.

Loading Component

We're loading HTTP data from our web API and displaying it on the screens, which is
great. Our web API is actually performing pretty fast right now, so the screen navigations
have been extremely quick. However, with mobile apps in particular, you can't predict
what kind of connection your users will have, so it's a very good idea to give them some
sort of visual indicator that data is being retrieved so that they know the app isn't frozen.
The Ionic loading component makes this a breeze. Let's add this to the Tournaments page.
The first thing I need to do is add the loading controller to the imports, then I want to
inject it into the constructor. With that in place, let's change our ionViewLoaded method
slightly to incorporate it. The first thing I'll do is get a handle to the loader by calling the
create method. And in here we're just going to say content: 'Getting tournaments...'. That
message will be displayed on the loader component. Then we'll say loader.present, and
this is a promise, and we're going to take this previous line right here and I'm going to cut
and paste it inside the promise. In fact, we're going to make this multiline now. And the
reason is because once the data is retrieved we need to dismiss the loader. That's it, that's
all we have to do to implement a loader. Now before we run this, I can see I've got a little
error down here. If I navigate up I can see I've got a red squiggle that I missed before, of
course I need to have a comma there. So now that that's fixed we can go run the
application again. Okay so when I click the Find a Tournament button we'll briefly see
the loader. Right there you saw Getting Tournaments. The data is loading pretty fast so
you didn't see it for very long, let me do it one more time so you can see it happen again,
and you can see that Getting Tournaments method. The other thing you saw is that there's
a little animation that's going in a circle. You can change that as well. Let me show you
how to do that. I could come in here to the content and I could say spinner is dots. Now
let's run it again. You can see we've got those three dots. Again, it happens very quickly.
You can see three dots right there. Now I'm going to comment that out because I think
the default circles looks a little bit better, but again, that's purely your preference. The
loading controller component is one you'll use frequently to indicate to your users that
data is being retrieved. So it's important to get comfortable with this component early on.

Add Third-party Library: Lodash

Ionic 2 comes with a ton of features out of the box build directly into the library. However,
for most real world apps, situations will arise when you want to leverage a third party
library. In my case, I'd like to use a library like lodash to manipulate some of the data
we're getting back from our HTTP services. Let's see how we can incorporate lodash into
our app. The first step is quite straightforward. We're simply going to run npm install like
we would any other package. Now one thing to keep in mind here is that we're building
this with TypeScript, so it'd be nice to have some typings files. Some JavaScript libraries
ship with the TypeScript definition files, but not lodash, so we want to add typings files
for that. We do this by using the typings tool. If you don't already have it installed, you
need to run an npm install with the g switch to install it globally and typings. Now I
already have it installed, so I'm not going to run this command right now. Instead I'm just
going to invoke it by saying typings install lodash. And what we can see down here in the
typings folder, we can go into modules and we can see that lodash has been added right
here. I can come into my index.d.ts file and we can see it's been added here as well. This
is going to give us IntelliSense for the lodash library. Another thing to see is that lodash
has been added to our package.json file because we use the --save switch. Now we're
going to use lodash to filter data on the Team Detail screen so we can show the game
schedule just for that selected team. So come into team-detail and I'm going to add an
ionViewLoaded method. And we're going to move this line from the constructor down to
this method. And we don't need this console.log anymore. Now let's import lodash. For
lodash I'll say import * to import the entire library, as _, because that's how we
traditionally refer to lodash, from lodash. I also want to import the EliteApi and let's inject
it into the constructor. And let's also add a games array. The final property I'm going to
add is just a property to hold the tournament data. And let's populate that tourneyData,
and I want to add a convenience method called getCurrentTourney, and you can see I'm
getting a red squiggle right now because that method doesn't exist yet. Let's add that real
quick on our EliteApi (Typing). And it's just returning the currentTourney right here that
was previously assigned when we got the data. Now we can see the red squiggle is gone.
Now at this point we've gotten the handle to the team, we've gotten the handle to the
tournament that this team is playing in, what we want to do is get a list of just this team's
games. Each game has a team 1 id and a team 2 id, so in order to find the games for this
team, either team 1 id has to equal this team id or team 2 id has to equal this team id. So
what we're going to do is we're going to assign the games array equal to, and we'll use the
lodash chain method here, sending in the tournament games (Typing). We'll call filter,
we'll say g for games, g goes to g.team1Id equals this.team.id or g.team2Id equals
this.team.id. And we have to call the value method at the end of the chain function so that
we get the value put into the games array. So this is the basic lodash filter that we want
to use, in fact, I want to add even more lodash functionality to this. After we've filtered,
I want to run a map function (Typing). And in the map function I need to determine a
couple of things, I want to know if this team is team 1 or team 2, so I know who's the
opponent, because whichever team this isn't, they're going to be considered the opponent
and so I want to be able to get a score display as well. You can see we get a red squiggle
because the scoreDisplay method isn't there yet, let's add that. On scoreDisplay all we're
doing is saying if there's a score, figure out who's who, so if it's team 1 we're going to use
a team 1 score, otherwise use a team 2 score. And the opponent is going to be the opposite,
so if we're team 1, that mean opponent is team 2. If we're team 2, that means opponent is
team 1. And then we'll use a winIndicator saying if we had more points we have a w for
a win, less points is an l for a loss. And then the scoreDisplay is just going to be a nice
thing showing the winIndicator and then our teamScore first and the opponentScore is
always going to be second. So back to the map function, we have the opponentName, the
scoreDisplay, and then in here we're just using a return statement to get simple things like
the gameId, the opponent, time and location. Now let's go to the HTML for this page. We
don't need these values anymore. We're going to put an ion-list and inside an ion-item.
For this ion-item we're going to say ngFor and we'll say let game of games. And in here
we're just going to say game.opponent. As we get to later modules and we start
incorporating more components, we'll make this fancier and we'll add the score display
and some of those things you saw, but for right now I'm just going to output a game
opponent. Let's go see what it looks like so far. We'll go into the tournaments, we'll select
Holiday Hoops Challenge and let's select HC Elite. Now instead of having hundreds of
games it just filters down to the four games where HC Elite is in the game, and it shows
the four opponents for those four games. And we can do this with any team, we can go
back and do Maryland 3D and this shows different opponents here. So in just a brief time
we've incorporate a third party library, in this case lodash, into our app and we've used it
to manipulate and filter the data that we're getting over HTTP service. Ionic makes it very
easy to incorporate third party libraries into your app.

Putting It All Together

Now our navigation is essentially complete and we've got real data coming from an HTTP
web API. Now it's time to put it all together. We're going to add some navigation to the
game page so that we can go from one team, navigate to any game, then go to the team
page for the other team in that game, and essentially be able to navigate infinitely. Let's
start in the Team Detail page here and on this ion-item I'm going to add a click event and
we'll call it gameClicked. Let's go into the team-detail, this is going to navigate to the
game page so we need to add an import to the GamePage. Let's go down here and add the
gameClicked method and we can see that we have a gameId, it's got to go and look in the
whole collection of games for the tournament data, find that sourceGame, and we're going
to pass that sourceGame to the GamePage as a navigation parameter. So let's go to the
GamePage, we're going to add NavParams to the imports, which means we also have to
inject it into the constructor (Typing), let's add a property for the game, and an
ionViewLoaded method where we simply assign that game to the navParams. I'm just
going to put some temporary HTML on the gamePage. It's not very pretty right now, we
just show the Home Team and a button that'll take you to the Team Detail of that team
and then the Away Team and a button that will take you to the team detail of the second
team. Let's make sure we have the teamTapped method implemented in our gamePage.
We've just added the teamTapped method. We want to use the EliteApi to get a handle to
the current tournament so we can have the data right here. Then we're going to find that
particular team and push that team to the TeamHomePage. Now you see we have a couple
red squiggles, so we have to do some injection. First let's import the TeamHomePage.
Next let's import the EliteApi. And let's inject it into the constructor. Now we're ready to
run the app. Let's navigate to a tournament and let's select the March Madness
tournament. We can see we have a ton of teams in here, let's select HC Elite 7th. Now we
can see the game schedule, so let's tap on the game for the Cyclones and we can see Home
Team was Cyclones, HC Elite was the Away Team. Let's go look at Cyclones. Now we're
on the Team Detail for Cyclones and we can see their games. They have one against
Maryland 3D, let's click that game. We can see the game. Let's click Maryland 3D. Now
we can see the Team Detail for Maryland 3D. And so on and so forth. So we have infinite
navigation where we can see the Team Detail for every screen, see the team schedule as
well as the game, and we have full back navigation for that entire stack. In the upcoming
modules we'll start to explore all of the components that we get with Ionic. Right now
some of these screens aren't very pretty, but we'll make them look a lot better as we
incorporate Ionic 2 components into our app.

Summary
That concludes this module on working with HTTP and lifecycle events in Ionic 2. We
started out by setting up a backend. We used Firebase for our HTTP web API, which is a
well known backend as a service. We then created the EliteApi service, which has the
responsibility of interacting with HTTP. We added a method to the EliteApi using
promises with the HTTP call. I then gave an overview of the various lifecycle events
available in Ionic 2 apps. Following this I showed how you can use those lifecycle events
to load the data at the appropriate time, depending on if you want the data to be loaded
every time the view is navigated to or just when it first loads on the navigation stack. I
then showed how you could use RxJS to interact with HTTP as an alternative to promises.
Then we added the loading component to our app so that we could give the user a visual
indicator that data was being loaded. Next we add lodash as a third party library, including
its TypeScript definition file. We used this to filter data so we could see the game schedule
for just the selected team, and we put it all together at the end by implementing what is
essentially infinite navigation, since we can navigate to the team detail screen for any
selected team. In the next modules we'll incorporate numerous Ionic 2 components, which
will add great functionality in addition to significantly increasing the visual appeal of our
app.

Ionic 2 Components
Overview

In this module we're going to add many Ionic 2 components to our app. Ionic 2 comes
with a multitude of built-in components that are optimized for mobile apps. We'll start by
taking a closer look at Ionic lists. We'll then add some list dividers. We've already used
some buttons in our app, but we'll take an even closer look at what you have available.
You've seen me add some icons earlier in the course, here I'll show you where you can
find them and how you add them. We'll add Ionic cards to our views, which are becoming
increasingly more common in mobile apps. I'll also show you how you can add custom
CSS to customize the appearance of your components. I'll show you how you can use the
Ionic grid system. Ionic 2 comes with a new component called the Ionic DateTime, this
makes working with dates drastically simpler than in the past. I'll then show toggles and
badges. I'll finish off by showing you how to use alerts and toasts. We'll cover a ton of
content in this module, so let's get started enhancing our app.

Ionic Lists

We've already seen some Ionic lists on some earlier examples, but let's take some time
now to look a little more closely. Lists are one of the most frequently used components
when developing Ionic mobile apps. Here on the Ionic website, you can see the
documentation for many different usages of lists. Inset lists, list dividers, list headers,
icon lists. I think it's always a good idea to consult the documentation to see what you
have available, but let's implement some of this now. We're going to add some lists to the
My Teams page, specifically we're going to add a list for the favorites, that is the teams
that we're following. Now ultimately we're going to have two sections on this My Teams
homepage, one section if we're not following any teams and another section if we are
following teams. We already have the start right here of the section for when we're not
following teams, we'll come back to this, for right now I'm just going to comment these
out. And I'll just put some alternative text here, all this text is saying is to follow more
teams, select a tournament, then you can follow teams from their team page. Let's add a
list. Now previously you saw me do this, where I would have an ion-list and inside was
an ion-item. And you can certainly do that, however, the individual items of a list don't
have to be an ion-item. In fact, I can make this a regular button. And then to the button I
can add ion-item as an attribute and that'll make the button have a regular visual
appearance that'll look just like a regular ion-item, but we can more intuitively do things
like attach click handlers to the button. Let's add an ngFor, which I can do to the button
just like a regular ion-item (Typing). And we'll say let item of favorites. I don't actually
have those favorites yet, so let's go over to the team page here and since we haven't
implemented that functionality yet, I'll just temporarily hard code a couple of favorites.
And we see it right here, we have two favorites, one's HC Elite 7th, the other is HC Elite,
they're in two different tournaments so you see two different tournament names, two
different tournament IDs. Let's go back to the my-teams.page, inside the button we're
going to put item.team.name. Now let's look at the app to see what we have so far, and
right here you can see that I have the list and we have the two favorites in the list. Now
let's add some icons to each item. Right above the name I'm going to put ion-icon and
we'll just get a name equal to star to show that these are our favorites, and we see the star
next to each item. Now Ionic list items are also quite flexible in that you can put different
content inside the items. Below the name I'm going to put a p tag and in this p tag I'm just
going to say item.tournamentName. And we can see the tournament name under each one
in a different font, it's starting to look better. We can also add list headers, so I'll come in
here right above the button, which is right above the item and I'll say ion-list-header and
we'll just say these are our Followed Teams, these are the favorite teams that we're
following. We can see Followed Teams right here, the list header. Let's attach a click
handler to the button. Come in here to the button and say click = favoriteTapped. Let's
add that favoriteTapped method, and what we can see is we want to use a loading
controller, we also want to use the eliteApi and we want to navigate to the
TeamHomePage. So we have some imports that we need to take care of. First let's add
the TeamHomePage, next let's add the loadingController, let's them import the eliteApi,
and of course we need to make sure that these have been injected into the controller
(Typing). Now our red squiggles have gone away and we're ready to run the app. So we
can see, we have our two list items here, I can tap either one of them and it'll take me to
the Team Detail directly from that page. This is actually the Team Home, which is
showing the list of schedule for that on the Team Detail page. There's HC Elite and here's
HC Elite 7th. You can always go back to the home. So this is a just quick example of how
we can customize Ionic lists. We have icons, we have different texts, and we have list
headers. And with just a few small enhancements we've significantly improved the visual
appeal of our page and we'll continue to make it even better.

List Dividers

The next topic I want to talk about is list dividers. I'm going to go to the Tournaments
page and select March Madness tournament and what we can see here is a very long list
and when lists get large we often need a way to more logically organize the list data for
our users. This can be done with list dividers. So here I have a long list of teams and they
have all different grade levels, it would be nice if we had list dividers that would subdivide
this list per grade. Let's implement that now. So here I am on the Teams page, in fact we
can remove this commented hard coded teams, and we need to have a couple of items
because we want the data to be structured a little bit differently, so I'm going to add a
couple of properties here, one's going to be an array for allTeams and another one is going
to be allTeamDivisions. Let's also add the loadingController and we're going to need to
use lodash here to manipulate the data, so let's do that as well. Now inside the call to get
the data for all the tournament data, we're going to change this code slightly. First I'm
going to have the allTeams variable, that's going to be the thing that holds the raw list of
teams data. The next thing I want to do is a lodash statement that subdivides these teams
into divisions. Let's take a closer look at this, I'm using the lodash chain command and
I'm doing a groupBy on the division and then for each one I'm using the two pairs in
conjunction with the map to say grab the divisionName and then the divisionTeams. So
there's going to be different items in the array, each item will have a divisionName and
then an array of those divisionTeams. And for now the old teams variable we were using,
we're just going to set that equal to allTeamDivisions for now. The other thing we want
to do is encapsulate this in a loading controller, so we'll have our typical loader and we're
getting a red squiggle because we neglected to inject the loadingController, let's do that
now, and then of course we have to say loader.present (Typing) and all of this is going to
go inside the loader (Typing) and we have to say loader.dismiss. Now before we actually
see what it looks like visually, I want to do a console.log so that we can actually see the
teams, so we'll call this division teams (Typing). Mainly I want you to be able to see the
results of that lodash query right here because it's very important to understand that before
we put in list dividers. So let's go to Find a Tournament, then Teams. Now don't worry
about the fact that nothing's displaying yet, we haven't done anything there. What I want
to direct your attention to is over here the division teams in the console, you can see that
instead of having a long list of 80 teams, we just have 11 items. If we inspect each one,
the first object in the array has a property called divisionName, which is the 3rd, and then
an array for the divisionTeams. The next one has divisionName 5th Black,
divisionTeams, and so on and so forth. And this is what mapped to our lodash query -
right here. So we did the groupBy to create the object in that form. With that in place,
now it becomes quite easy to put in our list dividers into our HTML. First thing I want to
do is let's encapsulate this button with an ion-list and we're going to put an ion-item-group
(Typing). Let's put that button inside the ion-item-group and the ion-item-group is going
to have its own ngFor and this is going to be division of teams. And the first thing I want
in each ion-item-group is an ion-item-divider and we'll give it a secondary attribute, so
we have a different color. We'll have division.divisionName. Now we have to change the
ngFor that was previously on the button because previously the buttons were just looping
over this long flat list of teams, now we want to loop over this object right here, the
division, specifically the divisionTeams. So we're going to say let team of
division.divisionTeams, that's that object we saw in the console. Now let's look at the app
again. Now we can see we have a nice organized list where we've grouped by the division.
It's going to make it much easier for people to find data in our list now. You can see the
secondary attribute shows that nice green color on each list divider. Dividers are a way to
make the display of a long list much nicer. Sometimes you might need to actually
manipulate your data a little bit to get it into the shape that will work more easily with the
divider, as you saw we did here. But this is typically not too difficult to do.

Buttons

Buttons are one of the most simple and most frequently used components that you'll work
with in the Ionic framework. Alright buttons are relatively basic, there are many ways we
can change the size and appearance of buttons. Here I am on the My Teams page, let's
look at this Find a Tournament button, which just has the default appearance right now.
Let's see the different ways we're able to customize this button. The first thing I'll do is
add a full attribute to it. We can see that when I do that, it spans the full width of the
screen. Now if I had a padding attribute on the ion-content, we can see that it'll just span
to the width of whatever the container is, the padding gives us a little bit of space on each
side. Let's remove full so we can see the default again, and there's the default size once
again. Now let's add round, you can see we now have rounded edges on the button. Let's
add outline, you can see we still have round edges, but we also have now just the outline
of the button. Let's replace outline with clear. Now we still have the button, the round
edges are essentially irrelevant, but we still have a button we can tap, it also looks more
like a hyperlink now. Let's move both round and clear and add small. Now we can see
the button has gotten slightly smaller than our default. Let's remove small and after the
text of the button, let's just put this in here to make this spacing a little bit more obvious,
let's add ion-icon and we'll give it a name of search. You can see that after the text it put
this search icon. Let's see what happens when we move it before the text. You can see it
simply puts it on the left side. Let's see what it looks like when we comment out the text
and we have an icon only. In this case the button sizes appropriately and just shows an
icon. Let's add outline back in, and now you can see we have an icon only button with an
outline appearance. We can also add fab for floating action button and you can see it gives
it that round appearance where we have a floating action button, which is a common thing
to see in mobile apps these days. So let's set this back to what we're going to use for our
app, which is we're going to use full, and let's bring the text back. For this screen, this is
the appearance I want for the button, but as you saw you have lots of different choices for
how the buttons will appear. Although buttons are basic, you have a ton of options for
how you get them to display, so I definitely recommend taking the time to get the display
just how you want it.

Ionicons

You've already seen me use icons a few times in this app, in fact you can see it right here,
we have the star icons on the My Teams. And you may have wondered how I knew what
string to use to get a certain icon to display. Let's take a look at that in a little bit more
depth now. First, if I go over to the Ionic documentation page for icons, you can see that
it's pointing me to this webpage called ionicons, and if I click that it'll take me over to the
ionicons website. Now the ionicons is a separate package you have in your app. So for
example, if I look at the package.json file, I can see ionicons right here. It was already
preloaded into our app when we first created it. And as we saw right here, I'm using ion-
icon name = star, and down here we used ion-icon name = search. So let's flip back to the
website here for the ionicons and you can see we have a ton of icons on the webpage, I
could just scroll down on and on. But we can also type in a search term, for example, if I
just type search, we can see that magnifying glass that I used on the Find a Tournament.
If I show people, you can see I have a few different icons here I can use, contacts, people,
contact, one contact, multiple contacts, multiple people. And if I click this one, for
example I click the one for people, you can see we have some different options here,
depending on your platform. Here's iOS, here's iOS outline, here's md, this is material
design for Android. And it's showing the basic usage, so really you just give it a name
like you've already seen me do, name = people, or if you want to explicitly put the name
in. So in this first example where the platform is not explicitly specified, the Ionic
framework will make sure that it puts in the platform automatically for the platform that
it detects that it's currently running on. Let's illustrate this in our app. So right here we
have the star icon, let's change this to people. And we can see now that instead of the star
we see the people icon. If I switch my platform to iPhone and refresh, we can see that the
people icon now changed and it's showing the iOS version of the icon because the user
agent changed, that's an example of how the Ionic framework will help you out
automatically depending on the platform. You can also explicitly specify this. So instead
of people I will say ios-people and it still iOS people here, but even if we change it back
to an Android platform, you can see that it's still showing the iOS icon for the people. So
you do have to be careful about it because this may not be desirable to show iOS style
icons on an Android device or Android style icons on an iOS device. We can also use ios-
people-outline and we see that it's now the outline version of that icon. So I'm just going
to flip back to the default, which is star, and we'll let it the select the platform
automatically, so it'll be Android if it's Android, iOS if iOS. The main thing is to make
sure you always consult the ionicons website, you'll find hundreds of high quality icons
to choose from, which can make your app much more visually appealing and professional.

Cards

Cards are quickly becoming an extremely common way to organize content and provide
familiar layout to users. Here I am on the documentation page and as I scroll down you
can see basic cards on the right, card headers, card lists, cards with images, background
images, and so on and so forth. Let's see how we can use cards to enhance the My Teams
screen a little bit. The first thing is I'm going to bring back this commented text and
actually I'm going to comment out everything else for the time being, and above this I'm
going to put an ion-card and this is going to have two sections, ion-card-header and the
header is just going to be No Followed Teams. We're going to show this card when we
detect that we have not saved any favorites. Eventually we're going to have a second card
that'll be for our favorites, and the second section will be ion-card-content, and we'll put
these two p tags in that card-content (Typing), and let's make sure we have a button in
there to find a tournament (Typing). Let's see what it looks like so far. Here's our card,
No Followed Teams is a header, it has some instructions that we're not following any
teams, and we can find a tournament. Now cards have some natural padding and we
already have some padding, so we can take that off. I'm going to remove this padding
attribute right here, and now this looks a little bit better because, as I said, using a card
providers some padding itself anyway. Now let's add a second card for the instance where
we are following teams. I'm not going to add a header this time, I'll just add ion-card-
content. I'm actually going to put this list above the ion-card-content and I'll put the p tag
and the button tag in that card-content (Typing). So our second card is for when we are
following teams, it shows the followed teams, and has its own card-content. Now here
we can see both of our cards, you can certainly have multiple cards on a screen if this is
appropriate for your display, but obviously in our case this doesn't make any sense since
we only want the top card to display if we have no favorites and we only want the bottom
card to display if we have favorites. Let's go fix that now. So here's the second card and
we're going to add an ngIf and it's simply going to be favorites, so if those favorites exist.
Let's copy that and over up on the first card, let's paste it and we'll put a not here to negate
and we'll only display this first card if there are not favorites. Now you can see we fixed
the app, it detects that yes we do have two favorites, and therefore it'll show the second
card. If we were to remove these, which are hard coded right now, then we would see just
the first card. Cards add a lot to the display. It can be a subtle effect, but it really helps
organize the screens for your users. I highly encourage you to use them in your apps.

Custom CSS
Although Ionic comes with components out of the box that look attractive and
professional, there will invariably be times when you need to provide your own custom
CSS, this is extremely easy to do. If we look at our app here, we can see the Follow Teams
header, it does stand out a little bit because it's a list divider, but it doesn't stand out that
much. At least it doesn't stand out as much as I'd like. Let's add some custom CSS to
enhance this. I'm going to come into the my-teams directory and the new file is going to
be my-team.page.scss. This is our Sass file, and I'm going to add a new class, my-teams-
header, and in it we're just going to say font-weight is bold and font-size is large. Now
this is regular CSS, which is certainly valid in Sass, but I can put any valid Sass command
in here. So we have my-teams-header as a new class, let's add that to the ion-card-header,
class= my-teams-header. And in fact, let's do that to both ion-card-headers. I'm copy that
and I'll paste it down here as well. Now one thing we're going to see here, notice that
nothing has changed. This is a common gotcha that people often run into. Adding the file
is not enough, you also need to include it. Let's do that now. So we'll come down here to
the theme directory and open the app.core.scss. And down here I need to add an import
to the pages/my-teams/my-teams.page because that's what we named it. Now that we've
included it, you can see we're getting a nice bold header and a larger font. It's so easy to
include custom styles in our app, I encourage you to do it frequently. It's also nice because
you can scope the styles to the individual screen that you're working with, rather than
having to include all the styles globally.

Grids

The grid system in Ionic is extremely flexible. It's based on a flex box and is quite easy
to use. Let's see how we can use it to enhance our app starting with the Team Detail view.
Here's the Team Detail view, and you can see this is the schedule just for this team and
all we're doing here is listing the opponent, that's interesting, but not really that helpful.
Let's add some more information to this screen while using the Ionic grid to organize that
information. First let's just remove this game.opponent right here and I'm going to add an
ion-row with three ion-columns inside, so we'll say times 3, and there we go, now we
have a row with 3 columns. To this first column let's add the game.time. So we can see
that we're using the game.time, the first p tag has just the date, the second one has the
time. Now we're putting here the opponent. We're going to say is it home or away? Who's
the opponent and where's the location? In the third column we're just going to put an h4
and we'll say game.scoreDisplay. Let's look at the app. And we can see this display is
way more helpful than before where it just listed the opponents, now we have date and
times, we know whether it's home or away because if they're away it says at and if they're
home it says versus, and we have a score display as well, and we have a W or an L to
indicate if the team won or lost that game. Let's add an ion card with an ion grid above
this list. So what I'm going to do is add an ion-card, in it we'll have an ion-card-content,
and in that ion-card-content we want 1 row and we want that row to have 2 columns,
times 2. Okay now inside this first column, we're going to have some detail about this
team. We want to show what their record is, what's their wins and losses, we want to
show the coach's name. For the second column we're just going to put a placeholder for
now. Now notice I was referring to this teamStanding object that has wins and losses, let's
make sure that's available in our component (Typing). And after the games filter down
here, I'll say this.teamStanding = we use the find method on the tournament data,
specifically the standings array, and we want to look for the teamId equal the this.team.id.
Now when we come into the team detail we have a nice little card at the top which shows
the record, there's wins and losses, there's' the name of the coach, and down here we saw
the list of that team's games. Now that we have the basics of using the grid system, let's
look at in a little bit more depth. One thing you may notice as you're looking down here
is that we're slightly out of alignment here, for example, right here this I states little bit
more over to the left than these ones over here and the W's are not lining up either in this
column. The ionic grid system allows us to put some width percentages on the columns.
What I can do here is I can say width-20 and let's do the same thing to the one down here,
and then up here we're going to make this width-60, so we have 20 plus 60 plus 20, that
equals 100, which is what we want. So this middle column will be a little bit wider than
the other ones. Now we can see everything is nicely lining up. The W's are all lined up
right in a row, same with this middle column, and even the dates are lined up. By default
the grid system will make the columns equal distant, however, because of the size of some
of our content it wasn't exactly lining up, so to be more explicit you can put column widths
to make it even better. Now we need to implement our Standings screen, which up to this
point has been blank. Let's use a grid system heavily here. Let's add the property for
standings, this will be an array, and we also want an individual team because we might
eventually show the standings for that team. Let's add NavParams and make sure we
import it (Typing). Let's also make sure we import the ELiteApi and inject it. Now let's
get the standings data. What we can see here is that I've added an ionViewLoaded method,
we grab a reference to the team that gets passed in, we get the current tournament data,
and all the standings. Then I am creating another property called allStandings, in fact let's
make sure we add this up here to get rid of the red squiggle (Typing), and we can see
we've also got a red squiggle because we neglected to do the import for lodash, let's do
that real quick (Typing). But back to this method, we're doing a similar lodash function
here where we're doing a groupBy on the division, so we can get the standings for each
division. We use this exact same technique with the two pairs and the map on the team
screen, so there's really not much different here, we're just doing it on the standings
instead of the teams. Now we actually haven't' shown the grid yet, I just want to do some
console logs here so you can see what the data looks like for the standings and the division
standings, which are all standings, the divisions standings. And we'll go into the
standings, and you see we have a couple different objects here, here's the standings array
and this has a ton of objects because it has the standings for every team, but then we have
this other one for division standings and if we look at this it's just 11, there are the
standings for 3rd grade, here are the standings for 5th grade. So this is where we did the
groupBy, so similar structure there. Now let's go add the grid. We can remove this and
let's add an ion-list with an ion-item-group with an ion-item-divider. In the ion-item-
group we're going to do an ngFor, let division of standings. In the ion-item-divider let's
use secondary, division.divisionName. And under the ion-item-divider, here's where we'll
add another grid. We'll have ion-item with an ion-row with one ion-column that has an
h2 inside. For that ion-item we're going to add an ngFor, let team of
division.divisionStandings. Let's add the primary attribute to give this a blue color. We'll
say team.teamName. Now we're going to do another row and in this row we're going to
have six columns, and inside of each one of those we're going to have an h4. So now
we've got another row with 6 columns and this is just for our headers. So let's add wins,
losses, winning percentage, points for, points against, and this is going to be for the points
diff. Let's add another row, this will be for the actual values. So this will also have 6
columns in it, this time we're going to have h5's. This is going to be wins, losses, winning
percentage, pointsFor, pointsAgainst, and pointsDiff. So let's come back here and run it
and we can see we clearly made a mistake, and I think I know what it is, we have the
standings object with all the standings, and then we have the division standings, which is
the grouped standings that's the one we actually meant to use. Let's go back and fix that.
So we'll just make this allStandings right here. Now when we come to the Standings, you
can see everything is nicely grouped, so we have our 3rd grade division, 5th grade, 6th
grade, and the grid system really made things look nice. We have one row here for the
team name in blue. We have another row for the wins, losses, and percentage for the
headers, another row for the actual values. In just a very short time we were able to use
the Ionic grid system to get a pretty nice display here. The grid system is extremely
flexible and robust. You can get a myriad of different alignments very easily without
having to rely on a system based on a fixed number of columns, such as 12 columns. Any
number of columns can be used with the Ionic grid system.

Ionic DateTime

DateTime controls have always been extremely problematic in mobile apps. It hasn't been
easy to get access to the native dateTime picker control and there can be significant
variations of date pickers across platforms. Ionic solves this by now introducing their own
dateTime control, which can be used on multiple platforms. Let's incorporate this by
adding a date filter to the Team Detail screen. Right now we see games across all dates,
so we can see we have March 21 and a couple on March 22, that's fine if I want to see all
the games, but maybe I just want to filter it for a specific individual day. What I'm going
to do after this row is I'm going to add an ion-item and inside it's going to have an ion-
label, and that label is going to be Date Filter. Under that I'm going to put an ion-datetime.
And in this ion-datetime we'll put a couple of things, first we'll have a displayFormat and
our displayFormat is going to be month, day, and year. We also want to have a
pickerFormat, same thing. I'm also going to attach an ngModel to this called dateFilter.
And we haven't added that yet, so I'm going to copy this and I'm going to put it over on
the TeamDetail. Even though we haven't put in any functionality yet for filtering, let's see
what it looks like on the app. And we can see our Date Filter label here, if we click it we
can see a Date Filter pops up, I can scroll up and down, I can select the day. Let's come
over here and flip to iPhone 6 (Loading). Notice now the date picker looks more like an
iOS dat picker control, whereas the last one was more along the lines of Android. So we
now have a functional date picker, but no actual filtering is happening yet. Let's add that
next. Let me also switch back to Android. So let's add a property for allGames, this is
going to be an array, and right after the initial assignment here we're going to say
this.allGames = to this.games. So we'll just set it equal to the same thing as games initially.
Now we want to do some date filtering here and the moment js library is really good at
that, so let's add that as a third party library. We'll come in here and say npm install
moment, now that that's installed we can use it. And one point I should make is that with
lodash we had to install the TypeScript definition files using the typings tool, we don't
have to do that with moment because it nicely includes the TypeScript definition files
along with the npm package. So I can just immediately come in here and say import * as
moment from moment. And now what we can do, let's go down to the bottom and let's
add a dateChanged method and in here we'll say this.games = and we'll filter on allGames
where the time for the game isSame as the dateFilter, specifically the day. So with the
isSame method of the moment library you can say is it the same year, is it the same month.
If we have day here, it's saying is it the same day. And we want to make sure this
dateChanged method is invoked anytime it's changed, so let's go over to our ion-datetime
and let's add an ionChanged event (Typing) and we'll put that right in there. Now let's run
the app again. So we have two games on the 21st and two on the 22nd. Let's come in here
and filter by the ones on the 21st. So we'll say 3/21/2015, sure enough, here are the two
games on the 21st. We could change this to the 22nd, there are the two on the 22nd. So
the filter is working correctly. We now have successfully implemented our date picker,
however, we don't currently have a way to clear the filter. We'll look at that in the next
section using the toggle component.

Toggle

As shown in the previous example, we now have a date filter which can filter the games
just for this day. As you see here, it's being filtered for March 22. However we have no
way to clear this filter, let's use the toggle component in order to do that. Right before my
ion-datetime I'm going to put in ion-toggle and let's attach an ngModel and it's just going
to ultimately be a Boolean, we'll call it useDateFilter. And in fact, let's add another
attribute here for whether or not this is disabled (Typing), looking at the useDateFilter.
So if it's not using the useDateFilter, it will be disabled, otherwise it'll be enabled. Let's
go to the team-detail.page.ts and let's just add the useDateFilter right here and we'll
initially set it equal to false. Let's see what we have in the app so far. So we come in here,
we see the Date Filter is disabled. I have the toggle, if I enable the toggle, now the Date
Filter is enabled and I can use it. But we still don't have the filtering working correctly.
The ion-toggle has an ionChange event we can subscribe to as well, so let's do that next.
So in this ion-toggle, we'll add ionChange and we want the dateChanged to be invoked
each time that changes. Now we have to make one change to that, let's come down to the
dateChanged method and we want to say if useDateFilter (Typing), so we're using the
date filter, we want to take this line and put it right in here like we previously have it,
otherwise we just want to reset the games to what we had originally with all the teams
games. Now that we have that in place, let's run it again. So we come in and we first it's
displaying all the games, we can't use the Date Filter because it's not enabled, let's toggle
it to enable it and let's come in here and select 3/21. We can see we're filtering just for
3/21, we make it 3/22, and we can also turn off the toggle and then all the games will be
displayed again, and we can also toggle that on and off. But now we see we have used
the toggle control in conjunction with the date picker to give the user a much more
satisfying experience to be able to see the games much more easily in the way they want.

Badges

Badges are another quick and easy component you can use in the Ionic framework when
you want to give a better visual indicator to something. For example, if we look at the
Team Detail page here, the score display, well it looks kind of boring and we see that
these are wins, but it'd be nicer if we had a better visual indicator so that we can show
better if something is a win or a loss. Let's use badges for this. So we'll come down here
to the score display and after it we're going to use an ion-badge, and inside we're going
to call a method called getScoreWorL, for win or loss, passing in that game. Let's add
that method to the team-detail, and you can see here that if it has a scoreDisplay, just grab
the first character, so it's grabbing a W or an L, we're just going to display it there in the
badge. And you can see now that we have the W in the badge, and they're all blue by
default. Let's change the color (Typing). Let's add a danger attribute. So we can see it's
easy to change the color, but now they're all red. We should conditionally change the
color, depending on whether it's a win or a loss. Let's do that next. So let's take out this
danger attribute and I'm going to add a class and this is going to be
getScoreDisplayBadgeClass for the game in question. So that
getScoreDisplayBadgeClass, let's make sure that's added in, and you can see that if it's a
W it'll return badge-primary, otherwise badge-danger. So we can see that they're all blue,
but of course this team won every game, so let's click on another team, the Cyclones, and
we can see that for the games they won it's blue and for the games they lost it's red. So
we're able to use badges to just bring out that information a little easier to give quick
visual indicators, in this case whether the team won or lost the game.

Alerts

The next component we're going to look at is the Ionic alert. One thing we've been
building up to in our app is adding the functionality to follow and unfollow teams. Let's
keep building towards that in our Team Detail page here. Just like on Twitter, we'll give
a button to follow and unfollow and if they unfollow we want to use the alert to show a
confirmation message to the user so that they can confirm if they actually want to
unfollow this team. We're going to take our placeholder comment here and we'll remove
it and we're going to replace it with a couple of buttons here to toggle whether or not
we're following. This first button is when they're not a favorite we'll add them as a favorite
and the second one will be if they're already a favorite. And you can see we use an ngIf
to conditionally display which one is showing at the time. The other thing I want to do is
make sure these columns are evenly spaced, so I'm going to add a width-50 right here,
we'll do that to both columns, and in fact to this one I'm going to add a text-right. In the
team-detail.page let's add isFollowing and we'll initially set it to false and let's also add a
placeholder for the toggleFollow method (Typing). We haven't added functionality yet,
but let's take a quick look at the app to make sure everything is good so far. And yes,
here's our button to add a favorite, we haven't hooked up any functionality to it yet, but
we can see it is right here. Now it's time to use the alert. To the Ionic import I'll add the
AlertController, and you can see this is a pattern here, AlertController, NavController,
LoadingController, and let's inject it into the constructor (Typing). Now let's see how we
can use the alertController. We'll come in here to our toggleFollow method and we'll say
if they are following, then we want to create a confirm object by calling the
alertController's create method, the title is going to be Unfollow. We're going to give it a
little message here, Are you sure you want to unfollow? We're also going to give it some
buttons, the first button is going to have text, Yes, and we can hook up a handler here. So
we'll say this.isFollowing is going to be false. And we'll just put a little TODO comment
in here: persist data here later. And then let's add a second button, we'll just say text is
No, but we won't need any handlers here. Now that we've hooked that up, we can say
confirm.present, and that's actually going to present it to the user. We also want an else
condition here, so if they're not following then we want to say isFollowing is true. And
again, we want to persist here. We'll add the persistence logic a little bit later. Now let's
run the app to see it in action. So here we are back on the screen, I'll click Add Favorite,
it's set it to true, which means that first button got hidden, now we're seeing the second
button indicating that yes this team is already a favorite. If we tap it again that will
unfollow and now we get the alert. Here's the title, here's the message, Are you sure you
want to unfollow? If I say No, nothing happens, we're still following. But if I say Yes,
then the handler will be invoked and it will set it to isFollowing false. So you can see the
alert is very flexible to use, we have handlers we can attach so we can have yes/no, we
can control the buttons, and what logic gets invoked for each button.

Toasts

The next component I want to show is the toast. The toast can be nice when you just want
to display a quick message to the user and then have it automatically dismissed after a
short period of time. In this example let's show the user a brief toast after they have
unfollowed a team, just to give them a little confirmation that the unfollow operation was
a success. So we're going to add our logic to the handler when they say yes they want to
unfollow the team, we're going to add it right here. But before we do that, we have to add
the toastController, just like we did for the alertController, we're going to add the
toastController here and we have to make sure that we inject it into the constructor
(Typing). Now let's go back down here again, here's where we want to put in our logic.
We want to create a toast object by calling the toastController's create method, you can
see a very similar API across these different controllers, where they have the create
method. We'll give it a message, You have unfollowed this team. We can also give it a
duration in milliseconds, so let's say 2000 for 2 seconds, and we can also give it a position,
we're going to make it the bottom, and then toast.present. Again, very similar consistent
API. So you can see that we can change the duration, if we want to make it longer or
shorter, we can change the position, maybe we want it at the top instead of the bottom.
Let's run this now. So we'll come in here and say Add Favorite, and now let's unfavorite,
and we're going to say Yes, and as soon as I click Yes I want you to look here at the
bottom of the screen, so I'll click Yes, and we see the toast comes up, you have unfollowed
this team, it was there for 2 seconds and then it disappeared. So once again you see how
easy it is to use the toast controller, very similar API to some of the other ones such as
the alert controller, and it's always nice to give your user helpful hints in your application
as they're using it.

Summary

This concludes this module on the initial Ionic components. We first covered lists in
greater depth and we saw how we could use list headers as well as use buttons in place of
ion items. We then added list dividers to give a nice grouping effect to our teams page.
We saw how flexible buttons are and how drastically we can change their appearance
with just a few attributes. I showed you how you can reference the ionicons website to
quickly implement professional looking icons in your apps. We then added cards to our
My Teams screen, which helped tremendously to organize the content of our screen. I
also showed how we can add custom CSS, in our case to a card header, to get the display
just how we want it. We then leveraged the Ionic grids heavily, not only to make our
Team Detail screen better, but also to design the entire Standings screen. The Ionic
DateTime component was leveraged to give date filtering capabilities to our Team Detail
screen, and we saw how this component is able to visually adapt to the platform it's
running on. We enhanced that example by using the toggle control to turn the dateTime
filtering on and off. Next we used badges to give a better visual indication about a team's
wins and losses. Finally we used alerts and toasts to start implementing the functionality
for following and unfollowing teams, specifically we used the alert to confirm if the user
actually want to unfollow and the toast to give them an informational message that the
operation was a success. In this module we covered many of the standard Ionic
components you will use frequently. These are components I think every Ionic developer
should learn early on. In the next module we'll go even deeper with Ionic components.
We'll go beyond the basics and show some examples that will come up in real world apps.

Ionic 2 Components: Beyond the Basics


Overview
In this module we're going to continue our journey exploring Ionic 2 components. In the
last module we covered numerous components that are good to know from day 1,
however, in this module we'll go beyond the basics and cover some more intermediate
and advanced components as well as continue to explore more real world scenarios. We're
going to start out talking about Ionic storage and we'll provide some preliminary local
persistence for our favorite teams that we've been displaying on the My Teams home
screen. I'll then show you Ionic events and how we can globally listen for those events
from anywhere in the app. I'll show you the Ionic refresher component that allows the
user to pull down and refresh. We'll then implement a search bar to make it easier for our
users to search for teams. We'll look at potential performance issues of long lists in our
app and we'll use virtual scroll to address those performance issues. I'll then implement
the segment component to add some filtering to our app. It's very common in mobile apps
to include mapping capabilities, we'll add that to make it easier for our users to find the
games. And then we'll add driving directions as well. All of these components are
definitely beyond the basics of just adding simple buttons and lists to our app. And they'll
significantly increase the features and quality.

Ionic Local Storage

Up until now we've just been using a hard coded list of our favorite teams to display
which teams we're following on the My Teams home screen. We're now going to add
some local persistence with Ionic storage. Internally this storage utilizes the browsers
local storage repository and stores key value pairs. One thing to note is that this type of
local storage should only be used for temporary data, that is, data we're okay to lose
because the operating system on the mobile device might decide to clean up that local
storage and we're not in control of that process. In the next demo we're going to implement
the persistence of My Teams with the local storage, but later in the course we're going to
switch the backing store of the local storage over to SQLite where we won't have to worry
about our data being cleared by the operating system. There are two places where we need
to interact with our favorites, one is the screen you see right here where we want to get a
list of our favorite teams to display on the screen. The other is the team detail page where
we can follow and unfollow teams. I'm going to create a user settings service that has the
responsibility of interacting with our storage, so I'll add a new file to the share directory
called user-settings.service.ts. We'll add a service and I'm going to call it UserSetttings.
And there's a couple of key imports we need at the top. We're going to import them from
ionic-angular and they're going to be LocalStorage and Storage. Then I'm going to create
a property called storage and set it equal to a new storage object, specifically passing in
what type of storage we're going to use, which in this case is regular LocalStorage. Now
I'm going to create three methods, one that will favorite a team or follow, another that
will unfavorite a team or unfollow, and a third that determines a Boolean true/false, are
we following a given team? So let's start with favoriteTeam. We're going to pass in a
team, a tournamentId, and a tournamentName. Before we store it in the local storage
system, I'm just going to create a new object here to combine all of these parameters into
one object, so we'll say team equals team, tournamentId is tournamentId and
tournamentName is tournamentName. The API to work with storage is quite
straightforward, all we have to do is say this.storage.set and it's a key value pair, so the
key is going to be the team.id and the value is just going to be an object, it has to be a
string, so I'm going to call JSON.stringify on this item. Now the method to unfavorite a
team is pretty straightforward. We're just going to pass in that team object and we'll say
this.storage.remove, and we'll do it by the key, which is the team.id. Finally, we're going
to have a method that returns true or false, isFavoriteTeam, passing in that teamId and
we'll just return, return area here, this.storage.get and this is based on a promise, so we
say then, if there's a value we'll return true, if not we'll return false. Now since we've
added that file let's go to our shared.ts and let's make sure we're included an export for it.
Now we want this to be globally available in our app, so we'll come in here to the app.ts,
let's add it to the import, we're also going to add it to the providers here. Now that we've
got that in place let's go to our team-detail.page and we're going to add userSettings to
the import and of course we want to make sure we're injecting it as well. We need to use
the userSettings in three places on this screen, first when the screen loads we need to
check if the team is already a favorite so we can set the initial value of the button correctly.
Second, we need to call the favoriteTeam method when the user favorites a team, last, of
course, we need to call the unfavoriteTeam method when the user removes a team as a
favorite, and let's actually name this userSettings with an s at the end. So let's do these
three things now. The first thing I'm going to do is come down to the bottom of the
ionViewLoaded method, right after the team assignment and we'll say
this.userSettings.isFavoriteTeam and we want to check if the current team here will send
in that team.id is the favorite team, and remember this works on a promise which sends
back a Boolean value and we'll just say this.isFollowing equals that value. So that'll
happen when the screen first loads. Now we want to go down to the toggleFollow method
and we have a couple of TODO placeholders here, so one is we have a TODO to persist
the data, this is one we're unfollowing because we're setting isFollowing to false, so for
this one we want to say this.userSettings.unfavoriteTeam and we'll just pass in this.team.
And then finally down here at the end, this is when we are following a team, so we want
to say this.userSettings.favoriteTeam. And we'll send in this.team, this.tournament.id, and
this.tournamentName. Let's just make this a little bit easier to read. Okay let's have a look
at what we have in our app so far. Now here we are in the My Teams screen. Now these
two teams right here are still hard coded and that's why they're showing up at this point.
So far we've only worked on the Team Detail screen. So what I'm going to do is I'm going
to click this first HC Elite on the March Madness tournament to go to Team Detail screen
for that team. We can see here's the Add Favorite button, so it's not detecting that it's a
favorite per our local storage right now. What I'm going to do is come over here to the
Application tab and specifically look at local storage and you can see, it's completely
empty right now. Now I'm going to click Add Favorite, and when it does this we can now
see that we've actually go the data stored in our local storage here. I can then click it
again, am I sure I want to unfollow? If I say Yes, then local storage gets cleared out. Even
more important than that, let's add them as a favorite again, we can see it's stored here,
I'm going to go back to the home screen. Now this time when I come into the screen, we
can see right off the bat this button is now set identifying them as a favorite team because
when the page first loads it detects that, yes, we have the data in storage, so let's show
them as a followed team. So for this screen we're looking pretty good right now. Now we
just need to implement the favorites for this screen so it can show the list of all our
favorites. Now we're going to come back here to our userSettings service and we need
another method for getting all the favorites. We're going to use lodash here and I'm going
to add a method at the bottom called getAllFavorites. And if we look at this method here,
it's just iterating over the properties in window.localStorage, doing a JSON.parse, so we
get the objects for each one, and returning the array. You might notice I'm not using
this.storage here because the default storage API against local storage doesn't have a
method to get all the items, though we will see something a little better when we get to
the SQLite example later. So let's go into the my-teams page, we've got to inject
userSettings, both to import and inject into the constructor. Now the favorites, we can
comment all this out and we're just going to make the favorites an empty array. Then
we're going to come down here and we're going to add an ionViewDidEnter method and
this is going to have one line of code, this.favorites = this.userSettings.getAllFavorites,
and that's it, now we're ready to run the app. And this time when we come into the app
we can see we we've only got one team here and that's because it's actually grabbing this
team from our local storage, so it just shows the one that we've stored in local storage.
Let's prove to this ourselves that this actually works. We'll go add a team from a different
tournament, so we'll click Find A Tournament, we'll call Holiday Hoops challenge and
we'll add HC Elite 7th grade and let's say add a favorite. Now if we go back to the home
screen, we can see that when we come into the home screen both teams are there and
they're both stored in local storage. Local storage can be effective for certain scenarios,
however, remember that if you have data that you absolutely cannot afford to lose, then
it's not an appropriate place to store the data since the operating system might decide to
clear it out. A little later in this course we'll convert this example to using SQLite, which
will provide very reliable local storage.

Events

The next topic I want to cover is Ionic events. Events are useful when we need to listen
for something globally and react to it. It's also a way to communicate between screens,
although for regular screen navigation you should definitely be using normal navigation
parameters. Let's see how we can incorporate this in our app. Here I have the My Teams
screen and we saw that when we follow and unfollow teams they'll automatically show
up here. I also want to add whatever teams we have designated as our favorite teams that
we're following to also be shown on the side menu navigation and when we follow and
unfollow teams, we want that navigation to be automatically updated appropriately. Let's
first go implement this baseline functionality. Here I am on the app.ts and we're going to
add a property for favoriteTeams, and this is just going to be a regular array. The next
thing I want to do is make sure that the userSettings is injected into the constructor. Then
I'm going to add a method called refreshFavorites and in it we're simply going to say
this.favorites = userSettings.getAllFavorites. And when the app first starts up we want to
invoke this method. Now let's flip over to the HTML and we want to add to the side menu
a second section of the side menu just for favorites where we iterate over the favorite
teams that we just added. Another thing you're going to see is that for each favorite team
we're calling a method called goToTeam, so let's make sure we have that implemented
(Typing). GoToTeam is using the EliteApi to get the tournament, the loadingController,
let's make sure we're injecting these things appropriately (Typing). Let's also add the
TeamHomePage to the imports here and now we have no more errors in our goToTeam
method. Let's run the app to see where we are so far. So when the page first loads, we see
the two HC Elite teams, they're also reflected here in the side menu. Let's click on this
one HC Elite 7th, all of that works. I'm going to unfavorite the team, yes I'm going to
unfollow them, now watch what happens here. When I go back to the home screen, the
HC Elite 7th is correctly removed from the My Teams because we refresh it every time
we call the ionViewLoaded method, but if we look in the side menu it's still there. So we
need to use an event to listen for an event of when a team is followed or unfollowed so
we can update this menu appropriately. So when dealing with events, there's two sides of
it, we want to publish the event and subscribe to the event. What we're going to do is in
our user settings here, we're going to publish the event, specifically any time a team
favorites or unfavorites a team, we'll publish that that particular event occurred. To do
this, the first thing we need to do is add the Events object to the list of Ionic imports here
and then we want to make sure that we inject it into the constructor. Then in the
favoriteTeam and unfavoriteTeam methods, all we need to do is say this.events.publish
and we're just going to use a string for a named event here, so we'll say favorites:changed,
and you can make this whatever convention you want. It's even possible to pass
parameters into event publications, though I don't need to do that here, I'm just saying hey
this event called favorites:changed is firing. Now let's go back to the app.ts, let's make
sure we're adding the events to the Ionic imports and let's make sure we're injecting it into
the constructor (Typing), and then when the app first starts up, this is where we're going
to subscribe to the method. We'll say this.events.subscribe, which event are we
subscribing to? favorites:changed. And when we subscribe, we're going to set up a
handler that will be invoked when it happens, this.refreshFavorites, and that should be it.
That should be all we need. Let's go try it out now. Here we are back in our app. We can
see we just have the one HC Elite team that's the favorite, that's reflected on the side menu
navigation as well as the My Teams page here. Let's go find the team in the March
Madness and we'll do that same team, the 7th HC Elite, I'm going to add them as a
favorite. Now let's go back to the home screen, we can see they're added here and now
we can see the event has fired so they've been added here as well. Let's prove that to
ourselves that it works both ways, we're going to unfollow this team, yes we want to
unfollow, when we go back to the home screen we can see it's been removed from the
home screen and as well it's being removed now from the side menu navigation. Events
are not necessarily needed on an everyday basis, but for situations like this where you
need to communicate across pages of your app globally, they are often exactly the tool
you need.

Refresher

The way we currently have the app coded, when a team is selected it pulls down the entire
data set for the tournament that team is in, teams, games, everything. In general, this is a
great performance optimization because data doesn't change that frequently and it would
be an unnecessary performance hit if we pulled down the data for every screen navigation.
However, let's say a set of games just ended and the user wants to see the latest results,
in that scenario we want to give the user an explicit way to refresh the data. We'll
implement this now with an Ionic refresher, which will allow the user to pull to refresh
on the Team Detail screen here, which is a user experience that people have come to
expect on mobile devices. The first thing we'll do here on the team-detail.html is we'll
come in and do an ion-refresher and inside ion-refresher-content. Now we haven't put any
logic in yet, but let's just flip back to the app real quick so we can see what the user
experience looks like. Here I'm back on the Team Detail, I'm going to grab it and pull it
down, you can see the arrow at the top there, and then the arrow up, I'm going to release
it and you can see we have a spinner indicating a refresh operation. Now of course, no
refresh is actually happening yet because we haven't added any code logic to do it, so let's
implement that now. The first thing we're going to do is come into our ion-refresher and
we're going to add an event called ionRefresh and we'll name the method refreshAll. Now
let's go into the team-detail.page and let's add a method at the end and we'll call it
refreshAll passing in the refresher, and we're going to make a call to the EliteApi,
specifically the refreshCurrentTournament, let's say subscribe, and when the data call
finishes we want to say refresher.complete, so it'll stop spinning, and when we want to
call the ionViewLoaded method again so it reinitializes. Now you may notice we're
getting a red squiggle on the refreshCurrentTournament method and that's because it
doesn't exit. So let's go add that now to our elite-api.service. Now we already have a
variable here for the currentTourney, I'm going to add a second variable here called
tourneyData and this is going to be an inline object here that we'll use as a dictionary. So
each time a different tournament gets selected, we'll put it in the tourneyData dictionary.
Now I'm going to come down here to getTournamentData and right now we can see all it
does is an http.get and then it assigns the response to the current tourney. I'm going to
actually have a complete replacement for this method and what you're going to see is it's
now got a forceRefresh parameter, which is optional and by default it's false, and it does
a little logic at the beginning, which just checks, if it's not a forceRefresh and we already
have the data in the tourneyData, then we can set the current tournament to that object
and just return it, no need to make another HTTP call. And you can see I've even put a
console.log in here because I want to be very explicit about it, so you can see what's
happening. On the other hand, if we are doing a forceRefresh or maybe we haven't already
made a call to that tournament, so you can see a console.log saying hey we're actually
about to make a fresh http call here, and then this looks pretty much like the code we had
before, but the only difference being on line 33 we add that data to the dictionary. And
then finally, we actually want to put in this refreshCurrentTourney method and all that's
happening here is we're encapsulating the getTournamentData method with a call to say
true, yes refresh current tournament. So it's really just like calling the getTournamentData
method as we've always been doing, but we're sending in true here, which will force a
refresh, even if we already have the data. Now let's go see this in action. Okay let's see
what happens here. So I'll click this team and this will be the first time the game loads
and you can see it says right here, about to make HTTP call, so because it's the first time
we've requested the data it goes out and makes a fresh HTTP call to the web API. Now
I'm going to go back to the home screen here, I'm going to select this a second time, the
same team, same tournament, and you can see - no need to make HTTP call, just return
the data. So we already have it cached, not need to go get it again, and this is pretty much
what our app has been doing all along. But now we actually want to refresh the data and
to illustrate that you can see this first game here, there's no score yet. So maybe the game
is in the fourth quarter or maybe the game just ended and we want to refresh this to see
what the final score was. So to illustrate that let me actually go into the console here for
Firebase and I'm going to add team1Score, we're going to make it 29, and then let's add a
team2Score, let's make it 41, and let's flip back here and I'm just going to do a pull to
refresh, and you can see we refreshed it and there's the new score, 41-29. It went out and
made a fresh HTTP call to the server to get the latest data. Pull to refresh is extremely
easy to implement and it's a feature that users have come to expect. Don't hesitate to add
this feature in your apps.

Search Bar

Search bars have become a major component in most apps these days. Let's see how we
can incorporate one to give a better user experience to our app. If we look at the Teams
screen here, we'll see that it's not easy to find the team you're looking for. The
categorization by division is nice, but users still have to scroll through a huge list in order
to find the team they're looking for. Let's add a search bar to this screen to make it better.
We come into the teams-page.html, the first thing we're going to do is add a generic ion
all purpose toolbar. And inside we'll add an ion-searchbar. Now to this ion-searchbar we'll
put a couple attributes in, the first one will be plalceholder, and we'll just say Search, and
then we're going to have an ngModel and we'll call it queryText. And let's go into the
teams-page and add the queryText. Now we haven't added functionality yet, but let's see
what it looks like visually first. And you can see, here's our search bar right at the top,
now let's add functionality to it. Let's add one more attribute here, it's going to be an
ionInput and the method we're going to give it is updateTeams. Then let's flip over to the
team.page TypeScript file and let's add the updateTeams method. Now let's have a look
at what this method does. The first thing we're going to do is we're going to get the input
from the textbox and we're just going to do a brute force toLowerCase on it, so here's our
text here, and then we're going to keep an array of what are the filteredTeams now. And
then we're just going to use lodash to forEach over all the divisionTeams and we do a
quick filter here for just the divisionTeams, and if there's actually results then we push it
onto this temporary array. We're doing this because the teams currently have that
hierarchical structure, so we have to go into each of the divisions to find the teams to see
if there's any matching teams. And when we actually are doing the filter we can see that
we're filtering the divisionTeams and we're doing a toLower here too and the includes is
essentially doing a substring on each item. Let's go have a look at the results. So we'll go
back into the Teams screen. Here's our search bar, we'll tap into it. I'm just going to type
hc and you can see that every time I type it updates and here's all the teams that have hc
in the name, these first four have hc to start the name, this one down here has hc inside
the name. Let's type cy and you can see we have Cyclones, and it does it across the
divisions. Now we can see that everything is being filtered correctly. In my case I had to
write a little extra code to deal with the hierarchical data. If this had just been a flat list it
would have been even easier. But either way, you can see that we can give our users a
pretty good search experience without having to write a ton of code ourselves.

Virtual Scroll for Lists

I'll be happy to admit it, I do 90% of my mobile app development using my browser here,
especially when I'm working on screens that don't require the native capabilities of the
mobile device. The convenience of the Chrome developer tools along with live reload is
just too hard to beat. Having said that, you must set aside time to test with an actual mobile
device, in particular it is just too easy to find situations where the performance looks
fantastic on my desktop browser here using my powerful development machine, only to
deploy the app to the device and find out we have significant performance issues when
running on the device. Let's work through one such example now, and then we'll add how
to fix it. So if we look at the Standings screen here, running on my normal desktop
browser, we can see there's a ton of teams in here, it's a huge list of teams and the
performance appears just fine. Now let's see what this same screen looks like on the actual
device. Here I am now running this exact same screen on my actual device, so this is not
a simulator, I'm actually holding my phone in my hand and reflecting the screen onto my
computer here. Same screen, if I use my finger to start scrolling down, you can see it's
actually horrible performance, it stops and starts. I can scroll for awhile and then it's very
choppy and it's really a horrible user experience up and down, and what's happening here
is the mobile browser is having a difficult time keeping track of these many items in the
DOM. When we typically have pure native applications they have controls, which add
and remove items to the list using a virtual scroll and all this is happening on your behalf
behind the scenes. Well with the Ionic framework we now have a virtual scroll here as
well, so we can approach the situation in much the same way that a pure native developer
would do it. Let's implement virtual scroll for this list now to see how we can improve
the performance of this screen on the actual device. Here I am in the standings component
and if you remember previously, one of the things we had to do was we had to use this
lodash query here to take what was a flat list of standings and we used the groupBy on
the division here to make it a hierarchical data structure so we could get the grouping for
each standing. When working with a virtual list, we actually need a flat structure. So the
first thing I'm going to do is I'm going to comment out this line completely, we won't be
using all standings, let's comment that out too, we're just going to use what we already
have here, which is the flat list of all the standings together. Now let's flip over to the
HTML page and here's our ion-list that we're using right now, we can see all the standings
in here, and let's just, I did a hard return a couple times to move that a little bit out of the
way, and we're going to create a new ion-list and inside this ion-list we're going to add an
attribute here for virtualScroll and we're going to set that equal to that standings property
that we already have. Inside the ion-list we're going to add an ion-item and in this ion-
item we're going to add an attribute called virtualItem. And inside we're going to say let
team. You can think of this sort of like an ngFor, we have a list here for our virtualScroll
standings, and this is an array of teams, so each team in that list is going to go on a virtual
item here, so that's why we say let team. This is representing one instance of a team of
this entire standings array, which is an array of teams. Now what I'm going to do, down
here on the old list we have the ion-item here where we are doing let team as part of an
ngFor and we had three rows in here. Here's an ion-row for the team name, here's an ion-
row for the header columns, and here's the third ion-row of the actual values. I'm going
to take these three rows right here and I'm going to cut and paste them into this ion-item.
Let's format. Now the other thing I want to put in the ion-list is another attribute called
approxItemHeight and inside that we're going to set it to 132 pixels. This is used to help
calculate the height of the scrollable area and how many cells should initially be created.
Now a lot of people look at this and think, wait, shouldn't my CSS be determining the
size of each item? And yes it should and it is. This approxItemHeight attribute is used as
a performance optimization to calculate the height of the scrollable area that those items
are inside of. Let's run the app on the device again to see how performance may or may
not have been effected. Now here I am back on my mobile device, we're back on the same
Standings screen, now let's see how the performance is. As I go through you can see
there's not that same choppiness that we had before, in fact it's performing really fast and
I can get down to the bottom of the screen with a few swipes and there I am right down
at the bottom of the screen. So the performance is actually pretty incredible right now and
this really looks a lot more like what we'd expect from a native app, that's the kind of
performance we have right now, which is really great. This is very promising. However,
even though performance is now much better, we've lost all our nice division headers that
we previously had. And this happened when we moved back to a flat structure. So let's
see how we can fix that now while still using the virtual scroll optimizations that are
giving us this native-like performance improvement. Back on the standings page, there's
a couple of things we need to do to allow us to have headers in a list that's user virtual
scroll. First, inside the ion-list element, I'm going to add a new attribute called headerFn
for header function and we're just going to refer to a method named getHeader. The other
thing I'm going to do is remember this original list we had down here, I'm going to take
this ion-item-divider and I'm going to cut and I'm going to paste that right up here, and
just like we had a virtual item attribute down here, we're going to add a virtualHeader
item up here and we'll just say let header, similar to how we had let team down here. Now
division.divisionName, that only existed when we had the hierarchical data so we're just
going to replace this with header, which was referring to this variable right here for the
header. So you can see that we've basically taken all the structure that was up here and
we've moved it to the list up above. So we don't even need this anymore, it's essentially
an empty list, take that out completely. And we've just referred to this getHeader method
here, and this is called for every row and it's used to determine do we need to add an ion-
item-divider here, which is our header. So let's flip back over to the Standings page and
we're going to add this getHeader method right here, it's going to take in a record, a
recordIndex, and then look at all the records. First let's just do a contrived example. I'm
going to say if the recordIndex, and we'll say mod 10, so if the recordIndex is divisible
by 10 return Header, otherwise we'll return null. Let's just run this first in the browser. So
here we are in the browser. We see a header right here, we scroll down about 10, we see
another header, if we scroll down another 10 we see another header and so on and so
forth. So we can see that function is getting called, but right now it's not that helpful
because we're just arbitrarily putting headers in here every 10 records. Let's see how we
can fix the logic to actually put the division names in there where they're supposed to go.
So we have a couple of conditions we need to check for. First if the recordIndex is 0, that
must mean we're on the first team, which is the first division, so yes we want to return the
actual record in that case. So instead of saying Header, we'll just say return
record.division. The other condition we want to check for, let's say we're not on the first
one so we have an or here, what we want to check is the division of the current record,
not equal to the one that came right before it. Now with that simple logic let's see how it
looks. Now here I am back on my mobile device, I'm holding my phone in my hand, and
we can see the first division there is 3rd grade and if I scroll down we can see there's 5th
grade Black, here's 5th grade White, there's 6th Black, 6th White, and now we can see
we've got the divisions in there exactly where they're supposed to go, we still have good
performance, the scrolling is smooth, we're getting native-like performance. I strongly
encourage you to incorporate virtual lists, which gives you virtual scrolling capabilities
into your app. Your users will thank you and your performance will be outstanding.

Segment

The ionic segment component is ideal when you want to provide different views often for
filtering data. It's not exactly like tabs because it doesn't typically involve an actual screen
navigation. Again, typically it's just used for filtering operations. Our Standings screen
here is coming along, but it's still a long screen. That view might be helpful some of the
time when we want to see the entire tournament, but it would also be helpful if we could
just filter the Standings screen for the division of the team we're currently looking at. For
example, I see this as HC Elite 7th, wouldn't it be nice if we could just filter it for the
division that this team is in? Let's add the segment component to the Standings screen to
make this happen. In the ion-header I'm going to add an ion-toolbar and then inside this
I'm going to add the ion-segment with two ion-segment-buttons, so we'll say times 2. For
the first button we're going to have an attribute that says value = division and the text of
the button will simply say division. Similarly value = all and the text will be All. And we
can add a secondary attribute here. Now we haven't actually added any logic yet, but let's
just see what it looks like visually in our app first. So we'll come back into the Standings
screen and we can see the segment right at the top, I can switch between Division and
All, and this currently looks very much like an Android look and feel. Let's switch over
to iPhone and refresh completely (Typing), and now we can see it looks very much like
an iPhone segment. So the segment control is another one that will dynamically adapt to
the platform you're running on. Now let's go add some logic to this. In the ion-segment
we're going to add a couple of things. First an ngModel and it's going to say divisionFilter
and then we're also going to add ionChange event and this is going to be filterDivision.
Now let's go add these two things to our standings component. First I'm just going to add
a divisionFilter, which is a simple string, and we'll set it by default to be the divisionFilter.
Then in the ionViewLoaded at the very bottom, remember this allStandings that we
previously used? We're going to bring this back, we're going to use it for a different
purpose now, we're going to say allStandings = tourneyData.standings. So if you look at
24 and 35, they're the same assignment. Initially we'll set them to the same value, but
we're going to use these for different purposes. Now let's add this filterDivision method
and what we can see here is if the divisionFilter equals all, well just set the standings
equal to the allStandings. So allStandings only job is going to be to hold that full list of
allStandings, otherwise if the divisionFilter is not all, now we're going to filter
allStandings by the division of the team that's currently selected. And we want to make
sure when the screen first loads this logic is invoked as well, so right in the
ionViewLoaded method we'll make a call to it. So filterDivision will be called the first
time the screen loads as well as as a result of the ionChange in the segment control. Now
let's go run it again. So we'll go back into HC Elite 7th to the Standings screen and
automatically division is already preselected and since HC Elite is a 7th grade division
we just see 7th Black here, it's just in that one division. So we can just see their division.
We can still flip over here and see all the divisions like we always could, but we can
always flip back and say oh I just want to see the division for the team I'm currently
interested in. And remember the segment control will dynamically adapt, depending on
whether you're running on Android or iOS. Don't hesitate to use the segment control in
your app to provide a visual for quick filtering capabilities.

Putting It All Together

At this point we need to set up the games page a little better because we're going to have
other things hanging off of it like mapping. In this next demo I'm not going to introduce
any new concepts, but we will be putting many of the concepts we've already learned all
together. Let's take out what was essentially temporary content here for the ion-content,
and let's fill in with some more robust content. What I've done here is I have a few
different rows, the first row has a couple of buttons, one for the Home team and one for
the Away team. And if we tap either one of these, it'll take us to the team home for each
of those respective teams. The next row, very similar, instead of just saying Home or
Away, it'll actually say the team name for the home team and the team name for the away
team. Similarly, if we tap either one of those it'll take us to the team home for each
respective team. For the next row we'll show which team was the winner, which team was
the loser, and we'll change the primary color of the class depending on if they' won or
lost, same tap rules apply. Down here we're going to have an Ionic card, which we've seen
before. This card is going to have an item that's just going to hold an icon of a calendar
with the date and time of the game, and down here we're going to have a label with the
location and some buttons that will eventually give us mapping and directions. I also don't
want to forget to add the primary attribute to this navbar as well. Now let's go to the game-
page. There was a couple of new methods we just added, so let's fill those in.
GoToDirections, goToMap, isWinner, I'm not going to put any content in them right now,
we'll use those in a subsequent demo, but they're just placeholders for now. The other
thing I want to do here in the ionViewLoaded is we need an actual date data type and the
game time, unfortunately, is just a string. So we'll change this to this.game and we'll add
a gameTime property and it's going to be equal to Date.parse(this.game.time). Another
thing I want to do is add a Sass file. So we'll come in here to the game folder, New File,
game.page.scss. And we'll just add some custom styles here. Let's also not forget, since
we just added a custom Sass file, we have to come in here and add the import for it. Now
let's see how our Game screen has been improved. Now our Game screen is looking much
better. We see Home or Away. I can tap any one of these, let's say I tap the Cyclones, and
it takes me to the Team Home for the Cyclones. Same if I tap the Home. If I tap Away
it'll take me to HC Elite 7th. We can see the score for home and away, tapping the score
will also take you to the Team Home page. And then we have the actual date and time of
the start time of the game and the location, and here we have our placeholder buttons for
mapping and driving direction. You can also see some borders here, which we added from
our custom Sass. Now the Game screen is looking much better. In our next demo we're
going to add functionality to add mapping and driving direction capabilities.

Mapping

Now it's time to add mapping to our app. It's nice that we're giving people a schedule of
times and locations for the games, but it would be a lot more helpful if we also added
mapping to help get them to the games. Let's add another page to our app for the map
page (Typing). Now that that's been created, we see it right here, let's go to our pages.ts
and make sure we're adding the export for it. Let's make sure we can navigate to it from
the Teams page. And we have a placeholder here, goToMap, where we're just going to
say this.nav. the typical push, go into the MapPage and we'll send in the current game.
Let's just show basic navigation before we go any further. Here we are in the Game screen,
I'm just going to click this button for the map, and it sends us to the Map page. The next
thing I want to do is to install a new package into our app called Angular 2 Google Maps.
What I'm going to do is I'm going to put it directly in my package.json file, angular2-
Google-maps. And I'm going to put a specific version in here, a 0.12.0 because I know
that's the version that works with the current version of Angular that I'm using. Depending
on when you're viewing this course, this may be the same version you're using, or you
may be using a later version. You just want to check the documentation for Angular 2
Google Maps to make sure you're using the right version. Additionally, remember I have
that GitHub repository that I'll keep up-to-date, so you can always consult that as well.
With that line in place I'm just going to run an npm install which will install any packages
that haven't already been installed in my package.json file. Now let's come into my app.ts
and I'm going to add an import here for angular2-Google-maps/core, specifically
GOOGLE_MAPS_PROVIDERS. And I'm going to add this to the list of my providers.
Now let's go to the Map page. I want to add import here too and in my component I want
to add directives specifically for that Google Map providers. Let's also replace
navController with navParams because I don't actually need the navController anymore.
And I also want to import the EliteApi and inject it into the constructor. Now what I want
to do is add a single property that's going to represent the map right here and I'm just
going to add a snippet for the ionViewLoaded method. Now if we look what I just added,
all I'm doing is I'm assigning a game to a local variable, I'm giving the tournament data,
and then more importantly I'm getting the actual location, so I'm looking up the location
from the list of all locations using that locationId. So those three lines are somewhat
boilerplate. What's more interesting is let's start assigning this map property (Typing). I'm
going to give it a couple of properties, one for lat, which is location.latitude, another for
lng, longitude. Then we're going to give it a default zoom level, we'll make it 12, and I'm
also going to assign a markerLabel, which is just going to be the game.location. Now let's
go into the HTML. In the content I'm going to add the sebm-google-map. And let's just
add some baseline properties. I'm going to give it an id of map, now I'm going to give it
a property latitude = map.lat, then longitude = map.lng, and let's also give it a zoom. Now
without going any further, let's see what our app is displaying visually so far. Here we are
back in the Game screen, let's click the Map button, oh and we can see we've got an error
here, unexpected directive. I think I know what the problem is, let's fix that. The mistake
made was that on the map page I accidentally imported GOOGLE_MAP_PROVIDERS
and I meant to import GOOGLE_MAP_DIRECTIVES. And similarly, I added the
providers down here to the directives and I meant to add the directives. So that was a little
bit of a silly mistake, but these are exactly the types of things you might encounter in real
world apps, so it's good to know how to debug them. Let's have another look at that screen.
Now back on the Game screen, let's click the Map button, and this is something you might
often run into, you come to the Map screen, you think you've set everything up correctly,
and it's blank. So this is a common gotcha you need to watch out for and the reason is
because we need to add CSS to actually set the dimensions of the map, so let's fix that
next. I'm going to come I here to the ion-content and I'm going to add a class and we're
going to call it map-page. Then we're going to add a new file to the map directory called
map.page.scss and this map page is going to have a width and a height of 100%. Now
since we added a custom scss file, we have to go down to the themes and add the import
for it. Now let's have another look. From the Game screen, let's click the map, and now
we have a nice map displaying. Now we're getting somewhere, let's add a couple more
features. Inside this Google Map we're going to add an sebm-google-map-marker. And
I'm going to copy the latitude and longitude, so the center of the map is going to have the
marker where this game is. Now let's have a look at the marker. Once again, from the
Game screen click Map, and we can see we have a marker right in the middle. Now let's
add a label. We'll add sebm google-map-info-window, and in here we're just going to put
a bold label that says map.markerLabel. From the Game screen we click Map, this time
when we click the marker we can see we have a marker label that pops up in the info
window, and it's set to the location for the game, which was Meadowbrook Ct. 2. So it
wasn't difficult to add mapping to our application at all. There's just a couple things to be
aware of, one, make sure you're setting your CSS properly, secondly, these are open
source libraries which are subject to change so always make sure you consult the
documentation, it may not match exactly to the version I'm using at the time you're
viewing this course, but again, I will keep the GitHub repository up-to-date just in case.

Driving Directions

It's great that we now have the map showing, but it would be even better if we provided
driving direction to people who are trying to get to a game. Let's add that now. From the
game.page we have this goToDirections method that has a placeholder in it, so let's
remove that, and I'm just going to add a couple lines of code here. So I'm just getting the
tournament data, then the location, then I have windows = location, and actually I meant
to put some back tics in here. Now one thing you're going to notice is we are getting some
red squiggle here for window because it doesn't know what window is. So let's make sure
we go up to the top and I'm just going to add an ambient declaration for this, it's a
TypeScript concept, which is basically just saying declare var window, and we're telling
TypeScript, trust me this window object will be there at runtime. And we can see the red
squiggle is now gone. So we're sending window.location to this geo protocol and we're
sending in the latitude and longitude. Let's add similar functionality to the Map page.
Above the Google Map I'm going to add a button and it's going to be fab for floating
action button and we'll say fab-left and fab-bottom. We'll also add a class called fab-map
and a click handler that says getDirections. Inside the button we'll just put an ion-icon
and the name will be navigate. Now you just saw me add this class for fab maps, so let's
go into the map.page.scss and let's add that. And you can see it's just calculating some
positional elements of the button. Let's go into the TypeScript file and we'll do the same
thing for the ambient declaration (Typing) and we're going to put a similar
goToDirections method in. Let's run it, but we're going to run it on our actual device since
it's going to get directions from our current location. Here I am back on my actual device.
We have these two buttons here, the one on the left is for the map, the one on the right is
for the navigation, the actual driving directions. So I'm going to tap this button on the
right and we're going to see that it opens up. Now since I'm on Android, it's giving me a
choice, let's of course use Waze, and I'm getting driving directions to that game. Let's go
back. This time I'm going to tap the Map button on the left, we can see the map loads,
there's my floating action button on the bottom left, let's tap that. Oh and nothing's
happening. I think we have another bug we need to fix, let's fix that real quick. And sure
enough, we can see that for the floating action button we named this getDirections, but in
the TypeScript file we named it goToDirections. So let's fix that, and now let's rerun it to
make sure everything's working correctly. Let's go back to the Map screen, there's our
map, our floating action button, let's tap it, and this time it's working. We can Waze pops
up exactly the same way it did before. It only took us a couple minutes to add driving
directions, it also didn't take us long to add maps. These are feature rich areas that your
users have come to expect, so I encourage you to put them in. And remember just always
consult the latest documentation on the third party libraries that you're using.

Summary

That concludes this module on Ionic 2 Components: Beyond the Basics. Unlike the
previous module where I introduced the more foundational components, like buttons and
lists, in this module we looked at some more feature rich scenarios. We started by looking
at local storage with Ionic so we could store our favorite teams and display them on the
My Teams screen. We then added events so we could globally listen for changes to the
teams that we're following and unfollowing, so we could update the side menu
immediately. We added pull to refresh functionality using the Ionic refresher component
so that users could explicitly refresh the data from their Team Detail screen. You saw me
add a search bar to our Team screen to make it very easy for our users to find a specific
team within the long list of teams. Probably the most important demo I showed was virtual
scroll for lists. I showed how the performance looked great on our desktop browser, but
then was horrible when we deployed it to an actual mobile device. Once we added virtual
scroll we had native-like performance. We added a segment component to our Standings
screen so we could switch between looking at the standings for the entire tournament
versus just filtering down to the division containing our team. At the end we used Angular
2 Google Maps to provide mapping in our app. You also saw me implement driving
directions in just a few lines of code. We've covered a ton of Ionic components already
in this course. In the next module we're going to focus on Ionic native, which gives us
access to the native capabilities of the mobile device.

Ionic Native
Overview

In this module we're going to cover Ionic Native. The Ionic Native library is what enables
your Ionic Cordova-based apps to be able to seamlessly access the native capabilities of
the device. Before we dive into Native plugins, we'll first answer the question, what is
Ionic Native? Then I'll show you how you can find Native plugins and add them to your
app. After that we'll get into code examples and I'll start by showing you how to use the
vibration plugin. We'll then see how we can use geolocation to get the current coordinates
of the device. I'll show you how you can use the device camera within your app. Then I'll
show how to use the barcode scanner. We'll cover how we can access the accelerometer
with the device motion plugin and I'll show how you can implement local notifications.
I'm actually going to do the demos I just mentioned in a separate app from the Elite
Schedule app that we've been building, but at the end of this module we'll get back to
building our Elite Schedule app and we'll integrate the Native SQLite plugin into that app.

What Is Ionic Native?

Before we dive into Ionic Native, it's important to just take a few moments to answer the
question, what is Ionic Native? In short, Ionic Native provides access to native device
features. Sometimes you hear people say they need to write a native app instead of a
cross-platform app because they need to access to certain native device features. This
assertion just isn't accurate because Cordova plugins enable you to access all these native
APIs. Examples of these are the camera, geolocation, accelerometer, and more. Cordova
plugins, which wrap native features, is not a new concept. What Ionic Native itself does
is to provide nice wrappers around these Cordova plugins, which have been notorious for
not always having the most developer friendly APIs. These native plugins actually use
native code, so Java on Android, Objective-C on iOS, C# on Windows, and so on.
Sometimes you hear people say that performance won't be good enough for that
JavaScript cross platform app in some area of their app. Not only are these assertions
typically misinformed, but also if you do find a case where that is true, you still have the
option to drop down and write native code in your cross platform app for these areas. This
truly gives you the best of both worlds. These Ionic Native wrappers can be used
regardless of whether you're writing your app in ES5, ES6 or TypeScript, so it should be
noted that you'll get the richest experience if you're using TypeScript. A few moments
ago you heard me say that Cordova plugins were known for not always having the most
developer friendly API. Part of that is always using traditional callbacks. Another thing
Ionic Native does for you is to wrap those callbacks in promises and observables, so you
can have a much more modern and easy to use API. Another differentiator with Ionic
Native is that it represents a curated list of native plugins. This is important because there
are many very low quality native plugins floating around out there. However, all the
plugins wrapped by Ionic Native have been curated by the Ionic team so that only high
quality plugins make it in. I should note that how to write your own native plugin is
beyond the scope of this course. In this module we're going to dive into how you can
discover, add, and implement Ionic Native plugins in your app.

Finding and Adding Ionic Native Plugins

In order to be able to add native plugins to an app, it is of course important to know how
to find them first. Here I am on the Ionic Native website, and you can see in the left hand
nav that I can scroll down on a huge list of curated Ionic Native plugins. I'm going to
click the one near the end here called vibration because I know that's the first one that
we're going to be implementing. For this module I'm going to set aside the Elite Schedule
app that we've been building and I'm going to use a new demo app just for the purpose of
showing Ionic Native plugins. What you see here is just a basic shell, which resulted from
running the Ionic start command with the side menu template. This is exactly what you
saw me do in the beginning of the course, so nothing new here. I basically just got a side
menu with a generic home page and an empty page for our vibration demo here. Nothing
else has been added. Here's just a quick look at our basic shell, we have the generic Home
page here, I've got side menu navigation, I have this one additional page called Vibration
and if I click it you can see there's just an empty vibration page so far. Now it's time to
actually add a plugin to our app. For every Ionic Native plugin that you use, you should
go to the documentation page for that plugin and you can see right at the very top the
ionic plugin add command that you need to use. So in this case we have ionic plugin add
cordova-plugin-vibration. Let's add that to our app now. Back in the Ionic cli we're going
to run this command, ionic plugin add cordova-plugin-vibration. Now this has just added
the vibration plugin to our app. Let's have a look. We have a plugins folder right here, I'm
going to expand that. We had a few plugins that were added by the new project template
by default. Here's the vibration plugin that we just added. And we can see in the www
folder we have this vibration.js. And this has a couple of methods defined in here, vibrate,
vibrate pattern, and this is generic Cordova wrapper that's wrapping around the native
APIs. We can actually drill down into the plugins to see the native code for each
respective platform. For example, here's the Android, here's vibration.java and we can
see the Java code that runs on Android. Here's iOS. We can see some Objective-C code
that runs. Here's Windows. We can see some C# code that runs. So you can actually see
the native code that's going to run on the respective platform. Taking a step back, it's
valuable to know how a typical native plugin is structured, but the IonicPluginAdd
command was all we actually needed to add the vibration plugin to our app. Now that it's
been added, we'll see how we can implement and use it in the next demo.

Vibration

Now that we've added the vibration plugin to our app, it's time to implement it. Here I am
on the vibration page HTML and I'm going to add a couple of buttons. For this first button
we're just going to say Vibrate and we'll make this full, we'll give it a click handler, and
we'll just call a method named vibrate. I'm going to copy this button and add another one
below it called Vibrate Pattern and the method will be vibratePattern. Now if we flip over
to vibration.page.ts, the first thing we need to do is add an import for Ionic-native and
specifically what we're going to import is vibration. Now you saw this import right here,
Ionic-native, another thing I just want to point out is that down here in the package.json
we actually have a package called Ionic-native right here. It's not always noticeable
because it's added to our project by default when we first run the Ionic-new-project
command. Now let's add our methods. The first one was vibrate, and all we're going to
do is we're going to say vibrfation.vibrate, and then it takes milliseconds, so we'll give
2000, so it's 2000 milliseconds, which is 2 seconds. Let's add a second method here,
vibratePattern and this time we're still going to call the vibrate method again, but we're
going to send it in an array. So what's going to happen here with the array is the first
argument, 2000 milliseconds, that's how long it should vibrate. The second argument,
that's how long it should pause, no vibration, and then we're going to do another vibration
500 milliseconds. So it's going to vibrate for 2 seconds, nothing for 1 second, and then
vibrate for a half a second. Another thing to point out is that the native plugins aren't
always identical on every platform. For example, vibration.vibrate on iOS, it just does a
basic vibration and you're not allowed to control the duration, you also can't give it a
vibration pattern. However, on Android you can control the duration and give it a pattern.
Another thing to point out is if I had done this import command and all my code and all
my code looks great, but if I had forgotten to actually add the vibration plugin to my app,
that's a case where the object will be undefined because you haven't actually added that
library, so always make sure you're actually explicitly adding the plugins that you're
using. Now let's go look at the app on the actual device. Now here I am on my actual
Android devices, I'm holding the device in my hand, casting it to the screen, and you can
see we have the generic Home page here. I'm going to tap the side menu and then select
Vibration, so we're navigated to the Vibration screen. This first button here, Vibrate, I'm
going to tap it and it should vibrate for 2 seconds because we said 2000 milliseconds for
that argument, I'm going to do that now. And hopefully you could hear that vibration as
I held it up to my microphone. Let's tap the second button now, and remember the pattern
we used was vibrate for 2 seconds, then pause for 1 second, then vibrate again for a half
a second, which is 500 milliseconds. So you heard the longer vibration and then a 1
second pause and then the shorter 500 millisecond vibration. The vibration plugin is a
good example of how easy it is to add native plugins to your app and in many cases be
able to access those native device features in just one line of code. In the upcoming demos
we'll look at several other native plugins.

Geolocation

The next plugin I'm going to show is geolocation. Always remember the first step is to
run the Ionic plugin add command, in this case cordova-plugin-geolocation. Now I'm
actually not going to take time for you to watch me run it right now, I've already run it.
So let's jump straight to the app. Here I am back in the app, I'm holding my Android
device in my hand. I'm going to tap the side menu and you can see I've actually added a
whole bunch of screens now, there's not very much code here and we're going to look at
the code sequentially one by one. For right now, we're going to look at the geolocation,
which is the item right below vibration. I come into the geolocation screen, you're going
to see I have one button and it says Get Geolocation, I'm going to tap that button and we
can see it gives my latitude and longitude of my current position. Now let's go look at the
code behind the scenes that made that possible. Now if we look in my pages directory
here, you can see I've added a few more screens and I'm going to show the code for each
one sequentially, but for right now let's focus on geolocation. First in the HTML page,
line 12 here, you'll see the button that was on the screen getGeolocation, it's calling a
method called Get Geolocation, and then when it returns, you can see it's putting the
latitude and the longitude hanging off of this object called location that has a lat and a
long. Now let's go look at the code for the getGeolocation method. I'm going to flip over
here, you can see first we've got the import statement up at the top, import Geolocation
from ionic-native, and then down here we have getGeolocation, which is simply called
getCurrentPosition, returning a promise and then I'm populating that location object with
this response object that has coordinates for latitude and longitude. And that's it. That's
all you need to use the geolocation plugin.

Camera

Our next plugin is the camera plugin, very commonly used in mobile apps. You can see
at the top here we need to run ionic plugin add cordova-plugin-camera. Let's go look at
our app screen first. Here I am on the camera screen and it just has one button that says
Take Picture. I'm going to go ahead and tap that and I'm just going to take a picture of my
keyboard here. It's taken the picture, I have some buttons at the bottom to accept or reject,
I'll tap the checkmark. And you can see, it's taken that picture and it's put it right on the
screen under my Take a Picture button, essentially embedding it into my app. Let's go
take a look at the code that made that possible. Here I have the camera.page.html. Here
on line 12 is that single button you saw that said Take Picture and it's just calling a
takePicture method, and then I simply have this Ionic-card down below it that has an
image element in it, as you can see the src attribute is being bound to this imageSrc
property. If we flip over here to the camera.page.ts, we can see that I'm importing a couple
of things on line 3, the Camera and CameraOptions from ionic-native, and if we scroll
down we can see that the options on line 14, that's CameraOptions, there's actually more
than even you can see right here, I've just filled out a few of them. This is saying I want
to get a file URI, I want to use the camera. The source type may seem obvious that it's
camera, but you can also, for example, select from a photo gallery. You can specify your
encoding type, in this case I did png, and you can give it a target height and width. You
can also set a Boolean, true/false to save to photo album on the picture you take. I've just
set it to false, I don't want to save it to a photo album because I'm just embedding it into
the app. Then on line 23 we actually invoke this getPicture method, passing in our camera
options, and then we have a promise here which is simply returning an imageUri because
we specified fileUrl on line 15, and we're simply setting the imageSrc equal to that
imageUri that comes back. The camera plugin is one of those Cordova plugins that's been
around for awhile. So it's well established and pretty easy to use.

Barcode Scanner

The next plugin we're going to look at is the barcode scanner. We need to run ionic plugin
add phonegap-plugin-barcodescanner. The barcode scanner is pretty robust and it can
scan barcodes in many different formats. Let's see it in action now. Here I am on the
Barcode Scanner screen and I just have two buttons, Scan and Reset. I'm going to tap the
Scan button, you can see I've just got a box of Cheerios here, I'm going to scan the UPC
code, you can see the format and the text just came up. Now I'm going to tap this blue
Lookup button and it's going to open in Chrome, send to a webpage, and it successfully
found from the UPCindex.com this box of Cheerios. And we can always hit the Reset
button to clear it out. So when you use the barcode scanner it's quite automatic. Let's have
a look at the code. Once again, the HTML is quite straightforward. I have two buttons,
one that calls a scan method and one that calls a reset method. And then I have an area at
the bottom for results where we see the Format and the Text and a button that's providing
the lookup. Let's go have a look at the scan method. You can see on line 2 we're importing
the barcode scanner from ionic-native. On line 13 we have the scan method and it's
BarcodeScanner.scan, then we have a promise here sending back that barcode data. So
the results property is the one where we assign the barcode data so we can see the format
in the text. Then we had a lookup and that was actually quite easy, I just called
window.open, sending it to the website and sending the text in, almost like a query string
parameter.

Device Motion

The device motion plugin allows us to access our device's native accelerometer so we can
track location in all three axes, the X, Y, and Z axis. To add it let's run ionic plugin add
cordova-plugin-device-motion. Let's see it in our app. Here I have my Device Motion
screen and I have two buttons, Start Watching and Stop Watching. Now when I tap the
Start Watching, which you're going to see when we eventually get to the code, is that I
can set the refresh rate, and I think I have it set to about a half a second right now. So
every half second it'll tell what the acceleration is of my device on all different axes. So
I'm going to the patient Start Watching. I'm going to move it up and down real quick, you
can see the Z axis moves a little bit. I'm move it left and right and you can see the Y axis
goes up a little bit, even sometimes X is negative if I'm moving to the left or to the right,
and it's extremely fine tuned. I'm actually going to set my phone down on the table and
what you're going to see is X and Y go almost to 0, not quite because it's not 100% precise.
You're going to see the Z axis gets close to 9.81, again that's not 100% precise, but it's
close, and 9.81, of course, that's the acceleration of gravity, 9.81 meters per second. Now
I'm going to tap the Stop Watching. Let's go have a look at the code. Over here on my
device-motion.html we can see my two buttons on line 12 and 13, Start Watching and
Stop Watching. And then down below is just very simple X, Y, and Z axis and I just have
a number piped that I'm using here to constrain to 4 decimal places, it can actually go out
probably 3 times that number of decimal places if you wanted it to. Let's go look at the
TypeScript. We're importing a couple of different things on line 2, AccelerationData,
AccelerometerOptions, and DeviceMotion. In the startWatching method, you can see it's
using AccelerometerOptions, which is the frequency, this is 500 milliseconds. For
example, I could set it to check every 10 seconds, just give me 10 second periodic
intervals checking my acceleration. Or if I wanted to do it very fast I could do it maybe
every 10th of a second. Whatever my options may be I call the watchAcceleration method
right here, passing in those options, and I subscribe to it. The subscription gets
acceleration data as a result and I'm just setting that to the data object, which is what we
were displaying in our view. And then stopWatching is simply unsubscribe. The
deviceMotion plugin could even be used, for example, if you were creating a driving app
and you wanted to see how many miles per hour someone was traveling at a given
moment. But there are many other uses for this plugin as well.

Local Notifications

The local notifications plugin allows you to schedule local notifications on the device.
Typically people think of push notifications where information is coming from a server
somewhere and pushing it down to your device and it shows up in a little alert area of
your phone, but you can actually schedule local notifications as well, they don't all have
to come from the server. For example, you might schedule meeting reminders. To add the
local notifications plugin, of course always remember to run the ionic plugin add
command, as you see right here. Let's go look at our app. Here I am on my Local
Notifications screen. It's just got a single button called Schedule Notification. I'm going
to go ahead and tap that button and it's just scheduled a notification and what we just saw
up in the upper left of my screen, we have that little bell icon that appeared in the
notification area, I'm on Android so I'm going to swipe down from the top, and what we
can see here is we have this Cool Notification. This is my cool notification and a little
bell icon. I can tap that notification and then I'm back in the app, Alert, Notification
received, Notification 21, and we can see it displayed on the screen, Notification 21. Let's
have a look at the code. The HTML is very simple, just a single button that calls a method
named scheduleNotification. And then we have this results area in an h2 tag. Let's flip
over to the local-notifications TypeScript file. We can see on line 2 we're importing local
notifications from ionic-native. If we scroll down we can see the scheduleNotification
method on line 18 and it's just a simple method called LocalNotifications.schedule. And
there are various properties we can give this, an id, we can give it a title, there was Cool
Notification, a text, This is my cool notification. The data property you can send in any
arbitrary object and we saw Cool Notification #21, sure enough, there's that id = 21, and
then the name - Cool Notification 21. The other thing you may have seen is that when we
first came into the screen, in the constructor we subscribed to a local notifications click
method, such that when the notification is tapped from that area that I swiped from the
top down on my Android device, we can get that notification data and then display the
results in the screen, so you saw that alert and then the results were displayed on the actual
screen itself. So local notifications provide a way to enable your users to get notifications
without the need of server-side data as you would typically see in push notifications.

Integrate SQLite into Your App

Now that we've seen some pretty straightforward demos of ionic-native plugins, let's
revert back to working on our elite schedule app, specifically I want to integrate the ionic-
native SQLite plugin into our app. If you remember, we're storing the list of favorite
teams in local storage and local storage isn't always reliable persistence on certain
operating systems since you can't always predict when the OS will clear the data. Let's
add the SQLite native plugin to our app to get reliable storage. The first thing I need to
do is run the ionic plugin add command that we see here. So I'll just come back to my
console, paste that in here from the webpage, and hit Enter. Now the plugin has been
installed. Let's come over here to the user-settings.service and we're going to add
SqlStorage to the list of imports from Ionic Angular. I don't need to explicitly put SQLite
here because since I added the SQL storage, that uses SQLite behind the scenes, so the
app won't work unless I've made sure to remember to add the plugin to my app, which
I've just done. Now that we've added SqlStorage I'm going to change line 7 so it uses
SqlStorage instead of localStorage. Now I want to run the app, but one thing just to
remember is the storage that we're assigning here on line 7, it's used to favorite a team,
right here, unfavorite a team on line 18, and also check whether it's a favorite team on
line 23. However, if we look down here at the getAllFavorites methods, that's still using
local storage so we haven't switched that yet. Let's go have a look at our app. And here
we are back in our app, and what's happening here is even though nothing is yet stored in
SQLite, we're still seeing two screens showing up on the My Teams screen because these
two are still being stored in local storage. So if we click one, this screen is reading from
SQLite, there's nothing in there, and that's why it's not being recognized as being a
favorite yet. Let's add this one as a favorite now, that was the HC Elite 7th. If we look
over here on the dev tools, we're going to flip over to the Application tab and find Web
SQL and you can see here we have ionicstorage and then a table called kv for key value.
And you can see we've got one row in that table. That's for the favorite we just added. If
we unfavorite, yes, and come out, refresh, it's gone, it's empty. If we add them back in,
go out and refresh, it's there. Now one thing to note is this is another thing the Ionic Native
plugin is doing for you, this is using Web SQL, which is not actually SQLite. Ionic is just
helping us out by recognizing that we're still in the browser so it's giving us a Web SQL
database to use in lieu of SQLite since we're in the browser. We actually have to get to
our real native device to use SQLite, but this helps us get our initial tests going in the
browser first. This kv table is for key value, as you heard me mention, this table is the
default for simple key value storage, but of course you can create other tables as well with
your desired schema. Let's go back to the home screen, let's go back to this other team,
let's make sure they're added as a favorite too, so now both these teams are added as
favorites. So we have this working for individual teams, unfavoriting and favoriting
individual teams, now let's go fix the query on the My Teams page so that it retrieves all
the favorites from our SQL storage instead of from local storage. So I'm going to come
into this getAllFavorites method and I'm going to comment this all out for now and under
it we're just going to say this.storage.query(*SELECT * FROM kv*). Then we have a
then, this is for our promise, and for now I'm just going to say console.log of data. And
I've got to make sure I have a return statement here. Now obviously we're not returning
proper data yet, we still need to come back and fix something here, but I want to show
this console.log statement first. Before we can run it though, we need to go to the My
Teams page and we need to fix this, so instead of assigning directly to it, now it's part of
a promise. So we need to say then(favs = this.favorites = favs). Now since this is giving
us an error here, let's just, even though all I said I wanted to do was a console, let's go
back here and we'll just return an empty array for now (Typing), and the error has gone
away. And the last change we need to make to make sure it runs correctly, same thing
here now that this is not a direct assignment, it's not part of a promise (Typing). Now
again, we have not yet put proper implementation in this userSettings method yet, I just
want to run the app briefly so we can see this console.log data. Okay so live reload
happened and it wrote to the console and you can see that we have this result right here
and it has a rowsAffected property and a rows property, and here are the rows, it has a
length equal to 2, and then this is not actually an array, these are individual objects and
each object has a key and a value and the value is as string that's represented as a JSON
string. So again, using SQLite we could have a table that has legitimate schema, but in
this case it's just using the default key value table. So now that we have a picture of what
the data structure looks like, we can go implement the code. And what we need to do here
is we'll have a for loop, just a traditional for loop, and we need to say i is less than
data.res.rows.length; i++, and that results array, we'll just push individual items on that
array, we need to say JSON.parse though, and that's data.res.rows.item, and we need to
actually get to the value by sending the indexer into that item method. Now let's run it
again. And we can see the screen has reloaded and we can see the teams right here on the
screen. Now that we have it working in the browser, let's run it on an actual device. Here
I am back on the device and we can see that I have no followed teams, it's now using
SQLite, so let's go add some favorite teams. I'm going to say find a tournament, March
Madness tournament. Let's use our little search feature here, 7th grade, HC Elite, we'll
add it as a favorite. We can tap the Home button, and we see we go back to the Home
button and we can see it's stored there now. We can come back, unfavorite, back to the
home screen, it's gone. So we can see that we're now using the SQLite plugin on the actual
device, this is going to have reliable local storage, we don't have to worry about the
operating system clearing it out, and this will have very robust persistence for our app.
These are exactly the types of examples you should look for for when it is appropriate to
use native plugins in your app.

Summary

That concludes this module on Ionic Native. In this module we saw numerous examples
of using plugins that enabled us to access native device features. We started out by
understanding that Ionic Native is a developer friendly wrapper around cordova plugins
that give us access to native device features. This is a curated list of plugins wrapped in
a modern API, which uses promises and observables instead of traditional callbacks. I
then showed how you can go to the Ionic Native website to find new plugins and add
them to your app by running the ionic plugin add command using the Ionic cli. The
Vibration plugin was the first plugin we added and you saw that on Android we could
control duration and pattern. We saw how the geolocation plugin can give us precise
longitude and latitude coordinates of our device on demand. I then showed how we could
use the device camera in our app to display the picture we took on our screen. The barcode
scanner is flexible enough to recognize several different barcode formats, you saw me
scan the box of Cheerios and look it up on the UPC index site. The device motion plugin
allows us to access the accelerometer feature of the device, which shows change of
acceleration in all three axes at a given snapshot in time. It also lets us control how
frequently we sample that data, whether it's 500 milliseconds, every 10 seconds, or any
other duration. I then showed how you can use local notifications to provide alerts to our
users for upcoming events. These notifications appear in the notification area of our
device. Finally, we reverted back to the elite schedule app and I switched out the local
storage of our favorite teams in favor of using the native SQLite plugin so we could get
more reliable storage. Our app is almost complete. In the next module we're going to put
some finishing touches on it, including custom icons and a nice splash screen.

Customizing Ionic 2
Overview

In this module we're going to look at some of the ways we can customize Ionic 2. At this
point our app is fully functional, but we want to put some nice finishing touches on it
before putting it in the app store. So far we've been using all the default colors that come
with Ionic. We're going to start out by customizing a couple of the core theme colors.
We'll then look at customizing some metadata in the config.xml, so items like the app
title will look correct when we deploy to a device. I'll show you how we can generate
icons for your app so that we don't have the default icon when it's deployed to a device.
Similarly, I'll show how to generate splash screens.

Custom Colors in app.core.scss

As we've seen through the course, we've been using the primary class, which is this blue
color we see here, and the secondary class, which is this green color we see here. These
look fine and are nice because we have a consistent color scheme through our app.
However, let's say we want to change these colors, perhaps to be more in line with our
company's branding. It turns out this is quite easy to do. In the theme folder we've
previously opened the app.core file to make changes. But this time I want to open the
app.variables file right here and we can see that we have some placeholders in here and
these are where the primary and secondary colors are set by default. So let's just change
these items, so that's a new color for primary, that's going to be a dark green color. Let's
have a look at what that looks like. So now I have a dark green color in the top bar instead
of the blue, which is fine except that it doesn't look against the light green color below it,
so let's change that to an orange. For secondary we're going to change this code and now
that's going to be an orange color. Let's go look at our resulting screen. Now we can see
the secondary has been changed. So we have a dark green for the primary, an orange for
the secondary, and these changes have been made throughout. And we can go to the other
screens so see that those changes are consistent throughout our entire app. So in just a
couple of brief changes to our Sass, we've made global changes to our colors, and it's
enabled us to customize in accordance with our desired branding.

App Metadata: config.xml

I've already deployed to my device several times earlier in this course, however, I never
stopped to show you the icon screen. You can see that our app has been added to this
screen with a default icon and the title doesn't even look right, it's all lowercase with
words separated by hyphens, in fact, you can't even see the entire title because it's cut off.
Clearly we need to fix this. The config.xml file is the primary file where we're going to
store our metadata for our app. If we open it up here we can see many elements that we
can change and customize appropriately. In fact right here we see the name element and
this is where the title that was being displayed on the icon screen was being sourced from.
So let's change this to Elite Schedule with proper casing. Then with our description, this
is just a default thing that says An Ionic Framework and Cordova project. Let's change
this to say The Elite Schedule awesome app. And then we see this default email account
down here, so we can change this, just put a default email account. We can put in a URL
instead of the Ionic framework, as the author we'll say Steve Michelotti. Now I've just
customized three options, the name, description, and the author, but there's other options
we can customize here. You can consult the documentation, we don't need to go through
every option, but what you're going to see is that even just by changing the name, this
will fix the issue of the inappropriate title being displayed on the icon screen. So now I'm
going to run the ionic run Android command again to redeploy to the device. Here we are
back on my device and you can see that now the title has been fixed and it says Elite
Schedule, which is exactly what we want. However, now we still have to fix the issue of
the icon needing to be customized and we also want to put a custom splash screen in there,
we'll fix those next in the following demos.

Generate App Icons

As we just saw in the previous demo, we've now fixed the title that appears on the icon
screen for our app, but now we need to customize the app icon so it's not showing this
generic icon. We need something more in line with our app. Let's fix that next. The default
icons can be found right here in the resources directory, and you can see right here we
already have an icon.png and a splash.png. In fact, we have platform specific directories
for Android and iOS and we can see the icons for each of those respective platforms.
What I'm going to do, let's close these, is I'm going to go into this folder and I'm going to
copy and paste two new icon files in, yes replace these, and you can see that I have
basketball icons now for the icon and the splash screen. With those image files in place,
we can now use the Ionic cli to generate some app icons. Now all I did right there is I just
ran the iconic command with no command line arguments because I wanted to show the
help page, and in particular what I wanted to point out is that we have this resources
switch right here, and this shows you that you can automatically use this to create icons
and splash screens. So let's first do the resources, iconic resources and we'll say --icon.
And you can see right here that it's generated the icons for Android because that's the
platform that we've added so far. If we had added iOS it would generate those as well. So
now we're going to run an Ionic run Android to deploy to my device again to see what it
looks like now. Here I am back on my device and you can see that we now have a nice
looking icon above our Elite Schedule title and now we're looking a lot more professional
in terms of the appearance of our app. So we've got our title correct, we've got our icon
correct, now let's just go add the correct splash screen.

Generate App Splash Screen

Just a few moments ago you saw me add new icons for icon.png and splash.png, and I
generated icons which went into this Android icon directory. Now let's do the same thing
to put new files in the splash directory. So very similar to the previous command we're
just going to run Ionic resources and --splash. And you can see it's generated these files
here, which have gone into the Android splash directory here. Now let's go have a look
at the splash screen on the device. Here I am back on my device and we're going to tap
the Elite Schedule icon and we can see the splash screen came up. And we're in our app.
So now we have added a nice title, nice icons, and a nice splash screen and now we have
a lot of polish to our app, it's looking very professional, and these are the things you want
to make sure you do before trying to deploy it to the app store.

Summary

That concludes this module on customizing Ionic apps. I started out by showing how you
can change the default colors in the app so that your global theme matches your desired
branding. The config.xml file is where important app metadata is stored. We customize
this so that the title appears as desired on the icon screen when deployed to the device.
Ionic makes it very easy to generic icons for your desired platform and you saw me
generate icons for my Android device. And Ionic makes it just as easy to generate splash
screens. That concludes this course on building mobile apps with Ionic 2. I hope you've
enjoyed the course and thanks for watching. We've seen how truly feature rich Ionic 2 is,
enabling us to build robust apps with modern technologies like Angular 2 and TypeScript,
technologies where we can reuse our skills as web developers. Now it's time for you to
go out and go build great apps.

Вам также может понравиться