@digitaldrummerj
Why are we still coding for multiple platforms?
"Hello."
Year | Device | Processor | RAM |
---|---|---|---|
2007 | iPhone | 620 MHz | 128 MB |
2010 | iPhone 4 | 1 GHz | 512 MB |
2014 | iPhone 6 | 1.4 GHz dual-core | 1 GB |
2015 | iPhone 6s | 1.8 GHz dual-core | 2 GB |
iOS 6+
Android 4+
Win Phone 10
Your App
Ionic
Angular
Webview (Cordova)
Native SDK
$ npm install -g gulp bower cordova ionic
Install NodeJs - http://nodejs.org
Visual Studio Code - https://code.visualstudio.com/
Install Git - https://msysgit.github.io/
Mac already has it installed
Globally install npm packages
ionic start todo blank
ionic serve
angular.module('starter', ['ionic'])
file: www\js\app.js
angular.module('starter', ['ionic'])
.config(function () {
})
file: www\js\app.js
$stateProvider
$stateProvider
.state('about', {
url: "/about",
templateUrl: "templates/about.html"
});
<ion-view view-title="About">
<ion-content class="padding">
My About Page
</ion-content>
</ion-view>
<ion-nav-view></ion-nav-view>
$urlRouterProvider.otherwise('/about');
$urlRouterProvider
<div>
<div>
<h1>Todo App!</h1>
</div>
<div>
version 1.0
<br/>
<br/> designed & developed by
<br/> [Your Name]
<br/>
<br/> Built using:
<br/> JavaScript, AngularJS, Cordova, & Ionic
<br/>
<br/>
</div>
</div>
<div class="card">
<div class="item item-divider text-center">
<h1>Todo App!</h1>
</div>
<div class="item text-center">
version 1.0
<br/>
<br/> designed & developed by
<br/> [Your Name]
<br/>
<br/> Built using:
<br/> JavaScript, AngularJS, Cordova, & Ionic
<br/>
<br/>
</div>
</div>
<ion-side-menus enable-menu-with-back-views="false">
<ion-side-menu-content>
<ion-nav-bar class="bar-stable">
<ion-nav-back-button></ion-nav-back-button>
<ion-nav-buttons side="left">
<button menu-toggle="left"
class="button button-icon button-clear ion-navicon">
</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-side-menu>
</ion-side-menus>
<ion-header-bar class="bar-stable">
<h1 class="title">Projects</h1>
</ion-header-bar>
<ion-content>
<ion-list>
<ion-item menu-close ng-href="#/app/about">
About
</ion-item>
</ion-list>
</ion-content>
.state('app', {
abstract: true,
'url': '/app',
'templateUrl': 'templates/menu.html',
})
.state('app.about', {
url: '/about',
views: {
'menuContent': {
'templateUrl': 'templates/about.html',
}
}
})
$urlRouterProvider.otherwise('/app/about');
angular
.module('starter')
.controller('AboutController',
AboutController);
AboutController.$inject = ['$scope'];
function AboutController($scope) {
$scope.title = "About My Awesome App";
}
'menuContent':
{
templateUrl: 'templates/about.html',
controller: 'AboutController'
}
<ion-nav-title>{{title}}</ion-nav-title>
<script
src="js/controllers/about.controller.js">
</script>
item-text-wrap
angular
.module('starter')
.controller('ProjectController', ProjectController);
ProjectController.$inject = ['$scope'];
function ProjectController($scope){
}
.state('app', {
abstract: true,
url: '/app',
templateUrl: 'templates/menu.html',
controller: 'ProjectController'
})
$scope.projects = [
{
"title": "Project 1"
},
{
"title": "Project 2"
}
];
<ion-item ng-repeat="project in projects">
{{project.title}}
</ion-item>
<script
src="js/controllers/project.controller.js">
</script>
<ion-view>
<ion-nav-title>{{activeProject.title}}</ion-nav-title>
<ion-content class="padding">
<ion-list>
<ion-item
ng-repeat="task in activeProject.tasks">
{{task.title}}
</ion-item>
</ion-list>
</ion-content>
</ion-view>
angular
.module('starter')
.controller('TasksController', TasksController);
TasksController.$inject = ['$scope'];
function TasksController($scope) {
}
.state('app.tasks', {
url: '/tasks',
views: {
'menuContent': {
templateUrl: 'templates/tasks.html',
controller: 'TasksController'
}
}
})
<ion-item
ng-repeat="project in projects"
ng-click="selectProject(project)"
menu-close
ng-href="#/app/tasks"
>
{{project.title}}
</ion-item>
$scope.selectProject = function (project) {
$scope.activeProject = project;
}
{
"title": "Project 1",
"tasks": [
{
"title": "Task 1",
"completed": false
},
{
"title": "Task 2",
"completed": true
}
]
}
<script
src="js/controllers/tasks.controller.js">
</script>
value | store simple values that may change |
constant | store values that will never change |
service | Service created using constructor function.
Good for devs that prefer OOP-style programming and like using the this keyword |
factory | Service created using constructor function
Good for devs using Revealing Module pattern |
provider | Most control over defining service but more complex and verbose. |
angular
.module('starter')
.factory('ProjectService', ProjectService);
ProjectService.$inject = [];
function ProjectService() {
}
function getProjects() {
return [
{
"title": "Project 1",
"tasks": [
{ "title": "Task 1", "completed": false },
{ "title": "Task 2", "completed": true }
]
},
{
"title": "Project 2",
"tasks": []
}
];
}
angular
.module('starter')
.factory('ProjectService', ProjectService);
ProjectService.$inject = [];
function ProjectService() {
return {
"getProjects": getProjects
};
}
$scope.projects = ProjectService.getProjects();
ProjectController.$inject = [
'$scope', '$state', 'ProjectService'];
function ProjectController($scope, $state, ProjectService) {
}
<i class="button button-icon ion-plus"
ng-click="showProjectModal()">
</i>
ProjectController.$inject = [
'$scope',
'$state',
'ProjectService',
'$ionicModal'
];
function ProjectController(
$scope, $state, ProjectService, $ionicModal) {
}
$ionicModal.fromTemplateUrl(
'templates/new-project.html',
function (modal) {
$scope.projectModal = modal;
},
{
scope: $scope
}
);
<ion-modal-view>
<!-- Modal header bar -->
<ion-header-bar class="bar-secondary">
</ion-header-bar>
<!-- Modal content area -->
<ion-content>
</ion-content>
</ion-modal-view>
<!-- Modal header bar -->
<ion-header-bar class="bar-secondary">
<h1 class="title">New Project</h1>
<button
class="button button-clear button-positive"
ng-click="closeProjectModal()"
>
Cancel
</button>
</ion-header-bar>
<ion-content>
<form ng-submit="saveNewProject(project)">
<div class="list">
<label class="item item-input">
<input type="text"
placeholder="Project Name"
ng-model="project.title">
</label>
</div>
<div class="padding">
<button type="submit"
class="button button-block button-positive"
>
Create Project
</button>
</div>
</form>
</ion-content>
$scope.showProjectModal= function () {
$scope.projectModal.show();
}
$scope.closeProjectModal = function () {
$scope.projectModal.hide();
}
$scope.saveNewProject = function (project) {
var projectTitle = project.title;
if (projectTitle) {
var newProject = ProjectService.addProject(project);
$scope.projects.push(newProject);
$scope.selectProject(newProject);
$scope.closeProjectModal();
$ionicHistory.nextViewOptions({
disableBack: true
});
$state.go('app.tasks');
}
project.title = "";
}
function ProjectService() {
return {
"getProjects": getProjects,
"addProject": addProject
};
function addProject(project) {
return {
"title": project.title,
"tasks": [
{ "title": "first tasks" }
]
};
}
....
}
$ionicSideMenuDelegate.toggleLeft();
ProjectController.$inject = [
'$scope', '$state',
'ProjectService', '$ionicSideMenuDelegate'];
function ProjectController($scope, $state,
ProjectService, $ionicSideMenuDelegate) {
}
<ion-nav-title>{{activeProject.title}}</ion-nav-title>
<ion-nav-buttons side="right">
<button class="button button-icon"
ng-click="newTask()"
ng-if="activeProject"
>
<i class="icon ion-compose"></i>
</button>
</ion-nav-buttons>
angular
.module('starter')
.controller('TasksController', TasksController);
TasksController.$inject = ['$scope', '$ionicModal'];
function TasksController($scope, $ionicModal) {
}
$ionicModal.fromTemplateUrl(
'templates/new-task.html',
function (modal) {
$scope.taskModal = modal;
},
{
scope: $scope
}
);
<ion-modal-view>
<!-- Modal header bar -->
<ion-header-bar class="bar-secondary">
</ion-header-bar>
<!-- Modal content area -->
<ion-content>
</ion-content>
</ion-modal-view>
<!-- Modal header bar -->
<ion-header-bar class="bar-secondary">
<h1 class="title">New Task for {{activeProject.title}}</h1>
<button
class="button button-clear button-positive"
ng-click="closeTaskModal()"
>
Cancel
</button>
</ion-header-bar>
<ion-content>
<form ng-submit="saveNewTask(task)">
<div class="list">
<label class="item item-input">
<input type="text"
placeholder="What do you need to do?"
ng-model="task.title">
</label>
</div>
<div class="padding">
<button type="submit"
class="button button-block button-positive"
>
Create Task
</button>
</div>
</form>
</ion-content>
$scope.showTaskModal= function () {
$scope.taskModal.show();
}
$scope.closeTaskModal = function () {
$scope.taskModal.hide();
}
function ProjectService() {
return {
"getProjects": getProjects,
"addProject": addProject,
"addTask": addTask
};
function addTask(task) {
return {
"title": task.title,
"completed": false
};
}
....
}
angular
.module('starter')
.controller('TasksController', TasksController;
TasksController.$inject = [
'$scope',
'$ionicModal',
'ProjectService'
];
function TasksController($scope, $ionicModal, ProjectService) {
}
$scope.saveNewTask = function (task) {
if (!$scope.activeProject || !task || !task.title) {
return;
}
var newTask = ProjectService.addTask(task);
$scope.activeProject.tasks.push(newTask);
$scope.closeTaskModal();
task.title = "";
}
<i class="icon icon-accessory ion-close-circled"></i>
class="item item-icon-right"
ng-click="deleteProject(project, $index)"
class="item item-icon-right"
$scope.deleteProject = function (project, $index) {
if (project === $scope.activeProject) {
$scope.activeProject = {};
}
$scope.projects.splice($index, 1);
}
<ion-list>
<ion-item
ng-repeat="task in activeProject.tasks"
class="item item-icon-right"
>
{{task.title}}
<i
class="icon ion-close icon-accessory"
ng-click="deleteTask(task, $index)">
</i>
</ion-item>
</ion-list>
$scope.deleteTask = function (task, $index) {
$scope.projects.tasks.splice($index, 1);
}
<i class="icon"
ng-class="task.completed ?
'ion-checkmark-circled' :
'ion-ios-circle-outline'"
ng-click="completeTask(task, $index)">
</i>
$scope.completeTask = function (task, $index) {
if ($scope.activeProject.tasks[$index].completed) {
$scope.activeProject.tasks[$index].completed = false;
} else {
$scope.activeProject.tasks[$index].completed = true;
}
ProjectService.save($scope.projects);
}
<ion-item
ng-repeat="task in activeProject.tasks"
class="item item-icon-left item-icon-right"
>
angular.module('ionic.utils', [])
.factory('$localstorage', ['$window', function($window) {
return {
set: function(key, value) {
$window.localStorage[key] = value;
},
get: function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
},
setObject: function(key, value) {
$window.localStorage[key] = JSON.stringify(value);
},
getObject: function(key) {
return JSON.parse($window.localStorage[key] || '{}');
}
}
}]);
angular.module('starter', ['ionic', 'ionic.utils'])
ProjectService.$inject = ['$localstorage'];
function ProjectService($localstorage) {
}
return {
"getProjects": getProjects,
"addProject": addProject,
"addTask": addTask,
"save": save
};
function save(projects) {
$localstorage.set('projects', angular.toJson(projects));
}
function getProjects() {
var projects = $localstorage.get('projects');
if (projects) {
return angular.fromJson(projects);
}
return [];
}
ProjectService.save($scope.projects);
ProjectService.save($scope.projects);
<div class="item-positive item item-divider text-center">
<h1 class="light">Todo App!</h1>
</div>
.activeProject {
background-color: $dark;
color: $light;
}
.completedTask {
text-decoration: line-through;
color: #A9A9A9;
}
ng-class="{completedTask: task.completed}"
$ ionic start myApp tabs
$ cd myApp
$ ionic upload
$ ionic share [email address]
Over 600 MIT licensed font-icons included
Automatically generate icons and splash screens
Creates size needed for each platform
$ ionic resources
$ ionic resources --icon
$ ionic resources --splash
ionic platform add [android/ios]
ionic [run/emulate] [android/ios]
Run test on device/emulator
Add mobile platform (Android or iOS)
@digitaldrummerj - digitaldrummerj@gmail.com
http://digitaldrummerj.me
Data Only
Edit / Delete / Reorder
> 1000 items.