Ionic

Ionic Split Panel Component

Recently the Ionic team released a preview of the split panel component. In this blog post, I want to take a look at it in a bit more depth. For those not familiar with this visual design pattern, it is very similar to the side menu layout. The main difference is that menu usually remains onscreen. Gmail is a great example of this layout. As Ionic begins to expand from the mobile space into progressive web apps and even the desktop, this layout is a common pattern.
Since this component is similar to the side menu layout, let’s scaffold our app using that template.
$ ionic start splitPanelDemo sidemenu --v2
Once the project is ready, go ahead and change the working directory to splitPanelDemo. Since the component is still under development, we need to swap out the release version of Ionic for the nightly build.
$ npm install --save ionic-angular@2.0.1-201702161925
With our copy of Ionic replaced, go ahead and open app.html. There are just a few things we need to do to convert our side menu template to use the split panel layout.
< ion-split-panel >
  < ion-menu [content]="content" when="xs" >
    < ion-header >
      < ion-toolbar >
        < ion-title >Menu< /ion-title >
      < /ion-toolbar >
    < /ion-header >

    < ion-content >
      < ion-list >
        < button menuClose ion-item *ngFor="let p of pages"             (click)="openPage(p)" >
        {{p.title}}
      < /button >
      < /ion-list >
    < /ion-content >

  < /ion-menu >

  < ion-nav main [root]="rootPage" #content swipeBackEnabled="false" >< /ion-nav >
< /ion-split-panel >
We need to tell the component when the ‘menu’ should be displayed. The typical UX flow is to have the split pane hide when the screen or viewport become reduced. The component has the following breakpoints defined:
label min-width
xs 0px
sm 576px
md 768px
lg 992px
xl 1200px
never
By passing one of these strings to our when attribute we can control when our menu is shown. Another item to note, the min-width our split panel is 270px and it set to be no larger than 28% of the viewport. All these values are defined within the components SASS files.
< ion-menu [content]="content" when="xs" >
The last adjustment we need to denote the ‘main‘ content for the split pane. For this, just include the main directive to
< ion-nav main [root]="rootPage" #content swipeBackEnabled="false" >
 Running $ ionic serve, will produce this:
screencapture-localhost-8100-1487963384735

The sidemenu template being rendered as a split panel layout.

If you include menuToggle on the header of the main pages, the split panel will understand that directive and use it when the split panel is hidden.
Now, this initial sample is not much more than sidemenu with the expose-aside-when value that was available in v1. Let’s explore a more complex sample.
In this sample, we will enable the split panel to have its own navigation stack that it independent of the main content’s navigation stack. This was a design pattern that I was never able to build using Ionic v1. I had several app ideas that would have been a perfect match for it (yes, I am starting to flesh those apps out now).
First, let’s generate a collection of new pages using the Ionic generate command:
$ ionic g page Main
$ ionic g page SideNav
$ ionic g page SideNav2
$ ionic g page View1
 Next, make sure you update app.module.ts to import these new views. In addition, take note of setting both the root and sideRoot variables, as well as setting myApp within the @NgModule.
import { NgModule, ErrorHandler, Component } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MainPage } from '../pages/main/main';
import { SideNavPage } from '../pages/side-nav/side-nav';
import { SideNav2Page } from '../pages/side-nav2/side-nav2';
import { View1Page } from '../pages/view1/view1';

@Component({
 templateUrl: 'app.html'
})
export class myApp {
 root = MainPage;
 sideRoot = SideNavPage;
}

