@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 --splashionic 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.