👋 Hey all, welcome back this week! Each tutorial is self-contained, so feel free to start at the beginning, or just plunge in here.
Introducing: The TrainSchedule Component
Our task in this tutorial will be to build a data table TrainSchedule component that can loop through an array of JavaScript data. We want it to be re-usable, so we can, in the future, simply "plug in" a new data set (e.g., a JSON file, or even a CSV). In doing so, we'll learn about the different data types available, and how to attach them to State and other Modulo Component Parts. We'll also learn the "for loop" template tag. Let's begin!
Starting snippet
In this tutorial, we will start with a bunch of "flat" State variables that only contains text. See below:
As with previous tutorials, you can simply copy and paste this code into any HTML file to start:
<template Modulo>
<Component name="TrainSchedule">
<Template>
<h3>Station</h3> <h3>Line</h3> <h3>Arrival (Departure)</h3>
<div>{{ state.station }}</div>
<div>{{ state.line }}</div>
<div style="{% if state.late %}background: #ffaaaa{% endif %}">{{ state.minutes }} min ({{ state.minutes|add:1 }} min)</div>
</Template>
<State
line="Red Line"
station="Embarcadero"
minutes="5"
late="false"
></State>
<Style>
:host {
display: block;
text-align: center;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
div {
background: #ffffffaa;
}
</Style>
</Component>
</template>
<script src="https://unpkg.com/mdu.js"></script>
<x-TrainSchedule></x-TrainSchedule>
Introducing Part 7: Data Types
As of right now, there are several glaring issues with our code: The first bug is that it shows the train as late (highlighted in red), yet it should not be. The second bug is that it says it will depart in "51 min", instead of "6 min", when it's supposed to have 1 minute for boarding. In both these cases, it's because of the wrong data type: We are only dealing with Strings, when we want to be using Numbers and Booleans.
The final omission is that there is only one station showing. Not a very useful data table!
We'll learn one more syntax next: The Data Prop, or :=
syntax. Typically, when we add attributes to anything, whether it is a Component Part or even just in regular HTML, the attribute value can only be a string. This means when we did <State minutes="5" ... >
previously, we made a mistake: The minutes
variable didn't get assigned to 5
the Number, but rather "5"
the String. Similarly, when we did late="false"
, we once again were creating a string with the word "false", instead of the Boolean value of false. Also, for one word values, quotes are optional.
Why don't we use "strings" for numbers? Using strings of digits (i.e. in quotes) instead of the numbers themselves means that things like arithmetic won't work as intended. Example: If state variable
count="1"
, thenstate.count + 10
will result in"110"
instead of the desired11
, since it's a string of digits, so"1" + "10" = "110"
Arrays
Continuing on our tour of data types, let's examine "container types" (ones that contain other data). In our case, container types are also "iterable types" (ones you can "loop on", e.g. with a for loop, as we'll learn later).
Arrays are the most important type of "container type" or "iterable type" in JavaScript. This means, a type that can contain other types. This means you can say it's an "Array of Numbers" (to refer to a certain collection of numbers, e.g. data you want to chart or graph), or an "Array of Strings" (to
refer to a collection of items of text, e.g. the usernames of people who are present in a chat room).
Objects
Objects are like arrays in that they contain other data, but instead of having an ordered sequence of items, they have them behind "keys", which are strings designations or labels for values, which can be any other type. The format for objects is like: { "key": "value", "key2": "another value" }
Arrays of Objects
When we access real-world data, whether those are blog articles in a publishing site, or a data items in a dashboard, they often "arrive formatted" as what's called a JSON array of objects. Here's an example:
<State
stations:='[
{
"name": "Embarcadero Station - San Francisco",
"trafficRating": 1353
},
{
"name": "19th Street Station - Oakland",
"trafficRating": 732
}
]'
></State>
Summary: JSON type list
To summarize this, look at this list of JSON types, and see if you can
understand the examples given of each type of data:
-
String -
"Hello!"
,"how are you"
,"f$J^&m$j"
, or the empty""
-
Number -
42
or32.5
-
Array -
[ ]
or[ 1, "a", true ]
(can contain other data) -
Object -
{ }
or{ "a": 123, "b": "XYZ" }
(can contain other data) -
Boolean -
true
andfalse
(no other possible values) -
Other:
null
Step 1: Fixing with Data Props
To fix it, we do the following:
<State
line="Red Line"
station="Embarcadero"
minutes:=5
late:=false
></State>
Data type? If you are new to coding, you might be confused by this term. It's a little like a file format for variables: Instead of JPG, DOCX, and ZIP, we have Numbers, Strings, Arrays, Objects, Booleans, etc. This collection of types is what makes up the "JSON" format, which Modulo uses.
This is called a data prop directive. You can identify a data prop directive (:=
), by spotting an attribute name that is suffixed with a colon right before the equal sign, like this: attributeName:=value
.
Step 2: Adding More Trains with Arrays and Objects
- Array syntax summary:
'[
(opening),]'
(closing), and contents seperated with comma:,
. Object syntax summary:'{
(opening),}'
(closing),:
(seperates the key from the value) and,
(seperates each entry)
Now, let's transform our State into having only a single state variable, an Array of Objects:
<State
trains:='[
{
"line": "Red Line",
"station": "Embarcadero",
"minutes": 5,
"late": false
},
{
"line": "Blue Line",
"station": "Embarcadero",
"minutes": 7,
"late": true
},
{
"line": "Red Line",
"station": "West Oakland",
"minutes": 1,
"late": false
}
]'
></State>
Step 3: Using a for-loop to show all trains
We looked at the {% if %}
template tag previously. Now we'll practice the {% for %}
template tag.
The "for-tag" is for when we want to duplicate a bit of template over and over for a repetitive bit of data. For example, if we want to template "for every article", or "for every pin in a world map", or "for every post in an article comment section". Each of these "for" statements refers to some plural thing that we want to have a similar style duplicated across, using the same HTML template for each item in that collection.
The for-tag syntax
For example, imagine showing a paragraph for every student in a class's roster
(assuming data like in the students:=
State data example above):
{% for name in state.students %}
<p>Name on roster: {{ name }}</p>
{% endfor %}
A for loop can also loop through other types of data, such as the very popular Array of Objects mentioned previously, formatting it in a reasonable way (assuming data like in the trains:=
State data example above):
{% for train in state.trains %}
<p>{{ train.station }} | {{ train.minutes }}</p>
{% endfor %}
In this example, the {{ train.station }}
and {{ train.minutes }}
refer to templating the individual values within the station object in the array of stations.
Like the "if", for has an "endfor", which it uses to designate the portion of the temlpate it will repeat. Unlike "if", it can use the template it 0 times, 1 time, or 2+ times (if-tags
can use the template only 0 times or 1 time, but can never "duplicate" the template and use it 2+ times).
Step 3: Using a for-loop to show all trains
Let's apply our for-loop knowledge below:
{% for train in state.trains %}
<div>{{ train.station }}</div>
<div>{{ train.line }}</div>
<div style="{% if train.late %}background: #ffaaaa{% endif %}">{{ train.minutes }} min ({{ train.minutes|add:1 }} min)</div>
{% endfor %}
<x-TrainSchedule>
- Complete Example
Finally, we put everything together, add in some font and sizing adjustments and a background, and we end up with the final results. Feel free to copy and paste the following to try it out:
<template Modulo>
<Component name="TrainSchedule">
<Template>
<h3>Station</h3> <h3>Line</h3> <h3>Arrival (Departure)</h3>
{% for train in state.trains %}
<div>{{ train.station }}</div>
<div>{{ train.line }}</div>
<div style="{% if train.late %}background: #ffaaaa{% endif %}">{{ train.minutes }} min ({{ train.minutes|add:1 }} min)</div>
{% endfor %}
</Template>
<State
trains:='[
{
"line": "Red Line",
"station": "Embarcadero",
"minutes": 5,
"late": false
},
{
"line": "Blue Line",
"station": "Embarcadero",
"minutes": 7,
"late": true
},
{
"line": "Red Line",
"station": "West Oakland",
"minutes": 1,
"late": false
}
]'
></State>
<Style>
:host {
background: url("https://upload.wikimedia.org/wikipedia/commons/thumb/2/29/BART_train_from_Farallones_Street_footbridge_%281%29%2C_July_2023.JPG/800px-BART_train_from_Farallones_Street_footbridge_%281%29%2C_July_2023.JPG");
display: block;
font-size: 1.1rem;
font-family: sans-serif;
text-align: center;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
min-height: 380px;
}
div {
background: #ffffffaa;
padding: 10px;
margin: 10px;
}
</Style>
</Component>
</template>
<script src="https://unpkg.com/mdu.js"></script>
<x-TrainSchedule></x-TrainSchedule>
Conclusion
In this section, we practiced using := data props to use different types of data in our component, and learned how we can use how to go deeper with Template and use a combo of {% for %}
, {% if %}
and other control-flow template-tags
. Next tutorial will really ramp it up, and show how to import data from online sources or APIs using the StaticData Component Part. Definitely follow and watch out for the next tutorial, since with that technique you can import your data and build data tables quicker than ever! As always, let me know if there is something you'd like covered in the comments.
Top comments (0)