I was inspired to write this blog from a recent post about which JS framework should be used for application development nowadays and it got me realizing that I should have written this a while ago. As you may know, RhoMobile has its roots in Ruby and what you get out the RhoMobile box is centered around Ruby views and controllers. You probably have tried our application generator in RhoStudio and you might have noticed that it starts you off thinking that you have to use JQuery Mobile in your application stack. Not only is it wrong to assume that, quite frankly it is wrong that we even suggest JQuery Mobile as the recommended framework. With its last release date of Oct 2014 and other signs of decline, one has to question the current state of JQM in modern hybrid application development. At the same time Ionic Framework has skyrocketed in adoption, growth and overall awesomeness. Even though Ionic is built on top of another hybrid app framework (Cordova), you can still reap the core benefits in your RhoMobile application and easily deliver a performant hybrid application.

 

Isn't the Hybrid vs Native Debate Over Already?

Before we get into the key features of Ionic and how to use it within RhoMobile, let's quickly summarize some of the key pieces that make up a great hybrid app design:

For those who want to jump right into it, clone this repo and you will have 3 starter Rho-onic apps as well as a demo app that I allude to in this article

  • Single Page App Pattern - if you are still treating your application as individual HTML pages, you are doing it all wrong. SPA is arguably the only way to get the most performance of your hybrid application. I strongly urge you to research this concept and understand the premise behind it, especially from a mobile device point of view.
  • Routing - in order to accomplish SPA, you need to have an easy way to break up your application into routes/states so your code can be maintainable and portable.
  • Templating - right along side routing, you need an easy way to build your UI and separate it into views or individual UI components
  • Mobile First Only - This is probably the most important piece. We all want our app to be as fast as possible and for our users not to notice or even care if it was not developed natively. To get that you want a framework that only cares about running on a mobile device and is designed with that in mind. Other frameworks that are trying to be website and mobile at the same time will never be able to give you 100% of what you need. Your app may fit on the screen automatically, but may not perform as well as it can.

Why I Can't Stop Using Ionic

As touched on above, Ionic is built on top of Cordova but is also includes Angular.JS. Cordova gives you the device APIs, but since we are building a RhoMobile application we will be throwing that part away from our stack. Angular is the foundation of the SPA design and gives Ionic the ability to build on top of that offering you not only great UI components, but also some built in directives and services that you can use in your application with ease. If you are not familiar with these terms, for now just think of them as self-contained intelligent components that you can instantly drop into your application. I don't know about you, but I do not like re-inventing the wheel every time I start a new application. As an added bonus, since the Ionic team is 'Mobile Only', they are already handling some of the things us hybrid-developers struggle with. Like how many times have you tried to figure out how to make a super long list of items scroll and perform as if it was native. Ionic has you covered, as we will explain and show some examples of this further along in this article.

Common UI Components

I am not going to spend a lot of time on this topic, any UI framework worth its weight will give you the common UI components that we need in our application like buttons, forms elements, icons, etc. You can head over to Ionic's site and see them in their glory. As with everything else, Ionic has designed these with mobile performance and usability in mind. They even give you great ways to customize the theme and look so that your app does not look like all other Ionic apps. Many of these components also automatically behave differently on Android and iOS to give you the best native like experience possible.

Screen Shot 2015-07-29 at 12.33.08 PM.jpg

Drop in Greatness

One of the best features in Angular that Ionic takes advantage of is the use of Angular Directives. Angular's docs do not really convey how great these are, but think of them as 'smart html markup'. In short, directives tie some self-contained javascript with html tags and attributes to give your application certain behavior without having to write much code at all. To demonstrate this, let's take a very complicated problem and make it dead-simple: large lists. There is so much work involved in making large lists to perform well in a hybrid-app like keeping the dom small enough without losing the scroll speed, or remembering position when navigating back to the list on page change to name a few. Well, Ionic has included a directive that does all of this for you - all in a few lines of code:

<ion-list>
  <ion-item collection-repeat="user in users" class="item item-avatar">
      <img src="{{user.user.picture.thumbnail}}">
      <h2>{{user.user.name.first | uppercase}} {{user.user.name.last | uppercase}}</h2>
      <p>{{user.user.location.city | capitalize}},{{user.user.location.state | capitalize}}</p>
  </ion-item>
</ion-list>

You will notice the <ion- tags and collection-repeat. This keeps my view nice and clean (not to mention super easy application prototyping) and leaves the complexity to the directive that has already been implemented for me. In my demo app that is included in the Rho-onic Git Repo I am pulling a list of 1000 users and using this directive to give you butter smooth scrolling. I dare you to try and reproduce this performance using your own homegrown techniques.

Screen Shot 2015-07-29 at 12.16.03 PM.jpg

Service With a Smile

Angular provides a foundation not only for smart markup, but it also provides the ability to package up intelligence that you may need to use within your controller logic in the form of services. Services are packaged up and named, so that you simply drop in the service into the controller that you need to use it in. Ionic includes several of these services. For example, say you want to provide an set of options when an item is selected in your application, you can drop in $ionicActionSheet and use it in your controller:

.controller(function($scope, $ionicActionSheet, $timeout) {

 // Triggered on a button click, or some other target
 $scope.show = function() {

   // Show the action sheet
   var hideSheet = $ionicActionSheet.show({
     buttons: [
       { text: '<b>Share</b> This' },
       { text: 'Move' }
     ],
     destructiveText: 'Delete',
     titleText: 'Modify your album',
     cancelText: 'Cancel',
     cancel: function() {
          // add cancel code..
        },
     buttonClicked: function(index) {
       return true;
     }
   });

   // For example's sake, hide the sheet after two seconds
   $timeout(function() {
     hideSheet();
   }, 2000);

 };
});