@NgModule({
 declarations: [
 myApp,
 MainPage,
 SideNavPage,
 SideNav2Page,
 View1Page
 ],
 imports: [
 IonicModule.forRoot(myApp)
 ],
 bootstrap: [IonicApp],
 entryComponents: [
 myApp,
 MainPage,
 SideNavPage,
 SideNav2Page,
 View1Page
 ],
 providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}
Next, let’s adjust the app.html file for our new structure. Instead of directly defining the content of the split panel, we are now just including an element and setting its root property to sideRoot. We will use this reference to populate the content.
< ion-split-panel when="sm" >

  < ion-menu [content]="content" >
    < ion-nav [root]="sideRoot" >< /ion-nav >
  < /ion-menu >

  < ion-nav [root]="root" main #content >< /ion-nav >

< /ion-split-panel >

Since both of these containers had their own navigation stack, we can move through our application independently. Let’s give our various pages some content first so we can see all this in action.

Change side-nav.html to:

< ion-header >

< ion-navbar >
< ion-title >Components< /ion-title >
< /ion-navbar >

< /ion-header >


< ion-content >
< ion-list >
< button menuClose ion-item *ngFor="let p of pages" (click)="displaySubNav(p)" >
{{p.title}}
< /button >
< /ion-list >
< /ion-content >

and side-nav.ts to

import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { SideNav2Page } from '../side-nav2/side-nav2';

@Component({
 selector: 'page-side-nav',
 templateUrl: 'side-nav.html'
})

export class SideNavPage {
 pages: Array<{ title: string, component: any }>;

 constructor(public navCtrl: NavController, public navParams: NavParams) {
 this.pages = [
{ title: 'Action Sheets', component: SideNav2Page },
{ title: 'Alerts', component: SideNav2Page },
{ title: 'Badges', component: SideNav2Page },
{ title: 'Buttons', component: SideNav2Page },
{ title: 'Cards', component: SideNav2Page },
{ title: 'Checkbox', component: SideNav2Page },
{ title: 'DateTime', component: SideNav2Page },
{ title: 'FABs', component: SideNav2Page },
{ title: 'Gestures', component: SideNav2Page },
{ title: 'Grid', component: SideNav2Page },
{ title: 'Icons', component: SideNav2Page },
{ title: 'Inputs', component: SideNav2Page },
{ title: 'Lists', component: SideNav2Page },
{ title: 'Loading', component: SideNav2Page },
{ title: 'Menus', component: SideNav2Page },
{ title: 'Modals', component: SideNav2Page },
{ title: 'Navigation', component: SideNav2Page },
{ title: 'Popover', component: SideNav2Page },
{ title: 'Radio', component: SideNav2Page },
{ title: 'Range', component: SideNav2Page },
{ title: 'Searchbar', component: SideNav2Page },
{ title: 'Segment', component: SideNav2Page },
{ title: 'Select', component: SideNav2Page },
{ title: 'Slides', component: SideNav2Page },
{ title: 'Tabs', component: SideNav2Page },
{ title: 'Toast', component: SideNav2Page },
{ title: 'Toggle', component: SideNav2Page },
{ title: 'Toolbar', component: SideNav2Page }
];

}

 displaySubNav(thePage:any) {
  this.navCtrl.push(thePage.component);
 }
}

Next, let’s change the side-nav2.html file to be this:

< ion-header >

 < ion-navbar >
  < ion-title >Details< /ion-title >
 < /ion-navbar >

< /ion-header >

< ion-content >
 < p >New content< /p >
< /ion-content >

We don’t need to change the side-nav2.ts for this simple demo. Let’s change our main.html file this:

< ion-header >

 < ion-navbar >
  < ion-title >Main< /ion-title >
 < /ion-navbar >

< /ion-header >

< ion-content padding >
 < button ion-button primary (click)="goNewView()" >Go View 1< /button >
< /ion-content >

and the main.ts to:

import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { View1Page } from '../view1/view1';

@Component({
 selector: 'page-main',
 templateUrl: 'main.html'
})
export class MainPage {

constructor(public navCtrl: NavController, public navParams: NavParams) { }

ionViewDidLoad() {
 console.log('ionViewDidLoad MainPage');
 }

goNewView() {
 this.navCtrl.push(View1Page);
 }
}

Save the files, and try it out.

split-panel-demo

Independent Ionic navigation in the split panel layout.

The source code for this demo is available at my GitHub Repo.

Better Ionic Theming

Recently I was working on a client application and was starting on the theming portion of the effort. Naturally, the client wanted some corporate branding applied to the app. Mostly simple things like changing out the header color to match the current corporate color, etc. However, this app was actually not going to be deployed as a native mobile app, but rather as a standard web app (technically a Progressive Web App). As such, I was paying more attention to files sizes of the build.

I knew I was not going to get into the bowels of the app build process, but I was curious about what I could optimize. The generated CSS file caught my eye as something that might be adjusted. As you know, Ionic ships with 5 theme colors:  primary, secondary, danger, light, and dark. I initially add a corpBrand variable within the $colors map. If you read the Theming your Ionic App page on the Ionic site, this is exactly what they demonstrate.

$colors: (
 primary: #387ef5,
 secondary: #32db64,
 danger: #f53d3d,
 light: #f4f4f4,
 dark: #222,
 corpBrand: #663399
);

So, I added in the reference to the corporate color and then built the app using both ionic serve and ionic build –prod to see what the sizes would be.

Build Method main.css Size
ionic serve 478kb
ionic build –prod 408kb

That’s a little large. I wondered what the base size of the CSS file was? Here is what the default main.css measures:

Build Method main.css Size
ionic serve 421kb
ionic build –prod 357kb

So, just add one additional variable to $color, increased the CSS file by 57kb. I was shocked for a moment. But then thought about what was happening in the build process. The build scripts were taking each entry in our $colors array, and applying it to each and every component in the framework. It did not matter it the new color was ever used on that component or not.

I decided to explore this a bit further by removing the corpBrand variable and also removing the reference to secondary color was well. I knew I did not directly use this in the app, so I thought it might be semi-safe to try it. I rebuilt the app using both ionic serve and ionic build –prod.

Build Method main.css Size
ionic serve 371kb
ionic build –prod 312kb

The savings were 50kb. This confirmed that each color variable costs about 50kb in file size. I am not sure that I totally trust deleting one or more of the Ionic default colors to save file size. Maybe in a future build script, some CSS tree-shaking might occur. With the rebirth of web apps, our file sizes will become increasingly important (hint, hint).

One solution…

So, how could I apply the corporate branding to the select components and still manage my CSS file size? Clearly, just adding it to the $color array was a bit expensive.

If you are not aware, one of the improvements in Ionic 2 was the addition of a ton of additional SASS variables. For example, the header needed to be in the corporate brand color. Since the header is built atop the Toolbar component, I hopped over to the Overriding Ionic SASS Variables page to see what might be easily altered. There I found $toolbar-ios-background, $toolbar-md-background, and $toolbar-wp-background.

Opening the theme/variables.scss file, I adjusted to include this:

// Shared Variables
// --------------------------------------------------
// To customize the look and feel of this app, you can override
// the Sass variables found in Ionic's source scss files.
// To view all the possible Ionic variables, see:
// http://ionicframework.com/docs/v2/theming/overriding-ionic-variables/

$corpBrand: #663399;

// App iOS Variables
// --------------------------------------------------
// iOS only Sass variables can go here

$toolbar-ios-background: $corpBrand;
// App Material Design Variables
// --------------------------------------------------
// Material Design only Sass variables can go here
$toolbar-md-background: $corpBrand;

// App Windows Variables
// --------------------------------------------------
// Windows only Sass variables can go here


$toolbar-wp-background: $corpBrand;

Saving these changes and running the tests again, I got these results:

Build Method Size
ionic serve 421kb
ionic build –prod 357kb

Basically, the same as the defaults (a few bytes larger in each case).

To sum all this up, when applying a custom theme to your Ionic application, I strong urge you to target the styling in a focused manner, rather than creating a new global color theme.

Developing Awesome Mobile Applications With the Ionic Framework

unnamed-1

If you happen to be attending ngConf this year, or live in the Salt Lake City area, I am giving an all-day workshop on Ionic on Tuesday, April 4th from 9:00 am – 4:00 pm.

In this workshop, you will be introduced to the Ionic v2 framework, a powerful hybrid mobile solution. Built atop of Angular 2 and Apache Cordova, this framework gives developers an incredibly powerful set of mobile components to create app store-ready apps.

You do not need to have a ticket to ngConf (which is sold out, again) to attend. Details on the workshop can be found here.

Hiking Guide: Joshua Tree released!

We have released our second paid app, Hiking Guide: Joshua Tree! It is available for both iOS and Android for $0.99. The app contains over 20 hikes in the Joshua Tree National Park. You can find a wide range of hikes; from easy to hard, from short to long, the perfect hike is a few taps away.

The app contains USGS topographic maps that outline each trail’s route, as well as providing descriptions of the trail and directions to the trail head.

We hope you enjoy the app and use it explore the many hikes in Joshua Tree National Park.

 

Hybrid Mobile Apps with Ionic 2

rc_cat
I am excited to announce the early access release of my new book, Hybrid Mobile Apps with Ionic 2! For anyone looking to learn about this powerful mobile framework, this book aims to get you up and running. Here is overview:

The book itself provides a solid overview of hybrid mobile development before diving in and walking you through building 3 different applications. In it, I also cover Angular 2, TypeScript and Apache Cordova.

The core of the book focuses on building three applications, each that showcase different aspects of the Ionic Framework; the Ionic CLI, their starter templates, its component library and more.

Now, this is an early release version of the book, meaning there might be an error or two. Plus, Ionic 2 is not quite done yet, so something might break. I will keep a careful eye on its progress and flag anything that might arise. In the meantime, I will be pushing forward on the rest of the book as its technical dependencies allow.

You can pick up your digital copy from O’Reilly’s website now! I hope you enjoy reading it.

Ionic 2 Full Swipe

Note: I will be updating this to RC0 shortly. I do know there is a minor issue with the button’s width not responding to the expanded space.

While working on my upcoming book on the Ionic framework from O’Reilly, I was reading over the blog post about some new additions to the <ion-item-sliding> component supporting a full swipe gesture. I hopped over to the docs to see if they explained how to enable it. Unfortunately, they did not have anything posted yet, so I began to deconstruct it from the code sample. Here is the sample:

<ion-item-sliding>
  <ion-item> Item 1 </ion-item>
  <ion-item-options side="left">
    <button>Mail</button>
  </ion-item-options>
  <ion-item-options side="right" (ionSwipe)="saveItem(item)">
    <button danger>
      Trash
    </button>  
    <button secondary expandable (click)="saveItem(item)">  
       Save
    </button>  
  </ion-item-options> 
</ion-item-sliding>

To support this interaction, two things must be added to our<ion-item-sliding>. First, we need to add the expandable directive to the button.

<button secondary expandable (click)=”saveItem(item)”>

This allows for the visual feedback of the button growing as the user swipes across the item.

swipe_demo

Typically this is attached to the item that is closest to the end of the row. To listen for the swipe gesture, we only need to include an ionSwipe event listener to the <ion-item-options> component. This listener should call the same function as if the user tapped on the item. Here is a simple Plunker showcasing it.

A quick look at Ionic Creator

creator-preview

Recently I had the chance to talk with Matt Kremer, the project lead behind the Ionic Creator web app. For those not familiar with this app, it is an online design tool for creating Ionic frameworks apps. Drifty (the company behind Ionic) has a long history of developing tools like this; Codiqa (for jQuery Mobile) and JetStrap (for Bootstrap), so seeing a visual design tool for Ionic was to be expected.

I had explored an earlier version of the tool, and it had a number of rough edges. Recently, Matt has made a number of improvements to it, and spent an hour showing me the new features.

Right off the bat, Creator now supports multiple projects via a nice clean landing page. If you had used the app before, you might remember how clunky it was. Where this comes into play, is you can now have team accounts, thus allowing your designers, developers, and other team members the ability to reference the project. The team feature is a paid option for the service.

Next up is the expansion of starter templates. For those who use the Ionic CLI, you are probably familiar with the three templates available; Blank, Side Menu, and Tabs. Creator has a slightly different set of templates; Blank, Login, Signup and Tabs. Now, the Login and Signup templates are very similar. One noticeable difference is the lack of a SideMenu template. Matt explained some of the difficulties in integrating this template into the app. He is hopeful as the app migrates to leverage the v2 framework, those issues will be resolved.

 

CreatorUI

In the past, I had tried to mockup a simple tab based UI and had a lot of trouble. I can say in this latest build of the tool, I was able to mockup my UI with little or no trouble. One area in particular was being able to properly set the tab’s icon.

Another improvement is the app is now smarter about components themselves. Previously, when you tried to add a checkbox and did not have a containing form element, the app would not allow it. Not only that, there was no feedback as to why you could not drag and drop the component onto the canvas. The underlying answer was there was no containing form element for the checkbox. So, Creator will now automatically add a containing form element if one is not already there. No longer do you have the appearance of the tool being broken.

Through the app, I was also impressed with the performance gains that had been made. The earlier version was quite sluggish. While there is still more to be done (isn’t that always the case?), the app has reached an acceptable level of performance for my usage.

Now, once we are done with the design, what can we do with it? Creator allows the project to be shared via URL, email or SMS, and can also require a passcode to view it. But beyond that we can reference it as a template source directly from the Ionic CLI. Simply click the export button and select the Ionic CLI option, and a unique code will be generated. Or if you prefer, you can download it as a .zip file.

As with all visual editors, there comes the question of what does the code look like? Again, I am pleased to say that Matt has done a nice job at providing a decent starting point to begin build your awesome Ionic app.

I am looking forward to the continued development of the this tool, as it is great way for my students to mock up their apps quickly. Plus, there is some more cool stuff coming that I can’t reveal yet, so stay tuned.