.
303 Create Ionic Sales Record Book With Side Menu
Building On Codepen Platform
Continue from the previous tutorial, http://basic-steps.blogspot.my/2017/01/302-create-ionic-sales-record-book-with.html
1) Add Side Menu Pages and Controls
HTML
- Side Menu codes
<script id="menu.html" type="text/ng-template">
<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 class="button button-icon button-clear ion-navicon" menu-toggle="left"></button> </ion-nav-buttons> </ion-nav-bar> <ion-nav-view name="side-menu21"></ion-nav-view> </ion-side-menu-content> <ion-side-menu side="left" id="side-menu21"> <ion-header-bar class="bar-stable"> <div class="title">Menu</div> </ion-header-bar> <ion-content padding="false" class="side-menu-left has-header "> <ion-list id="menu-list1"> <ion-item id="menu-list-item1" ui-sref="menu.home" menu-close="">Home</ion-item> <ion-item id="menu-list-item2" ui-sref="menu.summary" menu-close="">Summary</ion-item> <ion-item id="menu-list-item3" ui-sref="menu.details" menu-close="">Details</ion-item> </ion-list> </ion-content> </ion-side-menu> </ion-side-menus> </script> |
- Summary Page
<script id="summary.html" type="text/ng-template">
<ion-view title="Summary" id="page2"> <ion-content padding="true" class="has-header"></ion-content> </ion-view> </script> |
- Add Details Page
<script id="details.html" type="text/ng-template">
<ion-view title="Details" id="page3"> <ion-content padding="true" class="has-header"></ion-content> </ion-view> </script> |
JS
- Side Menu Control codes
.controller('menuCtrl', ['$scope', '$stateParams',
function ($scope, $stateParams) {
}])
|
- Summary Control codes
.controller('summaryCtrl', ['$scope', '$stateParams',
function ($scope, $stateParams) {
}])
|
- Details Control Code
.controller('detailsCtrl', ['$scope', '$stateParams',
function ($scope, $stateParams) {
}])
|
- Modify Config
.state('menu.home', {
url: '/page1',
views: {
'side-menu21': {
templateUrl: 'home.html',
controller: 'homeCtrl'
}
}
})
.state('menu', {
url: '/side-menu21',
templateUrl: 'menu.html',
controller: 'menuCtrl'
})
.state('menu.summary', {
url: '/page2',
views: {
'side-menu21': {
templateUrl: 'summary.html',
controller: 'summaryCtrl'
}
} })
.state('menu.details', {
url: '/page3',
views: {
'side-menu21': {
templateUrl: 'details.html',
controller: 'detailsCtrl'
}
} })
$urlRouterProvider.otherwise('/side-menu21/page1')
});
|
Full Codes
HTML
<html>
<head> <meta charset="utf-8"> <title>Diary</title> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> <!-- Internal Library <link href="lib/ionic/css/ionic.css" rel="stylesheet"> <script src="lib/ionic/js/ionic.bundle.js"></script> --> <!-- Cloud Library --> <link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet"> <script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script> <!-- Needed for Cordova/PhoneGap (will be a 404 during development) --> <script src="cordova.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/datejs/1.0/date.min.js"></script> </head> <body ng-app="app"> <div> <div> <ion-nav-bar class="bar-stable"> <ion-nav-back-button></ion-nav-back-button> </ion-nav-bar> <ion-nav-view></ion-nav-view> </div> </div> <script id="home.html" type="text/ng-template"> <ion-view title="Home" id="page1"> <ion-nav-buttons side="right" class="has-header"> <button class="button button-icon" ng-click="insertRecord()"> <i class="icon ion-compose"></i> </button> </ion-nav-buttons> <ion-content padding="true" class="has-header"> <!-- {{date}} <br/> {{details}} <br/> {{summaryYearMonth}} <br/> {{summaryDay}} --> <h2>DETAILS</h2> <div class="row"> <div class="col"><b>Date</b></div> <div class="col"><b>Sales</b></div> </div> <div class="row" ng-class-odd="'odd'" ng-class-even="'even'" ng-repeat="detail in details"> <div class="col">{{detail.date | date:'yyyy-MM-dd HH:mm:ss Z'}}</div> <div class="col">{{detail.value}}</div> </div> <h2>YEAR-MONTH SUMMARY</h2> <div class="row"> <div class="col"><b>Date</b></div> <div class="col"><b>Sales</b></div> </div> <div class="row" ng-class-odd="'odd'" ng-class-even="'even'" ng-repeat="(key, value) in summaryYearMonth"> <div class="col">{{key}}</div> <div class="col">{{value}}</div> </div> <h2>DAY SUMMARY</h2> <div class="row"> <div class="col"><b>Date</b></div> <div class="col"><b>Sales</b></div> </div> <div class="row" ng-class-odd="'odd'" ng-class-even="'even'" ng-repeat="(key, value) in summaryDay"> <div class="col">{{key}}</div> <div class="col">{{value}}</div> </div> </ion-content> </ion-view> </script> <script id="insertRecord.html" type="text/ng-template"> <div class="modal"> <!-- Modal header bar --> <ion-header-bar class="bar-secondary"> <h1 class="title">Insert Record</h1> <button class="button button-clear button-positive" ng-click="closeInsertRecord()">Cancel</button> </ion-header-bar> <!-- Modal content area --> <ion-content> <form ng-submit="submitInsertRecord(record)"> <div class="list"> <label class="item item-input"> <input type="date" placeholder="Transaction Date" ng-model="record.date"> </label> <label class="item item-input"> <input type="text" placeholder="Transaction Value" ng-model="record.value"> </label> </div> <div class="padding"> <button type="submit" class="button button-block button-positive">Insert Record</button> </div> </form> </ion-content> </div> </script> <script id="menu.html" type="text/ng-template"> <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 class="button button-icon button-clear ion-navicon" menu-toggle="left"></button> </ion-nav-buttons> </ion-nav-bar> <ion-nav-view name="side-menu21"></ion-nav-view> </ion-side-menu-content> <ion-side-menu side="left" id="side-menu21"> <ion-header-bar class="bar-stable"> <div class="title">Menu</div> </ion-header-bar> <ion-content padding="false" class="side-menu-left has-header "> <ion-list id="menu-list1"> <ion-item id="menu-list-item1" ui-sref="menu.home" menu-close="">Home</ion-item> <ion-item id="menu-list-item2" ui-sref="menu.summary" menu-close="">Summary</ion-item> <ion-item id="menu-list-item3" ui-sref="menu.details" menu-close="">Details</ion-item> </ion-list> </ion-content> </ion-side-menu> </ion-side-menus> </script>
<script id="summary.html" type="text/ng-template">
<ion-view title="Summary" id="page2"> <ion-content padding="true" class="has-header"></ion-content> </ion-view> </script> <script id="details.html" type="text/ng-template"> <ion-view title="Details" id="page3"> <ion-content padding="true" class="has-header"></ion-content> </ion-view> </script> </body> </html> |
JS
angular.module('app', ['ionic'])
.factory('DataTree', function() { return { all: function(trunkName) { var trunkString = window.localStorage[trunkName]; if (trunkString) { return angular.fromJson(trunkString); } return []; }, save: function(trunkName, trunkString) { //console.log(trunkString); window.localStorage[trunkName] = angular.toJson(trunkString); } } }) .controller('homeCtrl', ['$scope', '$stateParams', '$ionicModal', 'DataTree', function($scope, $stateParams, $ionicModal, DataTree) { $scope.date = new Date(); //var trunkDetails=[ // {date:$scope.date,value:100.50}, // {date:$scope.date,value:200.25} //]; //DataTree.save("trunkDetails",trunkDetails); $scope.details = DataTree.all("trunkDetails"); //console.log($scope.details); function summarizeYearMonth() { // convert to array var datevalue = []; $scope.details.forEach(function(d) { d.date = new Date(d.date); var obj = JSON.parse('{"' + d.date.toISOString().substring(0, 10) + '":' + d.value + '}'); datevalue.push(obj); }); var response = {}; datevalue.forEach(function(d) { //console.log(d); for (var k in d) { var _ = k.split("-"); var year = _[0]; var month = _[1]; var keyname = year + "-" + month; if (!response[keyname]) response[keyname] = d[k]; else response[keyname] = response[keyname] + d[k]; } }); //console.log(response); return response; } $scope.summaryYearMonth = summarizeYearMonth(); function summarizeDay() { // convert to array var datevalue = []; $scope.details.forEach(function(d) { d.date = new Date(d.date); var obj = JSON.parse('{"' + d.date.toISOString().substring(0, 10) + '":' + d.value + '}'); datevalue.push(obj); }); var response = {}; datevalue.forEach(function(d) { //console.log(d); for (var k in d) { var _ = k.split("-"); var year = _[0]; var month = _[1]; var day = _[2]; var keyname = year + "-" + month + "-" + day; if (!response[keyname]) response[keyname] = d[k]; else response[keyname] = response[keyname] + d[k]; } }); //console.log(response); return response; } $scope.summaryDay = summarizeDay(); // Create and load the Modal $ionicModal.fromTemplateUrl('insertRecord.html', function(modal) { $scope.insertRecordModal = modal; }, { scope: $scope, animation: 'slide-in-up' }); // Called when the form is submitted $scope.submitInsertRecord = function(record) { var d = new Date(record.date); var utcDate = new Date(Date.UTC( d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0)); $scope.details.push({ date: utcDate, value: record.value }); DataTree.save("trunkDetails", $scope.details); $scope.summaryYearMonth = summarizeYearMonth(); $scope.summaryDay = summarizeDay(); record.date = ""; record.value = ""; $scope.insertRecordModal.hide(); }; // Open our new task modal $scope.insertRecord = function() { $scope.insertRecordModal.show(); }; // Close the new task modal $scope.closeInsertRecord = function() { $scope.insertRecordModal.hide(); }; } ]) .controller('menuCtrl', ['$scope', '$stateParams', function($scope, $stateParams) {} ]) .controller('summaryCtrl', ['$scope', '$stateParams', function($scope, $stateParams) {} ]) .controller('detailsCtrl', ['$scope', '$stateParams', function($scope, $stateParams) {} ]) .config(function($stateProvider, $urlRouterProvider) { $stateProvider .state('menu.home', { url: '/page1', views: { 'side-menu21': { templateUrl: 'home.html', controller: 'homeCtrl' } } }) .state('menu', { url: '/side-menu21', templateUrl: 'menu.html', controller: 'menuCtrl' }) .state('menu.summary', { url: '/page2', views: { 'side-menu21': { templateUrl: 'summary.html', controller: 'summaryCtrl' } } }) .state('menu.details', { url: '/page3', views: { 'side-menu21': { templateUrl: 'details.html', controller: 'detailsCtrl' } } }) $urlRouterProvider.otherwise('/side-menu21/page1') }); |
2) Move Codes To Their Respective Pages.
Summary Codes go to Summary Page.
Details Codes go to Details Page.
We also include some more refinements:
1. The data object is sorted by date (in ascending order) before it is saved to local storage.
2. The Details Page contains ng-repeat filter that sorts item by date in descending order.
2.1) Summary Page.
HTML
<html>
<head>
<meta charset="utf-8">
<title>Diary</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<!-- Internal Library
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<script src="lib/ionic/js/ionic.bundle.js"></script>
-->
<!-- Cloud Library -->
<link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet">
<script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
<!-- Needed for Cordova/PhoneGap (will be a 404 during development) -->
<script src="cordova.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/datejs/1.0/date.min.js"></script>
</head>
<body ng-app="app">
<div>
<div>
<ion-nav-bar class="bar-stable">
<ion-nav-back-button></ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
</div>
</div>
<script id="home.html" type="text/ng-template">
<ion-view title="Home" id="page1">
<ion-content padding="true" class="has-header">
<!-- contents have been moved to other pages -->
</ion-content>
</ion-view>
</script>
<script id="insertRecord.html" type="text/ng-template">
<div class="modal">
<!-- Modal header bar -->
<ion-header-bar class="bar-secondary">
<h1 class="title">Insert Record</h1>
<button class="button button-clear button-positive" ng-click="closeInsertRecord()">Cancel</button>
</ion-header-bar>
<!-- Modal content area -->
<ion-content>
<form ng-submit="submitInsertRecord(record)">
<div class="list">
<label class="item item-input">
<input type="date" placeholder="Transaction Date" ng-model="record.date">
</label>
<label class="item item-input">
<input type="text" placeholder="Transaction Value" ng-model="record.value">
</label>
</div>
<div class="padding">
<button type="submit" class="button button-block button-positive">Insert Record</button>
</div>
</form>
</ion-content>
</div>
</script>
<script id="menu.html" type="text/ng-template">
<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 class="button button-icon button-clear ion-navicon" menu-toggle="left"></button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view name="side-menu21"></ion-nav-view>
</ion-side-menu-content>
<ion-side-menu side="left" id="side-menu21">
<ion-header-bar class="bar-stable">
<div class="title">Menu</div>
</ion-header-bar>
<ion-content padding="false" class="side-menu-left has-header ">
<ion-list id="menu-list1">
<ion-item id="menu-list-item1" ui-sref="menu.home" menu-close="">Home</ion-item>
<ion-item id="menu-list-item2" ui-sref="menu.summary" menu-close="">Summary</ion-item>
<ion-item id="menu-list-item3" ui-sref="menu.details" menu-close="">Details</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
</ion-side-menus>
</script>
<script id="summary.html" type="text/ng-template">
<ion-view title="Summary" id="page2">
<ion-content padding="true" class="has-header">
<h2>YEAR-MONTH SUMMARY</h2>
<div class="row">
<div class="col"><b>Date</b></div>
<div class="col"><b>Sales</b></div>
</div>
<div class="row" ng-class-odd="'odd'" ng-class-even="'even'" ng-repeat="(key, value) in summaryYearMonth">
<div class="col">{{key}}</div>
<div class="col">{{value}}</div>
</div>
<h2>DAY SUMMARY</h2>
<div class="row">
<div class="col"><b>Date</b></div>
<div class="col"><b>Sales</b></div>
</div>
<div class="row" ng-class-odd="'odd'" ng-class-even="'even'" ng-repeat="(key, value) in summaryDay">
<div class="col">{{key}}</div>
<div class="col">{{value}}</div>
</div>
</ion-content>
</ion-view>
</script>
<script id="details.html" type="text/ng-template">
<ion-view title="Details" id="page3">
<ion-nav-buttons side="right" class="has-header">
<button class="button button-icon" ng-click="insertRecord()">
<i class="icon ion-compose"></i>
</button>
</ion-nav-buttons>
<ion-content padding="true" class="has-header">
<!--
{{date}}
<br/> {{details}}
<br/> {{summaryYearMonth}}
<br/> {{summaryDay}}
-->
<h2>DETAILS</h2>
<div class="row">
<div class="col"><b>Date</b></div>
<div class="col"><b>Sales</b></div>
</div>
<div class="row" ng-class-odd="'odd'" ng-class-even="'even'" ng-repeat="detail in details |orderBy:'-date'">
<div class="col">{{detail.date| date:'yyyy-MM-dd'}}</div>
<div class="col">{{detail.value}}</div>
</div>
</ion-content>
</ion-view>
</script>
</body>
</html>
|
JS
angular.module('app', ['ionic'])
.factory('DataTree', function() {
return {
all: function(trunkName) {
var trunkString = window.localStorage[trunkName];
if (trunkString) {
return angular.fromJson(trunkString);
}
return [];
},
save: function(trunkName, trunkString) {
//console.log(trunkString);
window.localStorage[trunkName] = angular.toJson(trunkString);
}
}
})
.controller('homeCtrl', ['$scope', '$stateParams', '$ionicModal', 'DataTree',
function($scope, $stateParams, $ionicModal, DataTree) {
//codes have been moved to other pages
}
])
.controller('menuCtrl', ['$scope', '$stateParams',
function($scope, $stateParams) {}
])
.controller('summaryCtrl', ['$scope', '$stateParams','DataTree',
function($scope, $stateParams,DataTree) {
function summarizeYearMonth() {
// convert to array
var datevalue = [];
$scope.details.forEach(function(d) {
d.date = new Date(d.date);
var obj = JSON.parse('{"' +
d.date.toISOString().substring(0, 10) +
'":' + d.value + '}');
datevalue.push(obj);
});
var response = {};
datevalue.forEach(function(d) {
//console.log(d);
for (var k in d) {
var _ = k.split("-");
var year = _[0];
var month = _[1];
var keyname = year + "-" + month;
if (!response[keyname]) response[keyname] = d[k];
else response[keyname] = response[keyname] + d[k];
}
});
//console.log(response);
return response;
}
function summarizeDay() {
// convert to array
var datevalue = [];
$scope.details.forEach(function(d) {
d.date = new Date(d.date);
var obj = JSON.parse('{"' +
d.date.toISOString().substring(0, 10) +
'":' + d.value + '}');
datevalue.push(obj);
});
var response = {};
datevalue.forEach(function(d) {
//console.log(d);
for (var k in d) {
var _ = k.split("-");
var year = _[0];
var month = _[1];
var day = _[2];
var keyname = year + "-" + month + "-" + day;
if (!response[keyname]) response[keyname] = d[k];
else response[keyname] = response[keyname] + d[k];
}
});
//console.log(response);
return response;
}
$scope.$on('$ionicView.enter', function(){
$scope.details = DataTree.all("salesRecordBookDetails");
//console.log($scope.details);
$scope.summaryYearMonth = summarizeYearMonth();
$scope.summaryDay = summarizeDay();
});
}
])
.controller('detailsCtrl', ['$scope', '$stateParams', '$ionicModal', 'DataTree',
function($scope, $stateParams, $ionicModal, DataTree) {
$scope.date = new Date();
//var trunkDetails=[
// {date:$scope.date,value:100.50},
// {date:$scope.date-10,value:200.25}
//];
//DataTree.save("salesRecordBookDetails",trunkDetails);
$scope.details = DataTree.all("salesRecordBookDetails");
//console.log($scope.details);
//convert string data into date object
$scope.details.forEach(function(d){
d.date = new Date(d.date); });
// Create and load the Modal
$ionicModal.fromTemplateUrl('insertRecord.html', function(modal) {
$scope.insertRecordModal = modal;
}, {
scope: $scope,
animation: 'slide-in-up'
});
// Called when the form is submitted
$scope.submitInsertRecord = function(record) {
var d = new Date(record.date);
var utcDate = new Date(Date.UTC(
d.getFullYear(),
d.getMonth(),
d.getDate(), 0, 0, 0));
$scope.details.push({
date: utcDate,
value: record.value
});
//sort items by date
$scope.details.sort(function(a,b) {
return new Date(a.date).getTime() -
new Date(b.date).getTime()
});
DataTree.save("salesRecordBookDetails", $scope.details);
record.date = "";
record.value = "";
$scope.insertRecordModal.hide();
};
// Open our new task modal
$scope.insertRecord = function() {
$scope.insertRecordModal.show();
};
// Close the new task modal
$scope.closeInsertRecord = function() {
$scope.insertRecordModal.hide();
};
}
])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('menu.home', {
url: '/page1',
views: {
'side-menu21': {
templateUrl: 'home.html',
controller: 'homeCtrl'
}
}
})
.state('menu', {
url: '/side-menu21',
templateUrl: 'menu.html',
controller: 'menuCtrl'
})
.state('menu.summary', {
url: '/page2',
views: {
'side-menu21': {
templateUrl: 'summary.html',
controller: 'summaryCtrl'
}
}
})
.state('menu.details', {
url: '/page3',
views: {
'side-menu21': {
templateUrl: 'details.html',
controller: 'detailsCtrl'
}
}
})
$urlRouterProvider.otherwise('/side-menu21/page1')
});
|
No comments:
Post a Comment