forked from shangerxin/BookNotes
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathBuilding Mobile Apps with the Ionic Framework and AngularJS=Steve Michelotti;Note=Erxin.txt
705 lines (563 loc) · 19.6 KB
/
Building Mobile Apps with the Ionic Framework and AngularJS=Steve Michelotti;Note=Erxin.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
Building Mobile Apps with the Ionic Framework and AngularJS=Steve Michelotti;Note=Erxin
# Introduction
- code focus course
- course overview
+ introduction
+ getting started with ionic
+ navigation and routing with ionic
+ ionic components
girds, lists, cards, ...
+ data and caching for off line functionality
+ mapping
+ customizing ionic using sass
+ ngCordova to use access native device feature
+ basic request
angularjs, get start
angularjs, fundamentals
- what is ionic
+ open source framework for mobile-optimized library for html/js/css
+ built on top of angularjs
+ built for native cordova apps
+ bootstrap for mobile
+ ionicframework.com is the home page
+ click the getting start and doc to check the documentation
+ the showcase are the exiting apps which are build with ionic
+ subscribe the ionic blog
- cordova what and why?
wraps native api
it is cross platform
native mobile apps using html/js/css
re-use existing web skills
re-use existing web frameworks
- what we will be building
http://www.elite-schedule.net/2011
build a mobile accelerate functions for the website
- create a site map
# Getting start with ionic
- overview
+ ionic command line features
+ starting a new project
+ run your app
+ ionic starter templates
+ setting up your development environment
- ionic command line features
start, starts a new ionic project
serve, starts a local development server
platform, configure platform targets
build, locally build app for a platform
emulate, app in simulator
run, run app on device
- installing ionic
+ install nodejs
+ use console2 command prompt tool
+ install ionic
$ npm install -g ionic
+ install cordova
$ npm install -g cordova
- starting a new project
+ start a new project
$ ionic start [appName] [template]
$ ionic start myApp blank
this command will create the directory structure
+ open subline IDE
- run the app with a browser
+ local browser
* go to ionic project directory
* use serve command to start a development server
$ ionic serve
* instead of use chrome we could use canary which add newest of the chrome features, be forewared designed for developers and early adopters
canary with F12 will supply a emulation mode for perfect specify device size, it will also automatic change the user agent
* after change the code ionic will watch the file change and it will automatic restart the server
- run the app with an emulator
+ build the app
$ ionic platform add android
$ ionic build android
$ ionic emulate android
- run the app on read device, if set platform to execute in the real device with android sdk
$ionic platform and android
- ionic starter template
blank
tabs, basic tabs navigation from the bottom
sidemenu
maps
- setting up a development environment
$ ionic start project-name tabs
tabs is the template name
$ ionic serve
will start the developer service
+ use the sidemenu template
$ ionic start project-name sidemenu
use the sidemenu template
+ use sublime as IDE which is lightweight
* init ionic project
* open project directory
- setting up a development environment with visual studio
+ create new project
+ select blank javascript template
+ copy the previous ionic created project template and replace project files which is created by VS
+ the code run under the teler simulator
- setting up codepen, setting up a codepen account. it could be used as scrach pad
http://codepen.io/ionic
there are lots of example for ionic on the codepen.io
+ similar to JSFiddler or Plunker for tring ionic
- summary
# Navigation and routing
- overview
headers & footers -> tabs -> sidemenu-> routing
- navigation for elite schedule
+ site map
and decide which kinds of views to navigate between each views
- ionic header and footers
<body ng-controller="myCtrl">
<ionic-header-bar class="bar-position">
</ionic-header-bar>
<div class="bar bar-header bar-positive">
<div class="title">{{mytitle}}</div>
</div>
<div class="bar bar-footer bar-balanced">
<div class="title">{{myfooter}}</div>
</div>
</body>
the ionic-header-bar is a ionic directive. there are lots of ionic customized directives
- introduction to ionic tabs
<ion-tabs class="tabs-energized tabs-icon-top">
<ion-tab title="Dashboard" icon="ion-home" href="#">
</ion-tab>
<ion-tab title="favorites" icon="ion-star" href="#">
</ion-tab>
<ion-tab title="Account" icon="ion-gear-a" href="#">
</ion-tab>
</ion-tabs>
we could also change the style to tabs-icon-only
+ a list of ionc could be found at ionicons.com
- tabs setting up the initial structure
<header>
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="cordova.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
</head>
<body> ng-app="eliteApp">
<ion-nav-view></ion-nav-view>
</body>
+ add app.js file at /www/app/app.js
angular.module("eliteApp", ["ionic"])
.run(function($ionicPlatform){
$ionicPlatform.ready(function(){
if(window.cordova && window.cordova.plugins.Keyboard){
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar){
//org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider){
$stateProvider.state('home', {
url:"/home",
templateUrl:"app/home/home.html"
});
$stateProvider.state("app", {
url:"/app"
templateUrl:"app/layout/menu-layout.html"
});
$urlRouterProvider.otherwise('/app');
});
+ create home folder at /www/app/home/home.html
<ionic-nav-bar class="bar-balanced">
<h1 class="title">Elite Schedule</h1>
</ionic-nav-bar>
<ion-tabs class=...>
<ion-tab title="Leagues">
<ion-view></ion-view>
</ion-tab>
</ion-tabs>
- side menu, setting up the initial structure
+ add new folder /www/app/layout
+ add new file /www/app/layout/menu-layout.html
<ion-side-menus>
<ion-pane ion-side-menu-content>
<button menu-toggle="left" class="button button-icon icon ion-navicon"></button>
</ion-nav-bar>
<icon-side-menu side="left">
<header class="bar bar-header ...">
</header>
<ion-content class="has-header">
<ion-list>
<ion-item nav-clear menu-close>Home</ion-item>
<ion-item nav-clear menu-close>Teams</ion-item>
</ion-list>
</ion-content>
</icon-side-menu>
</ion-side-menus>
- introduction to Angular UI Router, ionic use all angular UI router for all routing needs
+ organize into state machines and translate into selecting the appropriate view
+ allows for nested views
+ 3 ways to active view
ui-sref
url
$state.go()
+ state have
unique name (must)
url, supports parameters
template/templateURL, used to point to a physical resource, specifically the html partial
optionally have controllers
$stateProvider.state("contacts", {
url:"/contacts",
templateUrl:"contacts.html"
})
+ nested states/views
angular UI router supports nested states
uses dot notation to achieve nested views
a child state inherits propertie from parent and it combine url of parent to full url
parent state can be abstract which means the state can't be active
* can have child states but not get actived itself
* must contain their own <ui-view> (ion-nav-view/)
code example for nested states:
$stateProvider
.state("foo", {
abstract:true,
url:"/foo",
templateUrl:"foo.html" //must contain <ui-view>
})
.state("foo.bar", {
url:"/bar", //will be /foo/bar
tempalteUrl: "bar.html"
})
.state("foo.baz", {
url:"/xxx", //will be /foo/xxx
tempalteUrl: "baz.html"
});
the foo state is an abstract state
+ active state
<a href="#/foo/bar">Go</a>
<a ui-sref="foo.bar">Go</a>
$state.go("foo.bar");
+ now we consider the sidemap again
leagues my teams
|
|-----------+---------------+---------------|
| | | |
teams standings locations rules
| |
team detail +-location schedule
| |
+-game --location map
we could use home.html as the layout abstract state view for the app
and the sub page, teams, standings, locations and rules will implement as sub state of leagues in home.html
- adding routing for tabs, app.js
angular.module("eliteApp", ["ionic"])
.run(function($ionicPlatform){
$ionicPlatform.ready(function(){
if(window.cordova && window.cordova.plugins.Keyboard){
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar){
//org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider){
$stateProvider.state('home', {
abstract:true,
url:"/home",
templateUrl:"app/home/home.html"
})
.state('home.leagues', {
url:"/leagues", //define the child state of home
views:{
"tab-leagues":{ //the view of the view defined in html
templateUrl: "app/home/leagues.html"
}
}
})
.state('home.myteams', {
url:"/myteams",
views:{
"tab-myteams":{
templateUrl: "app/home/myteams.html"
}
}
});
$stateProvider.state("app", {
url:"/app"
templateUrl:"app/layout/menu-layout.html"
});
$urlRouterProvider.otherwise('/home');
});
when navigate to an abstract state, the view will become blank because it is not allowed to create an instance for a abstract state
+ goto the home.html and change ion-viewto ion-nav-view
<ionic-nav-bar class="bar-balanced">
<h1 class="title">Elite Schedule</h1>
</ionic-nav-bar>
<ion-tabs class=...>
//we could use href to set where to find the temlate for the view
<ion-tab title="Leagues" icon="ion-home" href="#/home/leagues">
//the name of view will be reference in the app.js in the state
<ion-nav-view name="tab-leagues"></ion-nav-view>
</ion-tab>
//we could also use ui-sref which will let the framwork find the template for us
<ion-tab title="Leagues" icon="ion-star" ui-sref="home.myteams">
<ion-nav-view name="tab-myteams"></ion-nav-view>
</ion-tab>
</ion-tabs>
+ add template for the view tab-leagues and tab-myteams
* /app/home/myteams.html
<ion-view>
<ion-content class="has-header">
<h1></h1>
</ion-content>
</ion-view>
* /app/home/myleagues.html
<ion-view>
<ion-content class="has-header">
<h1></h1>
</ion-content>
</ion-view>
- adding routing for side menu, we are going to set the app state to abstract
.config(function($stateProvider, $urlRouterProvider){
$stateProvider.state('home', {
abstract:true,
url:"/home",
templateUrl:"app/home/home.html"
})
.state('home.leagues', {
url:"/leagues", //define the child state of home
views:{
"tab-leagues":{ //the view of the view defined in html
templateUrl: "app/home/leagues.html"
}
}
})
.state('home.myteams', {
url:"/myteams",
views:{
"tab-myteams":{
templateUrl: "app/home/myteams.html"
}
}
});
$stateProvider.state("app", {
abstract:true,
url:"/app"
templateUrl:"app/layout/menu-layout.html"
})
.state("app.teams", {
url: "/teams",
views:{
"mainContent":{
templateUrl:"app/teams/teams.html"
}
}
})
.state("app.team-detail", {
url: "/teams/id",
views:{
"mainContent":{
templateUrl:"app/teams/team-detail.html"
}
}
})
.state("app.game", {
url: "/game/:id",
views:{
"mainContent":{
templateUrl:"app/game/game.html"
}
}
})
.state("app.standing", {
url: "/standing",
views:{
"mainContent":{
templateUrl:"app/standing/standing.html"
}
}
})
.state("app.locations", {
url: "/locations",
views:{
"mainContent":{
templateUrl:"app/locations/locations.html"
}
}
})
.state("app.teams", {
url: "/rules",
views:{
"mainContent":{
templateUrl:"app/rules/rules.html"
}
}
});
$urlRouterProvider.otherwise('/home');
});
all the added child states of app are point to the mainContent view with their own template
+ make modification for the /www/app/layout/menu-layout.html
<ion-side-menus>
<ion-pane ion-side-menu-content>
<button menu-toggle="left" class="button button-icon icon ion-navicon"></button>
</ion-nav-bar>
<ion-nav-view name="mainContent">
</ion-nav-view>
</ion-pane>
<icon-side-menu side="left">
<header class="bar bar-header ...">
</header>
<ion-content class="has-header">
<ion-list>
<ion-item nav-clear menu-close ui-sref="home.leagues">Home</ion-item>
<ion-item nav-clear menu-close ui-sref="app.teams">Teams</ion-item>
<ion-item nav-clear menu-close ui-sref="app.standing">Standings</ion-item>
<ion-item nav-clear menu-close ui-sref="app.location">Location</ion-item>
<ion-item nav-clear menu-close ui-sref="app.rules">Rules</ion-item>
</ion-list>
</ion-content>
</icon-side-menu>
</ion-side-menus>
+ add states for the view, check the preivous states which inherit from the app state
+ add html teamplates
add new folder /www/app/teams
add team.html /www/app/teams/teams.html
add team-detals.html /www/app/teams/team-details.html
add game.html /www/app/game/game.html
...
+ update the side menu html to point to each new added views
- route parameters, navigate to the detail screen
.state("app.teams", {
url: "/teams",
views: {
"mainContent": {
templateUrl: "app/teams/teams.html"
}
}
})
.state("app.teams-detail", {
url: "/teams/:id", //:id route parameters, the /team/segment the segment is the id
views: {
"mainContent": {
templateUrl: "app/teams/teams-detail.html"
}
}
})
+ add teams.html
<ion-view>
<ion-content class="has-header">
<h1>team detail</h1>
</ion-content>
</ion-view>
+ team-detail.js
(function(){
"use strict";
angular.module("eliteApp").controller("teamDetailCtrl", ["$stateParams", teamDetailCtrl]);
function teamDetailCtrl($stateParams){
var vm = this;
console.log("$stateParams", $stateParams);
};
})();
- adding navigation animation
+ menu-layout.html
<ion-nav-view name="mainContent" animation="slide-left-right"></ion-nav-view>
- adding a back button for your app
<ion-nav-back-button class="button-clear button-icon icon ion-ios7-arrow-back"></ion-nav-back-button>
button-clear means no border
we could also use different icon for the back button
<ion-nav-back-button class="button-clear">
<i class="ion-arrow-left-c"></i>
</ion-nav-back-button>
- summary
# ionic components
- overview
+ lists
+ grid system
+ cards, attractive alternative for displaying information in your app
+ toggles and buttons
+ ionic popup, is a ionic services
- adding initial data
+ elite-schedule.net
+ grab some hard code data
+ copy the url ajax call address
+ use the data as development data
+ create a services api called eliteApp.js
(function(){
"use strict";
angular.module("eliteApp").factory("eliteApi", [eliteApi]);
function eliteApi(){
var leagues = JSON.parse(`...`);
var leagueDate = JSON.parse(...);
function getLeagues(){
}
function getLeagueData(){
}
return {
getLeagues: getLeagues,
getLeagueData: getLeagueData
};
}
}
+ add the service reference script tag in the index.html
+ add controller to leagues.html
<ion-view ng-controller="LeaguesCtrl">
<ion-content class="has-header">
<h1>Leagues</h1>
</ion-content>
</ion-view>
+ add LeaguesCtrl leagues-ctrl.js and inject the custom service
(function(){
"use strict";
angular.module("eliteApp").controller("LeaguesCtrl", ["eliteApi", LeaguesCtrl]);
function LeaguesCtrl(eliteApi){
var vm = this;
var leagues = eliteApi.getLeagues();
var leagueData = eliteApi.getLeagueData();
};
})();
- adding a basic ionic list
+ add a list
//leagues-ctrl.js
angular.module('eliteApp').controller('LeaguesCtrl', ['$state', 'eliteApi', LeaguesCtrl);
function LeaguesCtrl($state, eliteApi){
var vm = this;
var leagues = eliteApi.getLeagues();
vm.leagues = leagues;
vm.selectLeague = function(leagueId){
//TODO: select correct league
$state.go("app.teams");
}
}
//leagues.html
<ion-view ng-controller="LeaguesCtrl as vm">
<ion-content class="has-header">
<div class="list">
<a class="item item-icon-right" ng-repeat="leaguein vm.leagues" ng-click="vm.selectLeague(league.id)">
{{league.name}}
<i class="ion ion-chevron-right icon-accessory"/>
</>
</div>
</ion-content>
</ion-view>
+ add location screen
//location-ctrl.js
angular.module("eliteApp").controller("LocationsCtrl", ['eliteApi', LocationsCtrl]);
function LocationsCtrl(eliteApi){
var vm = this;
var data = eliteApi.getLeagueData();
vm.locations = data.locations;
}
//locations-html
<ion-view ng-controller="LocationsCtrl as vm">
<ion-content class="has-header">
<div class="item" ng-repeat="location in vm.locations">
<div class="item">
{{locationName}}
</div>
</div>
</ion-content>
</ion-view>
- list dividers for grouped data
# data and caching
# mapping
# customiing ionic
# ngCordova