-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtutorial-using-substitutions-with-montagejs.html
300 lines (227 loc) · 14.7 KB
/
tutorial-using-substitutions-with-montagejs.html
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
---
layout: docs
title: Using Substitutions
this-page: tutorial-using-substitutions-with-montagejs
---
<h1 id="building-a-simple-reddit-client-with-montagejs">Using Substitutions to Switch Components in MontageJS</h1>
<p>Many web applications need a way to change out a component with another. For example, imagine you wanted to make an app that had multiple pages. Normally, you would have to make each page a separate html file. This means that whenever the user wants to go to a different section of the website, they have to load a new page. With Montage, you can store a section of your app as a component, and then switch between each component without having to load a page. This is done through the prebuilt Substitution component.</p>
<p>Substitutions are useful for swapping out which modules are displayed in a specific space. In this tutorial we’ll cover a simple example by creating radio buttons that will be used to select different text modules to be displayed. The end result will also feature the temperature converter from the first tutorial. With substitutions, you can easily embed an existing component into another app. The end result should look something like this:</p>
<img src="{{site.baseurl}}/images/docs/tutorials/using-substitutions/tutorial-substitution-final.jpg" alt="The end result"></img>
<h1>Creating the Buttons</h1>
<p>Let’s start by creating the radio buttons. In order for the buttons to make selections we’ll need to include a radio button controller in our declaration:</p>
<pre id="code1"><code>"owner": {
"properties": {
"element": {"#": "main"}
}
},
"radioButtonController": {
"prototype": "montage/core/radio-button-controller"
}</code></pre>
<p>The controller does not need to be added in html because it doesn’t actually exist on the page, only its buttons do.</p>
<p>Next we’ll add the actual radio buttons using the component provided in Montage:</p>
<p>1. Add three buttons to the markup. Set each button's type to <i>radio</i>:</p>
<div id="code2">
<pre><code><input type="radio" data-montage-id="button1">
<input type="radio" data-montage-id="button2">
<input type="radio" data-montage-id="button3"></code></pre>
<p>2. Now add each button to the declaration:</p>
<pre><code>"button1": {
"prototype": "digit/ui/radio-button.reel",
"properties": {
"element": {"#": "button1"},
"checked": true,
"enabled": true,
"radioButtonController": {"@": "radioButtonController"},
}
},
"button2": {
"prototype": "digit/ui/radio-button.reel",
"properties": {
"element": {"#": "button2"},
"enabled": true,
"radioButtonController": {"@": "radioButtonController"},
}
},
"button3": {
"prototype": "digit/ui/radio-button.reel",
"properties": {
"element": {"#": "button3"},
"enabled": true,
"radioButtonController": {"@": "radioButtonController"},
}
}</code></pre>
</div>
<p>The <i>checked</i> property decides which button is checked (these are radio buttons, so only one should be selected at a time). We set each of these buttons to be <i>enabled</i> so they can be clicked on. Finally we set the <i>radioButtonController</i> property to a reference of our radio button controller that we created earlier.</p>
<p>By assigning <i>radioButtonController</i> in each of these buttons, we allow the controller to know which button is selected. Now, if you run the app, you should see three radio buttons.</p>
<h3>Adding Labels</h3>
<p>In most apps, you will want to have a label on your buttons so the user knows what they are clicking on. This is done by wrapping each input node in a label node, just like regular HTML:</p>
<pre><code><label>
<input type="radio" data-montage-id="button1">
Section 1
</label>
<label>
<input type="radio" data-montage-id="button2">
Section 2
</label>
<label>
<input type="radio" data-montage-id="button3">
Section 3
</label></code></pre>
<p>With these HTML labels, you should have three labeled radio buttons:</p>
<img src="{{site.baseurl}}/images/docs/tutorials/using-substitutions/tutorial-substitution-radio-buttons.png" alt="Three radio buttons with labels"></img>
<p><a href="http://montagejs.github.io/mfiddle/#!/a3e78e24a0a8525ec967">View source on MFiddle</a></p>
<h1>Adding the Content</h1>
<p>We will start by adding three switchable text components under the buttons. In order to be able to switch the content, we will need to add a substitution component:</p>
<pre id="code3"><code><div data-montage-id="substitution"></div>
"substitution": {
"prototype": "montage/ui/substitution.reel",
"properties": {
"element": {"#": "substitution"}
}
}</code></pre>
<p>Next we need to add the content components. For now, we will make the content as text components with simple text values.</p>
<p>1. Add three nodes as children of the subsitution node in the markup:</p>
<div id="code4">
<pre><code><div data-montage-id="substitution">
<div data-arg="component1" data-montage-id="content1"></div>
<div data-arg="component2" data-montage-id="content2"></div>
<div data-arg="component3" data-montage-id="content3"></div>
</div></code></pre>
<p>The <i>data-arg</i> attribute is the id that the substitution will use to recognize its child components. This attribute can be the same or different from data-montage-id, which is used for serialization.</p>
<p>2. Add the content as regular text components in the declaration:</p>
<pre><code>"content1": {
"prototype": "montage/ui/text.reel",
"properties": {
"element": {"#": "content1"},
"value": "This is the first sub-component."
}
},
"content2": {
"prototype": "montage/ui/text.reel",
"properties": {
"element": {"#": "content2"},
"value": "This is the second sub-component."
}
},
"content3": {
"prototype": "montage/ui/text.reel",
"properties": {
"element": {"#": "content3"},
"value": "This is the third sub-component."
}
}</code></pre>
</div>
<p>At this point, the substitution will still not show any content because we never assign it a component. We can tell the substitution to show a component by assigning to its <i>switchValue</i> property. This property should be set equal to the data-arg of a component. We will start by manually setting <i>switchValue</i> to point to the first component:</p>
<pre id="code5"><code>"substitution": {
"prototype": "montage/ui/substitution.reel",
"properties": {
"element": {"#": "substitution"},
"switchValue": "component1"
}
}</code></pre>
<p>Now if you run the project you should see the first text component:</p>
<img src="{{site.baseurl}}/images/docs/tutorials/using-substitutions/tutorial-substitution-first-component.png" alt="Showing the first component"></img>
<p>Now the substitution gets its component value from the first component in our declaration. Next we need to make the buttons change the current component.</p>
<p><a href="http://montagejs.github.io/mfiddle/#!/f17c3248199a7c4ccbfa">View source on MFiddle</a></p>
<h1>Linking it Together</h1>
<p>Now that we have a substitution and three radio buttons, we need to make them interact with each other. First, we will need a way to identify which component each button points to. We will do this by adding an extra property in our buttons:</p>
<pre><code>"button1": {
"prototype": "digit/ui/radio-button.reel",
"properties": {
"element": {"#": "button1"},
"checked": true,
"enabled": true,
"radioButtonController": {"@": "radioButtonController"},
<b>"type": "component1"</b>
}
},
"button2": {
"prototype": "digit/ui/radio-button.reel",
"properties": {
"element": {"#": "button2"},
"enabled": true,
"radioButtonController": {"@": "radioButtonController"},
<b>"type": "component2"</b>
}
},
"button3": {
"prototype": "digit/ui/radio-button.reel",
"properties": {
"element": {"#": "button3"},
"enabled": true,
"radioButtonController": {"@": "radioButtonController"},
<b>"type": "component3"</b>
}
}</code></pre>
<p>By adding these lines in the serialization, we are giving each of our buttons a custom value that points to a component's <i>data-arg</i>. This way, if we get a reference to one of these buttons, we can get information on which component it is linked to.</p>
<p><b>Note:</b> the <i>type</i> property is a custom property that we arbitrarily assigned, you can name the property whatever you like, as long as you are consistent.</p>
<p>Now that each button knows the <i>data-arg</i> of its corresponding component, we need to bind the substitution’s <i>switchValue</i> to the currently selected button’s <i>type</i> property. Radio Button Controllers have a <i>selectedRadioButton</i> property that we can use to get a reference to the currently selected button.</p>
<pre id="code6"><code>"substitution": {
"prototype": "montage/ui/substitution.reel",
"properties": {
"element": {"#": "substitution"}
},
<b>"bindings": {
"switchValue": {"<-": "@radioButtonController.selectedRadioButton.type"}
}</b>
},</code></pre>
<p><b>Note:</b> We also removed the “switchValue” property from the properties section since the binding will take care of setting the value for us.</p>
<p>The buttons should now switch between the different text reels as you select the radio buttons.</p>
<p><a href="http://montagejs.github.io/mfiddle/#!/b7f19617f03cbf859823">View source on MFiddle</a></p>
<h1>Beyond Text</h1>
<p>Substitutions aren’t limited to text reels. In this section we will be changing one of our text reels into a static html page.</p>
<p>First we'll need to create a new Montage component for our HTML page to interact with the rest of our application. You can do this by entering "minit create:component -n static" in the console in the directory where your application is located.</p>
<p>Once the static component has been created, we can alter the html to display a header, paragraph, and image:</p>
<pre><code><!doctype html><br/><html><br/> <head><br/> <meta charset="UTF-8"><br/> <title>Simple HTML page</title><br/> <script type="text/montage-serialization"><br/> {<br/> "owner": {<br/> "properties": {<br/> "element": {"#": "owner"}<br/> }<br/> }<br/> }<br/> </script><br/> </head> <br/> <body><br/> <div data-montage-id="owner" class="Test"><br/> <h1>This is a simple static HTML page</h1><br/> <p>Montage substitutions can be used to swap static HTML pages as well as montage components.</p><br/> <img src="static.jpg" alt="montage_logo"><br/> </div><br/> </body><br/></html>
</code></pre>
<p>You can select your own image here or download the montage logo <a href="http://i58.tinypic.com/raoks0.jpg" download="static">Here</a></p>
<p>Now that we've created our static html page as a component in Montage, we just need to link the component to our existing application:</p>
<p>Change This:</p>
<pre><code>"content1": {
"prototype": "montage/ui/text.reel",
"properties": {
"element": {"#": "content1"},
"value": "This is the first sub-component."
}
},</code></pre>
<p>Into This:</p>
<pre><code>"static": {
"prototype": "ui/static.reel",
"properties": {
"element": {"#": "static"}
}
},</code></pre>
<p>The first button on your application should now display the static HTML page!</p>
<h1>Adding Full Applications</h1>
<p>If you’ve completed the temperature converter tutorial you can change one of your text reels into your converter reel.</p>
<p>There are two ways you could get another component into your project:</p>
<p>Method 1: Copy every component in the temperature converter's UI folder into your current project's UI folder. You will need to rename the temperature converter's main.reel so that it does not conflict with your current project's main.reel. When you do this, be sure to also rename the files inside the folder, the class name at the top of the HTML markup, and the class name in the css file.</p>
<p>Method 2: Since the temperature converter's main reel is very small, you can simply copy over just the converter.reel into your project's UI folder. However, the main component in the temperature converter contains some css that you will need to copy over manually into your project.</p>
<p>Once you have copied the temperature converter's component(s), change the prototype of one of your components in the declaration.</p>
<pre><code>"content1": {
<b>"prototype": "ui/converter.reel"</b>,
"properties": {
"element": {"#": "content1"}
}
}</code></pre>
<p>If you copied over both converter.reel and main.reel (method 1), set the prototype to the name of the converter's main component. (E.g. if you renamed the converter's main reel to temperature.reel, use that as the prototype).</p>
<p>Your app should now show the temperature converter when the first radio button is selected:</p>
<img src="{{site.baseurl}}/images/docs/tutorials/using-substitutions/tutorial-substitution-final.jpg" alt="The end result"></img>
<p>You can use any component in this way, not just the temperature converter. For example, you could have the temperature converter on the first section, the Reddit Client on the second, and the Montage Popcorn app on the third.</p>
<script>
function change(button,code,video){
var mybutton = document.getElementById(button);
var mycode = document.getElementById(code);
var myvideo = document.getElementById(video);
if(mybutton.value=="See How to do it in Montage Studio"){
mybutton.value="See the Code";
mycode.style.display="none";
myvideo.style.display="inline-block";
}
else{
mybutton.value="See How to do it in Montage Studio";
myvideo.style.display="none";
mycode.style.display="inline-block";
}
}
</script>