Before We Get Started
Before you go through this tutorial, you should have at least a basic understanding of Ionic concepts. You must also already have Ionic installed on your machine.
So, to that end, we will be building a Notepad application that will allow a user to:
- View a list of Notes
- Add new Notes
- Save the Notes to permanent storage
We will start with a blank ionic template.So First install the Ionic blank template.
Open your Git cmd and type the run the following command to generate a new Ionic application.
If your system does not have Git installed ,install it.Follow my tutorial for installation. Git For Windows
ionic start NotePad blankThe Ionic Start command will create a folder named NotePad and setup the Ionic files and folders.
Add the Cordova project for the Android Platform and install the basic Cordova plugins as explained above.
cd Notepad ionic platform add androidAdd the Sqlite plugin to the android project.Sqlite is used to store the data for Notepad app.
cordova plugin add https://github.com/litehelpers/Cordova-sqlite-storage.gitBuild ionic project
ionic build androidOpen your newly created project using android studio (you can use your own IDE).
In android studio.File>Open>select Your Folder where ionic project is present.Select android folder from it and click ok.
Create template folder in the www>templates (Create template folder in the android>asset>www>templates in android studio)
Change your index.html into
<!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 rel="manifest" href="manifest.json"> <!-- un-comment this code to enable service worker <script> if ('serviceWorker' in navigator) { navigator.serviceWorker.register('service-worker.js') .then(() => console.log('service worker installed')) .catch(err => console.log('Error', err)); } </script>--> <link href="lib/ionic/css/ionic.css" rel="stylesheet"> <link href="css/style.css" rel="stylesheet"> <link href="css/animate.css" rel="stylesheet"> <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above <link href="css/ionic.app.css" rel="stylesheet"> --> <!-- ionic/angularjs js --> <script src="lib/ionic/js/ionic.bundle.js"></script> <!-- cordova script (this will be a 404 during development) --> <script src="cordova.js"></script> <!-- your app's js --> <script src="js/app.js"></script> <script src="js/controller.js"></script> <script src="js/autosize.js"></script> <script src="js/ng-cordova.min.js"></script> <input type="hidden" id="hfTemp"/> <input type="hidden" id="hfCheck"/> <input type="hidden" id="hfNoteValue"/> </head> <body ng-app="starter" class="platform-android platform-cordova platform-webview"> <ion-nav-view> </ion-nav-view> </body> </html>
Look into index.html
We add 3 hidden field named hfTemp,hfCheck and hfNoteValue in the index file.Use of it will explained later.
We use two html pages one Main page where you can see your data you add in notepad,here i named as Home.html.Another page for editing or adding text in notepad,here i named as editor.html.
Create a new html file in templates folder named Home.html .Copy the below code.
<ion-view > </div> <div class="bar bar-header bar-positive"> <button class="button" ng-click="Add()">Add</button> <h1 class="title">Notepad</h1> </div> <ion-content class="note" direction="y"> <div ng-repeat="Notemessage in details" class="list card animated infinite " style="opacity: 0.4;" > <div class="item item-divider" style="color:red;"></div> <button class="button button-small-light" ng-click="Delete(Notemessage)">Delete</button> <div class="item item-body" ng-click="watch(Notemessage.id)"> <div > <p>{{Notemessage.message}}</p> </div> </div> </div> </ion-content> </ion-view>It contains an Add button which is used to add new text file to the notepad.
ng-repeat is used to show all the text field you have added.
Create a new html file in templates folder named editor.html.
<ion-view > <div class="bar bar-header bar-positive"> <button class="button" ng-click="Confirm(edit)">Add</button> <h1 class="title">Notepad</h1> </div> <textarea class="editorcss" rows="25" ng-model="edit" id="textset" cols="50" ng-bind="update" placeholder="Enter text here..." style="width:355px;font-size:25px;background-color: rgba(255, 255, 255, .4);"> </textarea> <h1>{{Notemessage}}</h1> </ion-view>It Consist of textarea and an Add button to add file .
Change your style.css into
/* Empty. Add your own CSS if you like */ .test { margin-top:50px; } .imag1 { width:350px; } .main1 { margin-top:150px; } .item.item-input { background-color: transparent; color:#fff; } .editorcss { margin-top:45px; } .note { margin-top:40px; }Download ng-cordova.min.js and copy it in js page.We already specified it in index.html page
Change your app.js into
// Ionic Starter App angular.module('starter', ['ionic','starter.controller','ngCordova']) .run(function($ionicPlatform,$cordovaSQLite,$rootScope,$ionicSideMenuDelegate,$state,$ionicHistory,$ionicPopup) { $ionicPlatform.ready(function() { if(window.cordova && window.cordova.plugins.Keyboard) { // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard // for form inputs) cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); // Don't remove this line unless you know what you are doing. It stops the viewport // from snapping when text inputs are focused. Ionic handles this internally for // a much nicer keyboard experience. cordova.plugins.Keyboard.disableScroll(true); } if(window.StatusBar) { StatusBar.styleDefault(); } var db; db = $cordovaSQLite.openDB({name:"Test.db", location:'default'}); $cordovaSQLite.execute(db, 'CREATE TABLE IF NOT EXISTS Note (id INTEGER PRIMARY KEY AUTOINCREMENT, message TEXT)'); $ionicPlatform.registerBackButtonAction(function(e){ document.getElementById('hfTemp').value="test"; e.preventDefault(); if ($state.is('Home')) { navigator.app.exitApp(); } else{ $state.go('Home'); } return false; },101); }); }) .config (function($stateProvider, $urlRouterProvider) { $stateProvider .state('editor', { url: '/editor', cache: false, templateUrl: 'templates/editor.html', controller: 'EditCtrl' }) .state('Home', { url: '/Home', cache: false, templateUrl: 'templates/Home.html', controller: 'HomeCtrl' }); $urlRouterProvider.otherwise('/Home'); });Explanation
In app.js we created our database and table.I named database as Test.db.Then i created a table named Note having field id and message .
var db; db = $cordovaSQLite.openDB({name:"Test.db", location:'default'}); $cordovaSQLite.execute(db, 'CREATE TABLE IF NOT EXISTS Note (id INTEGER PRIMARY KEY AUTOINCREMENT, message TEXT)');Then we config our back button.If the app is in Home page then exit the app.Otherwise it go Home page.
$ionicPlatform.registerBackButtonAction(function(e){ document.getElementById('hfTemp').value="test"; e.preventDefault(); if ($state.is('Home')) { navigator.app.exitApp(); } else{ $state.go('Home'); } return false; },101); });Then define the 2 page we created in templates folder.
.config (function($stateProvider, $urlRouterProvider) { $stateProvider .state('editor', { url: '/editor', cache: false, templateUrl: 'templates/editor.html', controller: 'EditCtrl' }) .state('Home', { url: '/Home', cache: false, templateUrl: 'templates/Home.html', controller: 'HomeCtrl' }); $urlRouterProvider.otherwise('/Home'); });Add a controller.js in the js folder and copy the below code in it.
angular.module('starter.controller', []) .controller('EditCtrl', function($scope,$stateParams,$cordovaSQLite,$ionicPlatform,$state) { $ionicPlatform.ready(function() { document.getElementById('hfCheck').value="CHECK"; val1=document.getElementById('hfNoteValue').value; if(val1!=null) { vartemp=document.getElementById('hfTemp').value; if(vartemp=="SET") { db = $cordovaSQLite.openDB({name:"Test.db", location:'default'}); var query= "SELECT * FROM Note WHERE id= ?" $cordovaSQLite.execute(db, query, [val1]) .then( function(result) { $scope.edit = result.rows.item(0).message; /* document.getElementById('hfTemp').value="SET";*/ }, function(error) { } ); } } }); $scope.Confirm= function(edit){ vartemp=document.getElementById('hfTemp').value; if(vartemp!="SET") { db = $cordovaSQLite.openDB({name:"Test.db", location:'default'}); $cordovaSQLite.execute(db, 'INSERT INTO Note (message) VALUES (?)', [edit]) .then(function(result) { // $scope.statusMessage = "Message saved successful, cheers!"; $state.go('Home',{}); }, function(error) { // $scope.statusMessage = "Error on saving: " + error.message; }) } if(vartemp=="SET") { val1=document.getElementById('hfNoteValue').value; db = $cordovaSQLite.openDB({name:"Test.db", location:'default'}); var query = "UPDATE Note SET message='"+edit+"' WHERE id=?"; $cordovaSQLite.execute(db, query,[val1]) .then(function(result) { document.getElementById('hfTemp').value="test"; $state.go('Home',{}); }, function(error) { // $scope.statusMessage = "Error on saving: " + error.message; }); } }; }) .controller('HomeCtrl', function($scope,$stateParams,$cordovaSQLite,$ionicPlatform,$state,$ionicPopup) { $ionicPlatform.ready(function() { document.getElementById('hfCheck').value="CHECK"; $scope.details = []; db = $cordovaSQLite.openDB({name:"Test.db", location:'default'}); $cordovaSQLite.execute(db, 'SELECT * FROM Note ORDER BY id DESC') .then( function(result) { if (result.rows.length > 0) { for(var i = 0; i < result.rows.length; i++) { $scope.details.push({id: result.rows.item(i).id, message: result.rows.item(i).message}); } } }, function(error) { $scope.statusMessage = "Error on loading: " + error.message; } ); }); $scope.Delete= function(Notemessage){ var confirmPopup = $ionicPopup.confirm({ title: 'Delete', template: 'Are you sure?' }); confirmPopup.then(function(res) { if(res) { console.log('Sure!'); db = $cordovaSQLite.openDB({name:"Test.db", location:'default'}); var query = "DELETE FROM Note WHERE id = ?"; $cordovaSQLite.execute(db, query, [Notemessage.id]).then(function(res) { $scope.details.splice($scope.details.indexOf(Notemessage), 1); }, function (err) { $scope.statusMessage = "Error on loading: " + err.message; }); } else { console.log('Not sure!'); } }); } $scope.Add = function() { document.getElementById('hfTemp').value="test"; $state.go('editor',{}); } $scope.watch=function(val) { document.getElementById('hfTemp').value="SET"; document.getElementById('hfNoteValue').value=val; $state.go('editor',{}); } });Explanation
Define two controllers named HomeCtrl and EditCtrl.
Within the HomeCtrl.
Select all the data from table Note using the query ‘SELECT * FROM Note ORDER BY id DESC’ and show in the Home.html using ng-repeat.
$ionicPlatform.ready(function() { document.getElementById('hfCheck').value="CHECK"; $scope.details = []; db = $cordovaSQLite.openDB({name:"Test.db", location:'default'}); $cordovaSQLite.execute(db, 'SELECT * FROM Note ORDER BY id DESC') .then( function(result) { if (result.rows.length > 0) { for(var i = 0; i < result.rows.length; i++) { $scope.details.push({id: result.rows.item(i).id, message: result.rows.item(i).message}); } } }, function(error) { $scope.statusMessage = "Error on loading: " + error.message; } ); });Delete the data you add using the code.
$scope.Delete= function(Notemessage){ var confirmPopup = $ionicPopup.confirm({ title: 'Delete', template: 'Are you sure?' }); confirmPopup.then(function(res) { if(res) { console.log('Sure!'); db = $cordovaSQLite.openDB({name:"Test.db", location:'default'}); var query = "DELETE FROM Note WHERE id = ?"; $cordovaSQLite.execute(db, query, [Notemessage.id]).then(function(res) { $scope.details.splice($scope.details.indexOf(Notemessage), 1); }, function (err) { $scope.statusMessage = "Error on loading: " + err.message; }); } else { console.log('Not sure!'); } }); }For adding a file click on the Add button.Here i used hfTemp hidden field.It is used to differentiate the editor page whether it is an update or add a new file.
For New file hfTemp= test
$scope.Add = function() { document.getElementById('hfTemp').value="test"; $state.go('editor',{}); }Watch is used to navigate to editor.html file when we click on the text file..Here i used hfTemp hidden field.It is used to differentiate the editor page whether it is an update or add a new file.
For update hfTemp= SET
$scope.watch=function(val) { document.getElementById('hfTemp').value="SET"; document.getElementById('hfNoteValue').value=val; $state.go('editor',{}); }In EditCtrl
If the hidden field value id Set Then Updatation
if(vartemp=="SET") { db = $cordovaSQLite.openDB({name:"Test.db", location:'default'}); var query= "SELECT * FROM Note WHERE id= ?" $cordovaSQLite.execute(db, query, [val1]) .then( function(result) { $scope.edit = result.rows.item(0).message; /* document.getElementById('hfTemp').value="SET";*/ }, function(error) { } ); } if(vartemp=="SET") { val1=document.getElementById('hfNoteValue').value; db = $cordovaSQLite.openDB({name:"Test.db", location:'default'}); var query = "UPDATE Note SET message='"+edit+"' WHERE id=?"; $cordovaSQLite.execute(db, query,[val1]) .then(function(result) { document.getElementById('hfTemp').value="test"; $state.go('Home',{}); }, function(error) { // $scope.statusMessage = "Error on saving: " + error.message; }); }If hidden field not equal SET then insert
if(vartemp!="SET") { db = $cordovaSQLite.openDB({name:"Test.db", location:'default'}); $cordovaSQLite.execute(db, 'INSERT INTO Note (message) VALUES (?)', [edit]) .then(function(result) { // $scope.statusMessage = "Message saved successful, cheers!"; $state.go('Home',{}); }, function(error) { // $scope.statusMessage = "Error on saving: " + error.message; }) }
Then build and run your project
ionic run androidNote:Copy all files from NotePad\platforms\android\assets\www into Notepad\www
(If you are developing using android studio).Then Build ionic project.
Your notepad app is ready.
Check the app in playstore Notepad app
Download the code From Ionic Market or From GitHub