HTML5 that acts like native
Web wrapped in native layer
Direct access to native APIs
Familiar web dev environment
A single code base (web platform!)
(You'll feel right at home)
angular.module('ionicApp', ['ionic']) .config(function($stateProvider, $urlRouterProvider) { $stateProvider .state('app', { url: '/app', abstract: true, templateUrl: 'templates/menu.html', controller: 'AppCtrl' }) .state('app.search', { url: '/search', views: { 'menuContent': { templateUrl: 'templates/search.html' } }, }) .state('app.browse', { url: '/browse', views: { 'menuContent': { templateUrl: 'templates/browse.html', controller: 'BrowseCtrl' } }, }) $urlRouterProvider.otherwise('/app/browse'); });
State-Based Router with Nested Views
<div class="list card"> <div class="item item-body card-body"> <div class="image-container"> <img src="{{postData.image}}" alt="" /> </div> <div class="content-container"> <div class="description">{{postData.description}}</div> <div class="" ng-if="postData.comments.length"> <button class="button button-clear button-positive" ng-click="toggleComments()"> ... </button> <div class="item item-text-wrap" ng-show="commentsVisible" ng-repeat="comment in postData.comments track by $index"> {{comment}} </div> </div> <div ng-show="commentFieldVisible"> <div class="item item-input-inset" ng-show="commentFieldVisible"> <label class="item-input-wrapper"> <input type="text" placeholder="Add a comment" ng-model="newComment"> </label> <button class="button button-small button-balanced" ng-click="addComment()">Submit</button> </div> </div> <div class="button-bar"> ... </div> </div> </div> </div>
It's just Angular.js! (No extra learning curve)
.directive('postCard', function() { return { restrict: 'E', templateUrl: 'templates/post-card.html', scope: { postData: "=", }, controller: function($scope, $element) { // Some controller logic } }; });
.controller('BrowseCtrl', function($scope) { $scope.posts = [ { image: 'img/arya.jpg', description: "" }, { image: 'img/jon-snow.jpg', description: "" }, { image: 'img/tyrion.jpg', description: "" }, { image: 'img/daenerys.jpg', description: "" }, ]; })
... <ion-content> <post-card ng-repeat="post in posts" post-data="post"></post-card> </ion-content> ...
npm install -g ionic cordova
Boilerplate app structure ready for customization
LiveReload both local and native builds
Build and run native apps
js/app.js
angular.module('ionicApp', ['ionic']) .config(function($stateProvider, $urlRouterProvider) { $stateProvider .state('app', { url: '/app', abstract: true, templateUrl: 'templates/menu.html', controller: 'AppCtrl' }) .state('app.browse', { url: '/browse', views: { 'menuContent': { templateUrl: 'templates/browse.html', controller: 'BrowseCtrl' } }, }); // if none of the above states are matched, use this as the fallback $urlRouterProvider.otherwise('/app/browse'); }) .controller('AppCtrl', function($scope) {}) .controller('BrowseCtrl', function($scope) {});
/templates/browse.html
<ion-view view-title="Browse"> <ion-content> <h2>Browse</h2> </ion-content> </ion-view>
/templates/menu.html
<ion-side-menus enable-menu-with-back-views="false"> <ion-side-menu-content> <ion-nav-bar class="bar-positive"> <ion-nav-back-button> </ion-nav-back-button> <ion-nav-buttons side="left"> <button class="button button-icon button-clear ion-navicon" menu-toggle="left"> </button> </ion-nav-buttons> </ion-nav-bar> <ion-nav-view name="menuContent"></ion-nav-view> </ion-side-menu-content> <ion-side-menu side="left"> <ion-content> <ion-list> <ion-item menu-close href="#/app/browse"> Browse </ion-item> </ion-list> </ion-content> </ion-side-menu> </ion-side-menus>
/templates/post-card.html
<div class="list card"> <div class="item item-body card-body"> <div class="image-container"> <img src="{{postData.image}}" alt="" /> </div> <div class="content-container"> <div class="description">{{postData.description}}</div> <div class="" ng-if="postData.comments.length"> <button class="button button-clear button-positive" ng-click="toggleComments()"> ... </button> <div class="item item-text-wrap" ng-show="commentsVisible" ng-repeat="comment in postData.comments track by $index"> {{comment}} </div> </div> <div ng-show="commentFieldVisible"> <div class="item item-input-inset" ng-show="commentFieldVisible"> <label class="item-input-wrapper"> <input type="text" placeholder="Add a comment" ng-model="newComment"> </label> <button class="button button-small button-balanced" ng-click="addComment()">Submit</button> </div> </div> <div class="button-bar"> ... </div> </div> </div> </div>
/js/app.js
.controller('BrowseCtrl', function($scope) { $scope.posts = [ { image: 'img/arya.jpg', description: "..." }, { image: 'img/jon-snow.jpg', description: "..." }, { image: 'img/tyrion.jpg', description: "..." }, { image: 'img/daenerys.jpg', description: "..." }, ]; })
/templates/browse.html
<ion-view view-title="Browse"> <ion-content class="animate-fade-slide-in"> <post-card ng-repeat="p in posts" post-data="p"></post-card> </ion-content> </ion-view>
/js/app.js
.directive('postCard', function($ionicActionSheet, $ionicPopup, $timeout) { return { restrict: 'E', templateUrl: 'templates/post-card.html', scope: { postData: "=", }, controller: function($scope, $element) { $scope.commentsVisible = false; $scope.commentFieldVisible = false; $scope.postData.comments = $scope.postData.comments || []; $scope.toggleLike = function() { ... $scope.addComment = function() { ... $scope.showOptions = function() { ... } }; });
Providers and Service Objects
js/app.js
.factory('Post', function($resource) { return $resource('http://my-awesome-REST-API.com/post'); })
js/app.js
.controller('BrowseCtrl', function($scope, Post) { // Get all posts $scope.posts = Post.query(); })
1. Install ngResource via Bower (optional)
$ bower install ng-resource --save
2. Add dependency to index.html (optional)
<script src="lib/ng-resource/<path to>/ng-resource.js"></script>
3. Include in Angular app dependencies (optional)
angular.module('ionicApp', ['ionic', 'ngResource'])
bower install ngCordova --save-dev
lib/ngCordova/dist/ng-cordova.js
angular.module('starter', ['ionic','ngCordova'])
ionic plugin add org.apache.cordova.camera
.controller('AppCtrl', function($scope, $cordovaCamera) { document.addEventListener("deviceready", function () { var options = { quality: 50, destinationType: Camera.DestinationType.DATA_URL, sourceType: Camera.PictureSourceType.CAMERA, allowEdit: true, encodingType: Camera.EncodingType.JPEG, targetWidth: 100, targetHeight: 100, popoverOptions: CameraPopoverOptions, saveToPhotoAlbum: false, correctOrientation:true }; $scope.getPicture = function() { $cordovaCamera.getPicture(options).then(function(imageData) { var image = document.getElementById('myImage'); image.src = "data:image/jpeg;base64," + imageData; }, function(err) { // error }); }; }, false); });
<ion-nav-buttons side="right"> <button class="button button-icon button-clear ion-plus" menu-toggle="right" ng-click="getPicture()"></button> </ion-nav-buttons>
Taking a photo
Getting started guide ionicframework.com/getting-started
Documentation ionicframework.com/docs
Visit the Community Forum forum.ionicframework.com
Contribute on GitHub github.com/driftyco/ionic