Screen Shot 2015-07-29 at 9.30.15 AM.jpg

But Wait - There's More

I have only covered a few goodies that come out of the box with Ionic, there are plenty of good reads and reviews for you to Google. The community has exploded in the past year at adopting to Ionic and you can find other open source directives and services that the community has developed that you can use in your RhoApplication. Keep in mind that if any of them require a Cordova plugin, then those will most likely not be fully usable with RhoMobile. Others that simply provide some ui/js goodness should be able to be used without many issues. Here is a nice roundup of must have directives you should consider which BTW was written by an ex-JQuery Mobile ambassador who now professes a lot about Ionic.

One of my favorites is the ionic-datePicker. After adding the corresponding JS and CSS files for this directive, I can easily add a datePicker to app and bind to a data model without writing a single line of JavaScript:

<ionic-datepicker idate="currentDate" disablepreviousdates="true"  disablefuturedates="false" callback="datePickerCallback" disableddates="disabledDates" title="title" mondayfirst="true">
    <button class="button button-block button-positive"> {{ currentDate | date:'dd - MMMM - yyyy' }} </button>
</ionic-datepicker>

You can see this directive includes some options exposed via HTML attributes. The iDate attribute allows me to bind the value of the the chosen date in the datepicker to the local model I am using currentDate which gets displayed on an Ionic button

Screen Shot 2015-07-29 at 12.16.23 PM.jpg

Bionic RhoMobile Apps with Ionic

Ok, so now that you have a thirst for using Ionic inside your RhoMobile application, lets walk through the steps you need to take. This same concept really applies to other frameworks as well. And again for those who want to jump right to it, I have created a Git repo that contains multiple Rho-Ionic starter template apps based on Ionics starter projects. It also contains a demo app that demonstrates the features I mentioned in this article as well as a demonstration of using RhoMobile api's within the framework.

Be sure to install Ionic (npm install -g cordova ionic) and RhoMobile Suite before attempting these instructions

1. Create a new project with RhoMobile

Screen Shot 2015-07-29 at 12.18.39 PM.jpg

2. Create an Ionic project

Open a command prompt and go to the root of the project you just created. Then use ionic CLI to generate a new project. For this example, I chose to create a sidemenu based application called ionic. This will create a subfolder in my RhoMobile application called ionic so I can keep the two separate

Screen Shot 2015-07-29 at 12.20.15 PM.jpg

3. Replace RhoMobile public Folder

The Public folder acts as your 'web root'. If you look at the Ionic folder structure you will see a www folder that is basically the same concept. This is the folder we want to use in our RhoMobile application. Replace the entire contents of public with the contents of ionic\www

Screen Shot 2015-07-29 at 12.26.09 PM.jpg

4. Change RhoMobile Start Path

Open up the rhoconfig.txt file and look for start_path. By default it is setup to use Ruby views and controllers, which we will not be using in this example. Change it to point to the new start page:

start_path = '/public/index.html'

5. Modify Index.html

Remember that Ionic is built on top of Cordova, so it is including the cordova.js file by default. We want to remove this and replace it with the RhoMobile JavaScript api file. This file will be generated when you build your application (because it depends what extensions you include) and will be found in api/rhoapi-modules.js. Yourpublic\index.html` file should look like:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title></title>

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">

    <!-- ionic/angularjs js -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>

    <script src="api/rhoapi-modules.js"></script>

    <!-- your app's js -->
    <script src="js/app.js"></script>
    <script src="js/controllers.js"></script>
  </head>

  <body ng-app="starter">
    <ion-nav-view></ion-nav-view>
  </body>
</html>

6. Tweak Default Wrapper Behavior

There are a few things that drive me crazy about our default app generation, but especially on Android we add a Title Bar and Toolbar to the application that just wastes a lot of real estate and does not fit into the design of application I usually am going for.

First I will remove the toolbar, by opening app\application.rb and uncommenting the default Toolbar line:

@@toolbar = nil

Then I will remove the 'Title Bar' that gets inserted by default on top of the Webview container. I do this by opening build.yml and adding a line under the android section:

android:
  android_title: 0

7. Ready To Run on Device

Ok you are all set to run the app on a device. Go ahead and setup a Run Configuration for Android and check out your masterpiece.

Screen Shot 2015-07-29 at 2.31.09 PM.jpg

 

For actual development, you will probably want to do a lot of your UI and prototyping using Ionic's command line and live reload by going into your projects ionic folder we created above:

ionic serve

This will start a local server and load your app in your browser. You can then work on your JS and HTML and the app will instantly reload. Then have at it with your browser dev tools to ensure your app looks and flows they way you want to. When you are ready to either add device or RHoMobile APIs then simply copy your ionic\www folder to you public folder like we described earlier.

Note: I would not use RhoSimulator for this setup. Quite frankly it is using a different/dated Webkit engine than what you will see on your device. Not to mention Chrome Dev Tools are far superior and you also get Ionics awesome live reload when content changes.

Conclusion and Caveats

Like with any development efforts, there are so many choices and paths you can take to get to the same end result. Overall no matter what sets of components you choose for your application stack, you should fully understand how and why it is behaving the way it does and what aspects will effect your end users perception of how well your application is performing. As mentioned before, don't expect any Cordova plug-ins to work in a RhoMobile application using Ionic, but the rest of the framework will give you many opportunities to get your hybrid application started on the right foundation. I am always interested in hearing different options and suggestions for doing things a better way. For those who may be just starting with RhoMobile and possibly Hybrid application development, I hope you find the starter apps and suggested stack described here useful and a positive experience in your getting started journey.