-
Notifications
You must be signed in to change notification settings - Fork 32
/
03-templates.md.erb
227 lines (155 loc) · 11.2 KB
/
03-templates.md.erb
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
---
title: Templates
slug: templates
date: 0003/01/01
number: 3
points: 1
photoUrl: http://www.flickr.com/photos/73449134@N04/8194499092/
photoAuthor: Mike Lewinski
contents: Découvrir le langage de templating de Meteor, Spacebars.|Créer vos trois premiers templates.|Comment fonctionne les managers de Meteor.|Avoir un prototype de base fonctionnel avec des données statiques.
paragraphs: 46
---
Pour faciliter le développement dans Meteor, nous allons adopter une approche de l'extérieur vers l'intérieur. En d'autres termes, nous allons créer une simple page html/javascript, puis nous la rattacherons à la mécanique interne de l'application plus tard.
Ce qui veut dire que dans ce chapitre nous nous occuperons de ce qu'il se passe dans le répertoire `/client`.
Si vous ne l'avez pas déjà fait, créez un nouveau fichier appelé `main.html` dans votre répertoire `/client` et insérez le code suivant :
~~~html
<head>
<title>Microscope</title>
</head>
<body>
<div class="container">
<header class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<a class="navbar-brand" href="/">Microscope</a>
</div>
</header>
<div id="main">
{{> postsList}}
</div>
</div>
</body>
~~~
<%= caption "client/main.html" %>
Ce sera le template principal de notre application. Comme vous pouvez le voir c'est du langage HTML excepté pour la balise d'inclusion de template `{{> postsList}}`, qui est un point d'insertion pour le template `postsList` que nous verrons bientôt. Nous allons maintenant créer deux templates supplémentaires.
### Les templates Meteor
En son cœur, un site d'actualités social est composé d'articles organisés en listes, et c'est exactement de cette façon que nous allons organiser nos templates.
Créons un répertoire `/templates` dans `/client`. C'est ici que nous mettrons tous nos templates, et pour garder les choses en ordre nous allons également créer `/posts` dans `/templates` juste pour nos templates relatifs aux articles (posts).
<% note do %>
### Recherche de fichiers
Meteor est génial pour trouver les fichiers. Peu importe où vous mettez votre code dans le répertoire `/client`, Meteor le trouvera et le compilera proprement. Ce qui signifie que vous n'avez jamais besoin d'écrire manuellement des chemins d'inclusion (include) pour les fichiers javascript ou CSS.
Ça signifie également que vous pourriez aussi bien mettre tous vos fichiers dans le même répertoire, ou même tout votre code dans le même fichier. Mais sachant que Meteor compilera tout dans un seul fichier minifié de toute façon, nous garderons plutôt les choses bien organisées et utiliserons une structure de fichier la plus claire possible.
<% end %>
Nous sommes finalement prêt pour créer notre second template. Dans `client/templates/posts`, créez `posts_list.html` :
~~~html
<template name="postsList">
<div class="posts">
{{#each posts}}
{{> postItem}}
{{/each}}
</div>
</template>
~~~
<%= caption "client/templates/posts/posts_list.html" %>
Et `post_item.html` :
~~~html
<template name="postItem">
<div class="post">
<div class="post-content">
<h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
</div>
</div>
</template>
~~~
<%= caption "client/templates/posts/post_item.html" %>
Notez l'attribut `name="postsList"` de la balise template. C'est le nom qui sera utilisé par Meteor pour garder la trace de quel template va où (le nom du fichier n'est pas important).
Il est temps de présenter le système de templating de Meteor, **Spacebars**. Spacebars est du html simple, avec trois choses en plus : *inclusions* (parfois désignée sous le nom de "partials"), *expressions* et *block helpers*.
Les *Inclusions* utilisent la syntaxe `{{> templateName}}`, et indiquent simplement à Meteor de remplacer le champ par le template du même nom (dans notre cas `postItem`).
Les *Expressions* telles que `{{title}}` appellent une propriété de l'objet courant, ou retourne la valeur du template helper comme défini dans le template manager courant (plus d'information sur ce sujet plus tard).
Finalement, les *block helpers* sont des balises spéciales qui contrôlent le flux du template, tels que `{{#each}}...{{/each}}` ou `{{#if}}...{{/if}}`.
<% note do %>
### Aller plus loin
Vous pouvez consulter la [documentation Spacebars](https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md) si vous voulez en apprendre plus à propos de Spacebars.
<% end %>
Armé de cette connaissance, vous pouvez dorénavant comprendre ce qui se passe ici.
Premièrement, dans le template `postsList`, nous faisons des itérations sur un objet `posts` avec le block helper {{#each}}...{{/each}}. Ensuite, pour chaque itération nous allons inclure le template `postItem`.
D'où vient cet objet `posts` ? Bonne question. C'est un **template helper** ; vous pouvez vous l'imaginer comme un substitut à un contenu dynamique.
Le template `postItem` lui-même est assez simple. Il utilise trois expression : `{{url}}` et `{{title}}` retournent des propriétés du document, et `{{domain}}` appelle un template helper.
### Template Managers
Jusqu'à maintenant, nous avons travaillé avec Spacebars, qui est du HTML avec quelques balises parsemées dedans. Contrairement aux autres langages tel que PHP (ou même des pages HTML classiques, qui contiennent du javascript), Meteor garde les templates et leur logique séparés, et ces templates ne font rien par eux-même.
Afin d'exister, un template a besoin de **helpers**. Vous pouvez imaginer ces helpers comme un chef qui prend des ingrédients crus (vos données) et les prépare, avant de dresser une assiette (les templates) qu'il va donner à un serveur qui va ensuite vous les présenter.
En d'autres termes, pendant que le rôle du template est limité à l'affichage et aux itérations dans les variables, c'est celui des helpers qui fait en réalité le gros du travail en assignant une valeur à chaque variable.
<% note do %>
### Des contrôleurs ?
Il peut sembler tentant de penser aux fichiers contenant tous les helpers d'un template comme une sorte de "contrôleur" (controller). Mais cela peut être ambigu, puisque les "contrôleurs" (du moins du point de vue MVC) ont habituellement un rôle légèrement différent.
Nous avons donc décidé de ne pas utiliser cette terminologie et de nous référer simplement à "les helpers du template" ou à "la logique du template" lorsque nous parlons du code JavaScript associé au template.
<% end %>
Pour garder les choses simples, nous allons nommer les fichiers contenant les helpers comme le template, mais avec une extension **.js**. Créons donc directement `posts_list.js` dans `client/templates/posts` et commençons à construire notre premier helper :
~~~js
var postsData = [
{
title: 'Introducing Telescope',
url: 'http://sachagreif.com/introducing-telescope/'
},
{
title: 'Meteor',
url: 'http://meteor.com'
},
{
title: 'The Meteor Book',
url: 'http://themeteorbook.com'
}
];
Template.postsList.helpers({
posts: postsData
});
~~~
<%= caption "client/templates/posts/posts_list.js" %>
Si vous l'avez fait correctement, vous devriez avoir quelque choses de similaire à ça dans votre navigateur :
<%= screenshot "3-1", "Nos premiers templates avec données statiques" %>
Nous faisons deux choses ici. Premièrement, nous insérons des données prototype dans le tableau `postsData`. Ces données viendraient normalement de la base de données, mais comme nous n'avons pas encore vu comment faire (prochain chapitre) nous allons tricher en utilisant des données statiques.
Deuxièmement, nous utilisons la fonction `Template.myTemplate.helpers()` pour définir un template helper appelé `posts` qui retourne le tableau `postsData` défini auparavant.
Si vous vous souvenez, nous utilisons ce helper de `posts` dans notre template `postsList` :
~~~html
<template name="postsList">
<div class="posts page">
{{#each posts}}
{{> postItem}}
{{/each}}
</div>
</template>
~~~
<%= caption "client/templates/posts/posts_list.html" %>
Définir le helper de `posts` implique qu'il est maintenant disponible pour notre template, donc notre template sera capable de faire des itérations sur le tableau `postsData`, et d'envoyer chaque objet vers le template `postItem`.
<%= commit "3-1", "Avec le template basique de posts list et les données statiques." %>
### Le helper `domain`
De même, nous allons créer `post_item.js` pour y renseigner la logique du template de `postItem` :
~~~js
Template.postItem.helpers({
domain: function() {
var a = document.createElement('a');
a.href = this.url;
return a.hostname;
}
});
~~~
<%= caption "client/templates/posts/post_item.js" %>
Cette fois la valeur du helper `domain` n'est pas un tableau, mais une fonction anonyme. Ce modèle est bien plus commun (et plus utile) comparé à nos précédents exemples de données simples.
<%= screenshot "3-2", "Afficher les domaines pour chaque lien." %>
Le helper `domain` prend une URL et retourne son domaine via un peu de magie JavaScript. Mais où prend-il l'url dans un premier temps ?
Pour répondre à cette question nous avons besoin de revenir à notre template `posts_list.html`. Le block helper `{{#each}}` ne fais pas seulement des itérations sur notre tableau, il **insère également les valeurs dans `this` à l'intérieur du bloc de l'objet itéré**.
Ça signifie qu'à l'intérieur des deux balises `{{#each}}`, chaque article (post) est assigné à `this` successivement, et ça s'étend dans le manager du template inclus (`post_item.js`).
Nous comprenons maintenant pourquoi `this.url` retourne l'URL de l'article courant. De plus, si nous utilisons `{{title}}` et `{{url}}` dans notre template `post_item.html`, Meteor sait ce que veut dire `this.title` et `this.url` et retourne les valeurs correctes.
<%= commit "3-2", "Configurer un helper `domain` à partir du `postItem`." %>
<% note do %>
### Magie JavaScript
Bien que ce ne soit pas spécifique à Meteor, voici une petite explication de "Magie JavaScript". Premièrement, nous créons une balise ('a') avec ancre vide et la stockons en mémoire.
Nous modifions ensuite l'attribut `href` pour être égal à l'URL de l'article courant (comme nous venons de le voir, l'objet en cours de traitement se trouve dans un helper `this`).
Finalement, nous prenons avantage de la propriété spéciale `hostname` de l'élément `a` pour récupérer le nom de domaine du lien sans le reste de l'URL.
<% end %>
Si vous avez suivi correctement, vous devriez voir une liste d'articles dans votre navigateur. C'est juste une liste de données statiques, donc ça ne tient pas compte des avantages des fonctionnalités temps réel de Meteor. Nous verrons comment changer ça dans le chapitre suivant !
<% note do %>
### Hot Code Reload
Vous avez pu noter que vous n'aviez même pas eu besoin de recharger manuellement la fenêtre de notre navigateur quand vous avez modifié vos fichiers.
C'est parce que Meteor traque tous les fichiers dans le répertoire de votre projet, et rafraîchit automatiquement le navigateur quand il détecte une modification sur l'un d'entre eux.
Le Hot Code Reload de Meteor est très intelligent, en préservant même l'état de votre application entre deux rafraîchissements !
<% end %>