TL;DR:
Second part of Cordova + Ionic Tutorial on Visual Studio. Code here & Part I here
Hi everyone,
Last time, I presented you Cordova and walked you through the beginning of the process of building a simple Cordova app using Ionic and Visual Studio tools. But we weren't done. Not even close!
Ok, you've seen how to start a project in Visual Studio, how to structure our project using Ionic together with AngularJS and how to use some of Ionic directives and attributes to make your app feel like a native mobile one. It's time to try out one of the major features of Cordova cross-platform development - plugins.
Cordova itself provides the basic functionalities to the developer. The goal is for the developer to add the remaining APIs he requires through the installation of plugins. And what are these plugins?
A plugin is a package of injected code that allows the Cordova webview within which the app renders to communicate with the native platform on which it runs.
Picking it up from where we left of
At the end of Part 1 of this tutorial we had created our Post List view, remember that? Ok, but then what? We couldn't access a single post yet. Let's take care of that.
Last time, at posts.html
, we had at our post item a href
attribute linking to what would have been a Post view.
<ion-item ng-repeat="item in model.posts" class="item-thumbnail-left" href="#/app/post/{{item.Id}}">
That's what we probably would have done in a normal scenario, create another view and controller, like we did with the post list. In this case though, as I have my posts already online, I'm gonna use this situation to present you guys with a Cordova plugin that could come in handy - InAppBrowser.
InAppBrowser Plugin
First of all, this is how you install it, using Visual Studio:
- Double click
config.xml
file in your project.
- Select the Plugins menu option
- You'll have 3 tabs here: Core, Custom and Installed. You'll find InAppBrowser under the Core list. However if you want to install a different one, not available on this list, you can use the Custom tab and install it with a Git repo link. It's easy like that.
- Now just click Add
To make our life easier when using Cordova plugins together with AngularJS, we're installing ngCordova. ngCordova provides wrappers for the most commonly used Cordova plugins. You can read more about it in the link above.
So let's open our console, and use bower:
> bower install ngCordova -S
Next we add the script in our index.html
file:
<script src="bower_components/ngCordova/dist/ng-cordova.js"></script>
And finally we inject ngCordova module into our app, in our app.js
file:
//[app.js]
var app = angular.module('BinaryLiesApp', ['ionic', 'angularMoment', 'ngCordova']);
That's done. Save it, and let's go back to our Posts view. Let's change the item action so it will now call an action of our choice.
//[posts.html]
<ion-item ng-repeat="item in model.posts" class="item-thumbnail-left" ng-click="openPost(item)">
And in the PostsController we'll create the action.
//[PostsController.js]
$scope.openPost = function (item) {
// InAppBrowser related code will be here
}
For us to be able to use the InAppBrowser plugin, we'll need one more thing - to register $cordovaInAppBrowser service, provided by ngCordova in our PostsController, like this:
//[PostsController.js]
var PostsController = ['$scope', '$cordovaInAppBrowser', 'postsService', function ($scope, $cordovaInAppBrowser, postsService) {
Back to our openPost
function, we're gonna make our post page open in a cordova web view, by doing this:
//[PostsController.js]
$scope.openPost = function (item) {
$cordovaInAppBrowser.open(item.Url, '_blank', { location: 'no' });;
}
The 3rd argument is optional, It's an options object. By default it's 'location:yes', and 'location:no' hides a location bar showing the URL, obviously. This plugin has a few more functionalities that you should read about in their github.
As you can see, if you've tested what we did so far, opening a page with this plugin takes us out of our application context.
It has a few functions that you can use to try to improve this experience, only recommended if you control the landing page as well. Examples of that are the executeScript
and insertCSS
methods. These allow you to inject javascript as well as CSS styles to the page opened by InAppBrowser.
For now, that's as much control as you have inside InAppBrowser. If you desire to open or embed an external page in a seamless way inside your application, you probably will have more success with an IFrame, but that's not an easy (and pretty) task either.
Ok, let's move on now.
Options Menu
The following is a familiar icon in our mobile applications:
This allows us to add some extra functionality to all our pages with a popover menu. I'm going to show you how to build one of those.
All the javascript code will go under the AppController, so these functions are available throughout the entire application, since it will contain context-unaware functionalities.
To actually present the popover, we'll be using an ionic service -$ionicPopover. Let's build it then.
- First, we add the following code in the menu.html file
<!--[menu.html]-->
<ion-nav-bar class="bar bar-positive nav-title-slide-ios">
(...)
<ion-nav-buttons side="right">
<!-- The search button, with a click action to a function called toggleSearch -->
<button class="button button-icon icon ion-ios-search-strong" ng-click="toggleSearch(true)"> </button>
<!-- And here, the plus button, that will open a menu, it has a click action to another function we'll create -->
<button class="button button-icon icon ion-android-more-vertical" ng-click="openPopoverMenu($event)"></button>
</ion-nav-buttons>
</ion-nav-bar>
- Inject $ionicPopover service to AppController (AppControler.js)
//[AppController.js]
var AppController = ['$scope', '$ionicPopover', '$location', '$state', function ($scope, $ionicPopover, $location, $state) {
- Initialize the popover from a html template in the AppController Init function, and save the instance to a $scope variable:
//[AppController.js]
self.Init = function () {
$ionicPopover.fromTemplateUrl('app/templates/popover-menu.html', {
scope: $scope,
}).then(function (popover) {
$scope.menuPopover = popover;
});
//To destroy the popover when we're done with it
$scope.$on('$destroy', function () {
$scope.menuPopover.remove();
});
}
- Create the popover-menu.html template
<!--[popover-menu.html]-->
<ion-popover-view class="fit">
<ion-content scroll="false">
<div class="list">
<!-- Here goes the list of action that we want to make available in the menu -->
<ion-item item-icon-left href="#" ng-click="openPopoverMenuOption('share')">
<i class="icon ion-android-share-alt"></i>
Share
</ion-item>
</div>
</ion-content>
</ion-popover-view>
- Finally we'll create the popover show/hide functions in the AppController
//[AppController.js]
$scope.openPopoverMenu = function ($event) {
$scope.menuPopover.show($event);
};
$scope.closePopoverMenu = function () {
$scope.menuPopover.hide();
};
Done! You should have something like the image below. The height of the popover could be changed using some CSS.
Options Menu: Share
A common thing in our mobile applications, and pretty much everywhere nowadays, is the possibility of sharing any content through our favorite channels. Let's see how we can make that happen using another Cordova plugin - Social Sharing.
This is a pretty simple one. At first, we'll need to follow the steps we've taken before with the InAppBrowser Plugin: let's go to our config.xml > Plugins and install Social Sharing plugin.
This is not one of the core ones, so we'll have to use the Custom tab, select the Git method option, and use the following Url to install it:
https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin.git
Ng-cordova has a wrapper for sharing as well, so we'll inject ng-cordova's share service to our AppController.js to use it in a function.
//[AppController.js]
var AppController = ['$scope', '$ionicPopover', '$location', '$state', '$cordovaSocialSharing', function ($scope, $ionicPopover, $location, $state, $cordovaSocialSharing) {
And then we have the share function (also in AppController.js). This function will invoke the native device services, allowing the user to share with any of the sharing apps available in the device. If you want to share only to a specific application, ng-cordova has also some specific functions like shareViaFacebook or shareViaTwitter that you can find here.
//[AppController.js]
$scope.share = function (title, message, link, file) {
$cordovaSocialSharing
.share(message, title, file, link) // Share via native share sheet
.then(function (result) {
console.log("shared successfully");
}, function (err) {
// An error occured
console.log("An error occured while sharing.");
});
}
Moving forward... remember back then where we added the Share option to the popover menu? There we added a openPopoverMenuOption function binded to the click action. Let's create it now and put to use our new share function. In our AppController:
//[AppController.js]
$scope.openPopoverMenuOption = function (option) {
$scope.closePopoverMenu();
if (option == 'share') {
var title = "Binary Lies Mobile App";
var message = document.title;
var url = "http://binarylies.ghost.io/";
$scope.share(title, title + " : " + message, url, null);
}
}
This is the final look of your share, if you choose to share via Twitter.
And this is it guys! A very simple application, that I hope it helps you get started with a few basics of developing with Cordova and Ionic.
Code of Part I & II here:
https://github.com/joanavb/binarylies_cordova101tutorialPart1and2