-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
828 lines (750 loc) · 44.4 KB
/
Copy pathindex.html
File metadata and controls
828 lines (750 loc) · 44.4 KB
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
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Intro à Angular</title>
<meta name="description" content="Une présentation d'Angular en français destinée à un public débutant en javascript et se concentrant sur l'aspect 'pratique'">
<meta name="author" content="Pierric Cistac">
<meta name="keywords" content="anuglar, angularjs, français, présentation, introduction, javascript">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
<link rel="stylesheet" href="css/reveal.css">
<link rel="stylesheet" href="css/custom.css">
<link rel="stylesheet" href="css/theme/night.css" id="theme">
<!--<link rel="stylesheet" href="css/theme/beige.css" id="theme">-->
<!-- Code syntax highlighting -->
<link rel="stylesheet" href="lib/css/railscasts.css">
<!--<link rel="stylesheet" href="lib/css/zenburn.css">-->
<!-- Printing and PDF exports -->
<script>
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
</script>
<!--[if lt IE 9]>
<script src="lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<small id="step" style="text-transform: uppercase; padding: 15px;"></small>
<!-- Any section element inside of this container is displayed as a slide -->
<div class="slides">
<section title>
<h1>Welcome !</h1>
<blockquote>I have nothing to offer but blood, toil, tears, and sweat.</blockquote>
<p class="fragment roll-in">W. Churchill, 13 mai 1940</p>
<p><a href="https://twitter.com/pierrci" style="font-size: smaller;">@pierrci</a></p>
</section>
<section title>
<h2>Evolution of Web Apps</h2>
<a href="https://evolution-of-apps.firebaseapp.com">https://evolution-of-apps.firebaseapp.com</a>
<p>David East - Firebase & Angular team</p>
</section>
<section>
<section title="AngularJS > Introduction">
<h2>So... Angular !</h2>
<img class="stretch" src="img/trends.png" alt="">
</section>
<section title="AngularJS > Introduction">
<h2>En 4 mots clés</h2>
<ul>
<li>Framework Javascript</li>
<li>SPA</li>
<li><a href="https://plus.google.com/+AngularJS/posts/aZNVhj355G2" title="Model-View-Whatever par Igor Minar">MVW</a> (o_O)</li>
<li>Google</li>
</ul>
<br><br>
<p style="font-size: smaller;">Au sujet de MVC / MVVM :</p>
<div style="font-size: initial;">
<a href="http://www.docdoku.com/blog/2015/02/17/architecturer-ses-applications-js-pattern-mvvm/">http://www.docdoku.com/blog/2015/02/17/architecturer-ses-applications-js-pattern-mvvm/</a>
<a href="http://stackoverflow.com/questions/667781/what-is-the-difference-between-mvc-and-mvvm/">http://stackoverflow.com/questions/667781/what-is-the-difference-between-mvc-and-mvvm/</a>
</div>
</section>
<section title="AngularJS > Introduction">
<p>Version 1.X : <a href="https://angularjs.org/">https://angularjs.org/</a></p>
<p>Version 2.X et + : <a href="https://angular.io/">https://angular.io/</a></p>
<div class="fragment roll-in">
<blockquote>AngularJS however is not an example of developers maintaining backwards compatibility. It takes pleasure in starting over. In fact, you can just about rip up your old Angular apps now. It’s for your own good.</blockquote>
<p style="font-size: initial;"><a href="https://twitter.com/edwardcgordon">@EdwardCGordon</a> - <a href="http://bit.ly/1QJbGBD">packtpub.com</a></p>
</div>
<p class="fragment roll-in">La classe non ?</p>
</section>
<section title="AngularJS">
<h2>Ready for roller coasters ?</h2>
<img src="http://www.bennadel.com/resources/uploads/2013/feelings_about_angularjs_over_time.png" alt="">
</section>
</section>
<section>
<section title="AngularJs > Introduction">
<h3>Sans Angular...</h3>
<pre style="font-size: initial !important;"><code data-trim class="hljs xml javascript">
<html>
<head>
<title>Index</title>
</head>
<body>
Name: <input type="text" id="myInputBox">
Hello <span id="nameSpan"></span> !
<script>
var inputElem = document.getElementById("myInputBox");
inputElem.addEventListener('keyup', function() {
var text = inputElem.value;
document.getElementById("nameSpan").innerHTML = text;
});
</script>
</body>
</html>
</code></pre>
<br>
<div class="fragment roll-in">
<h3>Avec Angular !</h3>
<pre style="font-size: initial !important;"><code data-trim class="hljs xml javascript">
<html>
<head>
<title>Index</title>
<script src="../angular.min.js"></script>
</head>
<body ng-app>
Name: <input type="text" ng-model="nameModel">
Hello {{ nameModel }} !
</body>
</html>
</code></pre>
</div>
</section>
<section title="AngularJs > Introduction">
<pre><code data-trim class="hljs xml javascript">
<html>
<head>
<title>Index</title>
<script src="../angular.min.js"></script>
</head>
<body ng-app>
Name: <input type="text" ng-model="nameModel">
Hello {{ nameModel }} !
</body>
</html>
</code></pre>
<ul>
<li class="fragment roll-in" style="margin-bottom: 10px;">
<span class="keyword">ng-app</span> : directive de bootstrap ("démarrage"), indique à angular où se situe l'application dans la page HTML.
</li>
<li class="fragment roll-in" style="margin-bottom: 10px;">
<span class="keyword">ng-model</span> : directive qui associe ("bind") la valeur d'un champ à une variable.
</li>
<li class="fragment roll-in" style="margin-bottom: 10px;">
<span class="keyword">{{ nameModel }}</span> : expression angular, elle est évaluée par angular et son résultat est inséré dans la page.
</li>
</ul>
</section>
<section title="AngularJs > Introduction">
<h2><demo /></h2>
</section>
</section>
<section>
<section title="AngularJs > Modules">
<h2>Les modules</h2>
<pre><code data-trim class="hljs xml"><body ng-app="monApplicationAngular"></code></pre>
<p>La valeur passée à <span class="keyword">ngApp</span> est le nom du <span class="keyword">module</span> principal de l'application.</p>
<p>Un module contient les composants de notre application : controllers, directives, services, filtres...</p>
</section>
<section title="AngularJs > Modules">
<p>Pour pouvoir ajouter ces composants, il faut <span class="keyword">déclarer le module</span> côté javascript :</p>
<pre><code data-trim class="hljs javascript">
var app = angular.module("monApplicationAngular", [
"ngRoute",
"ngResource",
//...
]);
// Dans sa forme la plus simple :
// var app = angular.module("monApplicationAngular", []);
</code></pre>
<div class="fragment roll-in" style="margin-top: 50px;">
<p>Une fois déclaré, on peut l'appeler et lier des composants :</p>
<pre><code data-trim class="hljs javascript">
angular
.module("monApplicationAngular")
.directive("uneDirective", maDirective);
function maDirective() {
//...
}
</code></pre>
</div>
</section>
</section>
<section title="AngularJs > Expressions">
<h2>Les expressions Angular</h2>
<pre><code data-trim class="hljs xml">
<body ng-app="monApplicationAngular">
1 + 2 = {{ 1 + 2 }}
Nom de l'utilisateur : {{ user.name }}
Loisir n° 3 de l'utilisateur : {{ user.loisirs[2] }}
</body>
</code></pre>
<p class="fragment roll-in">Comment et où déclarer <span class="keyword">user</span> ?</p>
<p class="fragment roll-in">=> Dans un <span class="keyword">controller</span></p>
</section>
<section>
<section title="AngularJs > Controllers">
<h2>Les controllers</h2>
<p>C'est là que l'on interagit avec les données de la vue</p>
<pre><code data-trim class="hjs javascript">
angular
.module("monApplicationAngular")
.controller("HomeController", HomeController);
function HomeController() {
var vm = this; // vm pour ViewModel
vm.user = {
name: "Pierric",
loisirs: ['ski', 'lecture', 'musique']
}
}
</code></pre>
<p>On "<span class="keyword">bind</span>" les méthodes et variables qui nous intéressent au <span class="keyword">this</span> de HomeController</p>
</section>
<section title="AngularJs > Controllers">
<p>Il faut penser à déclarer le controller dans le HTML grâce à la directive <span class="keyword">ngController</span></p>
<pre><code data-trim class="hljs xml">
<body ng-app="monApplicationAngular">
<div ng-controller="HomeController as home">
Nom de l'utilisateur : {{ home.user.name }}
Loisir n° 3 de l'utilisateur : {{ home.user.loisirs[2] }}
</div>
</body>
</code></pre>
<div class="fragment roll-in">
<p>On utilise la syntaxe <span class="keyword">controllerAs</span>, indissociable du binding à l'instance du controller (le <span class="keyword">this</span> côté JS), en spécifiant un alias pour notre controller : <span class="keyword">home</span> (arbitraire)</p>
<div style="font-size: smaller; margin-top: 40px;">
<a href="http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/">Do You Like Your Angular Controllers with or without Sugar?</a> - <a href="https://twitter.com/John_Papa" style="font-style: italic;">@John_Papa</a>
</div>
</div>
</section>
<section title="AngularJs > $scope">
<h3>$scope</h3>
<p>Dans le javascript, on aurait pu aussi lier le modèle à <span class="keyword">$scope</span> au lieu de <span class="keyword">this</span>, sans utiliser la syntaxe <span class="keyword">controllerAs</span> :</p>
<pre><code data-trim class="hljs javascript">
function HomeController($scope) {
$scope.user = {
name: "Pierric",
loisirs: ['ski', 'lecture', 'musique']
}
}
</code></pre>
<p>Côté HTML :</p>
<pre><code data-trim class="hljs xml">
<div ng-controller="HomeController">
Nom de l'utilisateur : {{ user.name }}
Loisir n° 3 de l'utilisateur : {{ user.loisirs[2] }}
</div>
</code></pre>
</section>
<section title="AngularJs > $scope">
<h3>Les limites de $scope</h3>
<pre><code data-trim class="hljs xml">
<div ng-controller="MainCtrl">
{{ title }}
<div ng-controller="AnotherCtrl">
{{ title }}
<div ng-controller="YetAnotherCtrl">
{{ title }}
</div>
</div>
</div>
</code></pre>
<div class="fragment roll-in">
<p>
On préfèrera limiter <span class="keyword">$scope</span> à l'utilisation de méthodes qui en dépendent telles que <span class="keyword">$watch</span>, <span class="keyword">$on</span> ou <span class="keyword">$broadcast</span>
</p>
<pre><code data-trim class="hljs javascript">
function HomeController($scope) {
var vm = this;
vm.username = "Pierric";
$scope.$on('someEventFiredFromElsewhere', function (event, data) {
// do something!
});
}
</code></pre>
<p style="font-size: smaller;"><a href="http://toddmotto.com/digging-into-angulars-controller-as-syntax/">Digging into Angular’s “Controller as” syntax</a> - <a href="https://twitter.com/toddmotto" style="font-style: italic;">@toddmotto</a></p>
</div>
</section>
<section title="AngularJs > $scope">
<h2><demo /></h2>
</section>
</section>
<section>
<section title="AngularJs > Directives">
<h2>Les directives</h2>
<p>ngApp, ngController, ngModel, ... sont des directives</p>
<p>Ce sont des marqueurs positionnés sur des <span class="keyword">éléments du DOM</span> qui indiquent à angular quel comportement attacher à un élément et/ou quelle transformation y apporter</p>
<p>De nombreuses directives sont intégrées nativement : <a href="https://docs.angularjs.org/api/ng/directive" title="Liste des directives de base">https://docs.angularjs.org/api/ng/directive</a></p>
</section>
<section title="AngularJs > Directives">
<h3>Directives de template</h3>
<ul>
<li>
<a href="https://docs.angularjs.org/api/ng/directive/ngIf">ngIf</a> : insère ou pas un élément dans le DOM en fonction de la valeur de l'attribut
<pre><code class="hljs xml"><div ng-if="vm.isVisible">I'm gonna disappear</div></code></pre>
</li>
<li class="fragment roll-in">
<a href="https://docs.angularjs.org/api/ng/directive/ngRepeat">ngRepeat</a> : permet de parcourir les éléments d'un tableau et d'afficher leur valeur
<pre><code class="hljs xml"><div ng-repeat="user in vm.users">{{ user.name }}</div></code></pre>
</li>
<li class="fragment roll-in">
<a href="https://docs.angularjs.org/api/ng/directive/ngSwitch">ngSwitch</a> : modifie le contenu d'un élément suivant la valeur d'une expression
<pre><code data-trim class="hljs xml">
<div ng-switch="vm.isEditable">
<div ng-switch-when="false">Name : {{ vm.user.name }}</div>
<div ng-switch-when="true"><input type="text" ng-model="vm.user.name"/></div>
</div>
</code></pre>
</li>
</ul>
</section>
<section title="AngularJs > Directives">
<h3>Directives de style</h3>
<ul>
<li>
<a href="https://docs.angularjs.org/api/ng/directive/ngShow">ngShow</a> / <a href="https://docs.angularjs.org/api/ng/directive/ngHide">ngHide</a> : modifie la visibilité d'un élément du DOM suivant la valeur de l'expression en paramètre
<pre><code data-trim class="hljs xml">
<div ng-hide="vm.hidden">Hello hide</div>
<div ng-show="vm.hidden">Hello show</div>
</code></pre>
</li>
<li class="fragment roll-in">
<a href="https://docs.angularjs.org/api/ng/directive/ngClass">ngClass</a> : conditionne dynamiquement les classes d'un élément du DOM suivant la valeur d'expressions
<pre><code class="hljs xml"><p ng-class="{bold: vm.important, red: vm.error}">Map Syntax Example</p></code></pre>
</li>
<li class="fragment roll-in">
<a href="https://docs.angularjs.org/api/ng/directive/ngDisabled">ngDisabled</a> : modifie la valeur de l'attribut disabled suivant l'expression spécifiée
<pre><code class="hljs xml"><button ng-disabled="vm.isDisabled">Disabled</button></code></pre>
</li>
</ul>
</section>
<section title="AngularJs > Directives">
<h3>Directives d'action</h3>
<ul>
<li>
<a href="https://docs.angularjs.org/api/ng/directive/ngClick">ngClick</a> : permet d'appeler une fonction ou d'évaluer une expression lors d'un clic sur l'élément
<pre><code data-trim class="hljs xml">
<div ng-click="vm.click()">Click me!</div>
<button ng-click="vm.count = vm.count + 1" ng-init="vm.count = 0">Increment</button>
</code></pre>
</li>
<li class="fragment roll-in">
<a href="https://docs.angularjs.org/api/ng/directive/ngKeydown">ngKeydown</a> / <a href="https://docs.angularjs.org/api/ng/directive/ngKeyup">ngKeyup</a> : associe des actions à des événements claviers
<pre><code class="hljs xml"><input type="text" ng-keydown="vm.down()" ng-keyup="vm.up()"></code></pre>
</li>
<li class="fragment roll-in">
<a href="https://docs.angularjs.org/api/ng/directive/ngSubmit">ngSubmit</a> : spécifie l'action à effectuer pour l'envoi d'un formulaire. Ne pas combiner avec ngClick !
<pre><code data-trim class="hljs xml">
<form ng-submit="vm.submit()" ng-controller="SimpleFormController as vm">
<input type="text" ng-model="vm.text" name="text" />
<input type="submit" id="submit" value="Submit" />
</form>
</code></pre>
</li>
</ul>
</section>
<section title="AngularJs > Directives">
<h2><demo /></h2>
</section>
</section>
<section>
<section title="AngularJs > Filtres">
<h2>Les Filtres</h2>
<p>Les filtres permettent de formatter et de... filtrer (!) les expressions auxquelles ils sont appliqués :</p>
<pre><code data-trim class="hljs xml">
{{ expression | filter }}
{{ expression | filter1 | filter2 }} <!-- Ils peuvent être combinés -->
{{ expression | filter:arg1:arg2 }} <!-- On peut passer des arguments -->
</code></pre>
<div class="fragment roll-in">
<p>Exemples :</p>
<pre><code data-trim class="hljs xml">
{{ 'Mon texte' | uppercase }}
{{ '25.465' | number:2 | currency:'$'}} <!-- seulement 2 décimales -->
</code></pre>
</div>
<div class="fragment roll-in" style="margin-top: 60px;">
<p>Liste des filtres natifs : <br>
<a href="https://docs.angularjs.org/api/ng/filter">https://docs.angularjs.org/api/ng/filter</a>
</p>
</div>
</section>
<section title="AngularJs > Filtres">
<p>Soit le tableau suivant dans un controller:</p>
<pre><code data-trim class="hljs javascript">
var jb = {name: 'JB', gender: 'male'},
cyril = {name: 'Cyril', gender: 'male', birth: '1990-11-25'},
agnes = {name: 'Agnes', gender: 'female', birth: '1991-07-22'},
cedric = {name: 'Cedric', gender: 'male', birth: '1992-02-22'};
vm.ninjas = [jb, cyril, agnes, cedric];
</code></pre>
<p>Avec le HTML suivant :</p>
<pre><code data-trim class="hljs xml">
<p>{{ vm.ninjas | orderBy:'name' | limitTo:2 }}</p>
<div ng-repeat="ninja in vm.ninjas">
{{ ninja.birth | date:'yyyy' }}
</div>
</code></pre>
<p>On obtiendra :</p>
<pre class="fragment roll-in"><code data-trim class="hljs javascript">
[
{"name":"Agnes","gender":"female","birth":"1990-07-22"},
{"name":"Cedric","gender":"male","birth":"1990-02-22"}
]
1990
1991
1992
</code></pre>
</section>
<section title="AngularJs > Filtres">
<h3>Le filtre Filter</h3>
<p><span class="keyword">filter</span> permet d'appliquer un filtre personnalisé aux éléments d'un tableau</p>
<pre><code data-trim class="hljs xml">
<input type="text" ng-model="searchText">
<table id="searchTextResults">
<tr><th>Name</th><th>Birth date</th></tr>
<tr ng-repeat="ninja in vm.ninjas | filter:searchText">
<td>{{ ninja.name }}</td>
<td>{{ ninja.birth | date:'dd/MM/yyyy' }}</td>
</tr>
</table>
</code></pre>
<pre><code data-trim class="hljs xml">
<label>Any: <input ng-model="search.$"></label><br>
<label>Name only <input ng-model="search.name"></label><br>
<label>Gender only <input ng-model="search.gender"></label><br>
<label>Equality <input type="checkbox" ng-model="strict"></label><br>
<table id="searchObjResults">
<tr><th>Name</th><th>Gender</th></tr>
<tr ng-repeat="ninja in vm.ninjas | filter:search:strict">
<td>{{ ninja.name }}</td>
<td>{{ ninja.gender }}</td>
</tr>
</table>
</code></pre>
</section>
<section title="AngularJs > Filtres">
<h2><demo /></h2>
</section>
</section>
<section title="AngularJs > Exercices">
<h2>Time for practice !</h2>
<p><a href="http://www.codecademy.com/fr/learn/learn-angularjs">Learn AngularJS | Codecademy</a> - Unit 1</p>
<p><a href="http://campus.codeschool.com/courses/shaping-up-with-angular-js/">Shaping up with AngularJS | CodeSchool</a> - Levels 1 / 2 / 3</p>
</section>
<section>
<section title="AngularJs > Directives custom">
<h2>Créer ses directives</h2>
<p>L'avenir du web est aux <a href="http://webcomponents.org/">Web Components</a> : découpage des fonctionnalités en modules réutilisables indépendamment.</p>
<p>Les directives sont un avant-goût et permettent d'implémenter une partie de cette logique.</p>
<br>
<div class="fragment roll-in">
<pre><code data-trim class="hljs xml">
<div>
<h1 class="title">{{ book.title }}</h1>
<h2 class="author">{{ book.author }}</h2>
<div class="extract">{{ book.extract }}</div>
</div>
</code></pre>
<p>peut devenir :</p>
<pre><code data-trim class="hljs xml">
<book-details data-book="main.book"></book-details>
</code></pre>
</div>
</section>
<section title="AngularJs > Directives custom">
<p>Fichier <i>bookDetails.directive.js</i> :</p>
<pre><code data-trim class="hljs javascript">
angular.module('myApp')
.directive('bookDetails', bookDetails); // camelCase côté JS !
function bookDetails() {
return { // Une directive retourne un objet de "configuration"
restrict: 'E', // La directive doit être appelée sous forme d'élément
scope: { // On crée un nouveau scope isolé propre à la directive
book: '=' // On récupère l'objet passé à l'attribut correspondant
},
templateUrl: 'bookDetails.tpl.html', // Indique où aller chercher le HTML
};
}
</code></pre>
<p>Fichier <i>bookDetails.tpl.html</i> :</p>
<pre><code data-trim class="hljs xml">
<div>
<h1 class="title">{{ book.title }}</h1>
<h2 class="author">{{ book.author }}</h2>
<div class="extract">{{ book.extract }}</div>
</div>
</code></pre>
</section>
<section title="AngularJs > Directives custom">
<ul>
<li style="margin-bottom: 10px;">
<span class="keyword">restrict</span> : indique comment doit être appelée la directive dans le HTML - A pour attribut, E pour élement et C pour classe CSS. On peut les combiner, par exemple '<span class="keyword">AEC</span>'.
</li>
<li style="margin-bottom: 10px;">
<span class="keyword">scope</span> : crée un scope isolé pour la directive. On récupère les éléments du scope englobant via les attributs. '<span class="keyword">@</span>' pour passer une valeur (chaîne de caractères), '<span class="keyword">=</span>' pour du <span class="keyword">two-way binding</span> sur un objet.
</li>
</ul>
</section>
<section title="AngularJs > Directives custom">
<ul>
<li style="margin-bottom: 10px;">
<span class="keyword">controller</span> : une directive peut avoir son propre controller.
</li>
<li style="margin-bottom: 10px;">
<span class="keyword">controllerAs</span> : permet de spécifier un alias pour le controller, comme avec <i>ng-controller = ... as ...</i>
</li>
<li>
<span class="keyword">bindToController</span> : indissociable de <i>ControllerAs</i>, lie les propriétés à l'instance du controller plutôt qu'au scope.
<pre><code data-trim class="hljs javascript">
...
controller: function () {
var vm = this;
vm.selectBook = function () { ... }
},
controllerAs: 'bookDetails',
bindToController: true
...
</code></pre>
</li>
</ul>
<p style="font-size: smaller;">
<a href="https://docs.angularjs.org/api/ng/service/$compile">https://docs.angularjs.org/api/ng/service/$compile</a>
</p>
</section>
<section title="AngularJs > Directives custom">
<h2><demo /></h2>
</section>
</section>
<section title="AngularJs > Exercices">
<h2>Time for practice !</h2>
<p><a href="http://www.codecademy.com/fr/learn/learn-angularjs">Learn AngularJS | Codecademy</a> - Unit 2</p>
<p><a href="http://campus.codeschool.com/courses/shaping-up-with-angular-js/">Shaping up with AngularJS | CodeSchool</a> - Level 4</p>
</section>
<section>
<section title="AngularJs > Services">
<h2>Les services</h2>
<p>Les services sont des objets dans lesquels on met le code correspondant à <span class="keyword">la logique métier</span> de l'application. Ils sont aussi utilisés pour organiser <span class="keyword">le code partagé</span> de l'application.</p>
<p style="margin-top: 60px; text-align: left;">Les services sont :</p>
<ul>
<li><span class="keyword">Lazy</span> : paresseux, ils ne sont instanciés que lorsque l'application en a besoin</li>
<li><span class="keyword">Singletons</span> : ils seront instanciés <span class="keyword">une seule fois</span> et cette instance est ensuite utilisée partout</li>
</ul>
</section>
<section title="AngularJs > Services">
<h3>Les services natifs</h3>
<ul>
<li>
<a href="https://docs.angularjs.org/api/ng/service/$http">$http</a> : permet de faire simplement des <span class="keyword">requêtes AJAX</span>. Renvoie une <span class="keyword">promise</span> avec une callback de succès et une autre d'échec.
<pre><code data-trim class="hljs javascript">
$http({method: 'GET', url: '/serverUrl'})
.success(function(data, status, headers, config){ ... })
.error(function(data, status, headers, config){ ... });
</code></pre>
</li>
<li class="fragment roll-in">
<a href="https://docs.angularjs.org/api/ngResource/service/$resource">$resource</a> : service plus haut niveau, utilisé pour interagir avec des <a href="http://www.wikiwand.com/fr/Representational_State_Transfer" title="Wikipedia !">API REST</a>. Nécessite le module <span class="keyword">ngResource.</span>
<pre><code data-trim class="hljs javascript">
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'}, 'delete': {method:'DELETE'} };
</code></pre>
<pre><code data-trim class="hljs javascript">
var Poneys = $resource('/races/:raceId/poneys/:poneyId',
{ raceId: 24, poneyId: '@id'}, { run: { method: 'PUT' }});
var fury = Poneys.save({ name: 'Fury Red'});
</code></pre>
</li>
</ul>
</section>
<section title="AngularJs > Services">
<ul>
<li>
<a href="https://docs.angularjs.org/api/ng/service/$location">$location</a> : rend accessible l'URL de la page actuelle à notre application et expose plusieurs méthodes.
<pre><code data-trim class="hljs javascript">
// avec l'url http://example.com/#/some/path?foo=bar&baz=xoxo
var path = $location.path(); // => "/some/path"
var searchObject = $location.search(); // => {foo: 'bar', baz: 'xoxo'}
</code></pre>
</li>
<li class="fragment roll-in">
<a href="https://docs.angularjs.org/api/ng/service/$timeout">$timeout</a> / <a href="https://docs.angularjs.org/api/ng/service/$interval">$interval</a> : permettent de wrapper setTimeout et setInterval dans le <span class="keyword">cycle de vie</span> de l'application angular.
<pre><code data-trim class="hljs javascript">
var delayedFn = $timeout(function(){ ... }, 1000) // Après 1 seconde.
var recurringFn = $interval(function(){ ... }, 1000, 0) // Chaque seconde.
</code></pre>
</li>
</ul>
<p class="fragment roll-in">Autres wrappers ($window, $document...) et services natifs : <a href="https://docs.angularjs.org/api/ng/service">https://docs.angularjs.org/api/ng/service</a></p>
</section>
</section>
<section>
<section title="AngularJs > Promises">
<h2>Les Promises</h2>
<p>
Nouveauté de l'EcmaScript 6, implémentée via le service <span class="keyword">$q</span>.<br>
Utilisée lors de <span class="keyword">traitements asynchrones</span> tels que les requêtes AJAX avec $http.
</p>
<p>Une promise peut avoir deux résultats : <span class="keyword">succès</span> ou <span class="keyword">échec</span>.</p>
<pre><code data-trim class="hljs javascript">
$http.get(...)
.then(function(data){
// succès, promise résolue
}, function(error){
// erreur, promise rejetée
});
</code></pre>
</section>
<section title="AngularJs > Promises">
<h3 style="text-transform: lowercase;">$q</h3>
<pre><code data-trim class="hljs javascript" style="max-height: 100%;">
function asyncGreet(name) {
var deferred = $q.defer(); // On crée un objet deferred
$timeout(function() { // Ici on crée artificiellement un délai
deferred.notify('About to greet ' + name + '.');
if (okToGreet(name)) {
deferred.resolve('Hello, ' + name + '!'); // succès
} else {
deferred.reject('Greeting ' + name + ' is not allowed.'); // échec
}
}, 1000);
return deferred.promise; // On retourne la promise de deferred
}
var promise = asyncGreet('Robin Hood'); // La fonction retourne une promise
promise.then(function(greeting) {
alert('Success: ' + greeting); // En cas de succès
}, function(reason) {
alert('Failed: ' + reason); // En cas d'échec
}, function(update) {
alert('Got notification: ' + update); // Indication de progression
});
</code></pre>
</section>
<section title="AngularJs > Promises">
<h2><demo /></h2>
</section>
</section>
<section title="AngularJs > Dependency Injection">
<h2>L'injection de dépendance (DI)</h2>
<p>Pour pouvoir utiliser un composant dans un autre, angular utilise un système d'injection de dépendance.</p>
<pre><code data-trim class="hljs javascript">
function HomeController($scope, $http) { ... }
// function HomeController($http, $scope) { ... } // équivalent !
</code></pre>
<pre><code class="hljs javascript">HomeController.toString(); // "function HomeController($scope, $http) { ... }"</code></pre>
<p>Pour éviter les problèmes en cas de minification du javascript, on "annote" les composants :</p>
<pre><code data-trim class="hljs javascript">
HomeController.$inject = ['$scope', '$http'];
function HomeController($scope, $http) { ... } // Il vaut mieux garder le même ordre...
</code></pre>
</section>
<section title="AngularJs > Exercices">
<h2>Time for practice !</h2>
<p><a href="http://www.codecademy.com/fr/learn/learn-angularjs">Learn AngularJS | Codecademy</a> - Unit 3</p>
<p><a href="http://campus.codeschool.com/courses/shaping-up-with-angular-js/">Shaping up with AngularJS | CodeSchool</a> - Level 5</p>
</section>
<section>
<section title="AngularJs > Routes">
<h2>ngRoute</h2>
<p>
ngRoute est le module angular de base chargé du <span class="keyword">routage</span>. <br>
Il est composé d'une directive <span class="keyword">ngView</span>, d'un <span class="keyword">$routeProvider</span> et de 2 services : <span class="keyword">$route</span> et <span class="keyword">$routeParams</span>.
</p>
<div class="fragment roll-in">
<p><span class="keyword">ngView</span> indique quelle partie de la SPA sera mise à jour :</p>
<pre><code class="hljs xml"><div ng-view></div></code></pre>
</div>
</section>
<section title="AngularJs > Routes">
<h3>$routeProvider</h3>
<p>$routeProvider permet de déterminer les routes de l'application et de faire le lien entre URL, template et controller.</p>
<pre><code data-trim class="hljs javascript">
angular
.module("monApplicationAngular")
.config(configure);
function configure($routeProvider) {
$routeProvider
.when('/races/:raceId?', { // raceId est un paramètre facultatif
templateUrl: 'races.html',
controller: 'RacesController' // Remplace ng-controller="..."
})
.when('/', {
templateUrl: 'poneys.html',
controller: 'PoneysController'
controllerAs: 'poneys' // Remplace ng-controller="... as ..."
})
.otherwise('/'); // Si l'url ne correspond pas, redirection
}
</code></pre>
</section>
<section title="AngularJs > Routes">
<h3>$routeParams</h3>
<p>Service permettant de déterminer les paramètres de la route. Combinaison de $location.search() et $location.path().</p>
<pre><code data-trim class="hljs javascript">
// Avec une url = http://www.example.com/#/races/13?poney=10
$routeParams ==> { raceId: "13", poney: "10" }
</code></pre>
</section>
</section>
<section title="AngularJs > Exercices">
<h2>Time for practice !</h2>
<p><a href="http://www.codecademy.com/fr/learn/learn-angularjs">Learn AngularJS | Codecademy</a> - Units 4 / 5</p>
</section>
<section title="AngularJs > Ressources">
<h2>Ressources utiles</h2>
<ul>
<li><a href="https://docs.angularjs.org/guide">Le guide du développeur</a></li>
<li><a href="https://books.ninja-squad.com/angularjs">Devenez un ninja avec AngularJS</a> - ebook - [fr]</li>
<li><a href="https://www.video2brain.com/fr/angularjs">2 formations vidéos</a> chez <i>video2brain</i> - [fr]</li>
<li><a href="http://www.grafikart.fr/formations/angularjs">Formation vidéo AngularJS</a> par <a href="https://twitter.com/grafikart_fr" style="font-style: italic;">@grafikart_fr</a> - [fr]</li>
<li><a href="https://github.com/johnpapa/angular-styleguide/blob/master/a1/i18n/fr-FR.md">Le guide de style Angular</a> par <a href="https://twitter.com/john_papa" style="font-style: italic;">@john_papa</a> - [fr]</li>
<br>
<li><a href="https://developer.mozilla.org/fr/docs/Web/JavaScript/Une_r%C3%A9introduction_%C3%A0_JavaScript">Une réintroduction à Javascript</a> sur <i>MDN</i> - [fr]</li>
</ul>
</section>
</div>
</div>
<script src="lib/js/head.min.js"></script>
<script src="js/reveal.min.js"></script>
<script>
// Full list of configuration options available at:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
transition: 'convex', // none/fade/slide/convex/concave/zoom
// Optional reveal.js plugins
dependencies: [
{ src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/highlight/highlight.js', async: true, condition: function() { return !!document.querySelector( 'pre code' ); }, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: 'plugin/zoom-js/zoom.js', async: true },
{ src: 'plugin/notes/notes.js', async: true }
]
});
function signPostEra( event ) {
var title = event.currentSlide.attributes.title;
if(title) {
var era = document.getElementById('step');
era.innerText = title.value;
}
}
Reveal.addEventListener( 'ready', function( event ) {
signPostEra( event );
});
Reveal.addEventListener( 'slidechanged', function( event ) {
signPostEra( event );
});
</script>
</body>
</html>