DEV Community

Cover image for Learn template-tags while creating interactive forms in a web component (Learn Modulo.js - Part 6 of 10)
michaelb
michaelb

Posted on

Learn template-tags while creating interactive forms in a web component (Learn Modulo.js - Part 6 of 10)

👋 Hey all, welcome back this week! Each tutorial is self-contained, so feel free to start at the beginning, or just plunge in here.

Note: Due to a bug with Dev.To, I'm unable to publish this tutorial normally. The fenced code blocks do not support template syntax, causing the markdown parser to crash.

Introducing: The NewsletterSubscribe Component

Showing the final result of NewsletterSubscriber

In Part 6, we'll be creating a custom, interactive sign-up form that only shows the newsletters to subscribe when the user chooses. This will give us practice with some very useful techniques, while building up our knowledge of template-tags, a core concept in templating.

Starting snippet

In this tutorial, we will start with Props, just like with the PictureFrame component in Part 2.

As with previous tutorials, you can simply copy and paste this code into any HTML file to start:

<template Modulo>
    <Component name="NewsletterSubscribe">
        <Template>
            <form method="POST">
                <h2>Learn Modulo.js - Sign-Up Component</h2>
                <label><strong>Email:</strong><input [state.bind] name="email" /></label>
                <label>
                    <input [state.bind] name="subscribe" type="checkbox" />
                    I want to subscribe to receive news and special offers
                </label>
                <label>
                    <input [state.bind] name="newsletters.kombucha" type="checkbox" />
                    Kombucha Enthusiast Newsletter
                </label>
                <button>Submit</button>
            </form>
        </Template>
        <State
            email=""
            subscribe:=false
            newsletters:={}
            newsletters.kombucha:=true
            newsletters.soda:=false
            newsletters.wine:=true
            newsletters.beer:=false
        ></State>
    </Component>
</template>
<script src="https://unpkg.com/mdu.js"></script>
<x-NewsletterSubscribe></x-NewsletterSubscribe>
Enter fullscreen mode Exit fullscreen mode

Important things to note: Look at how "State" is set-up. Do you see how newsletters:={} assigns to a JavaScript Object (designated with {}), and how then kombucha, soda, wine, and beer are all assigned with the syntax newsletters.kombucha, etc? This creates an Object that ends up looking like: { "kombucha": true, "soda": false ... }. This is a short-hand in Modulo for creating such objects. Also, note how name="newsletters.kombucha" must specify the full name, including the dot (.), to access that true/false value.

Introducing Part 6: Template Tags

In addition to filters, the Modulo templating language also support powerful "template tags", which allow for more complicated custom behavior. This includes the next two topics in this tutorial: "if" template-tag, which allows for conditional rendering (e.g. "only show the submit button if a form is filled correctly", or "only show the modal if the user has clicked the button"), and the "for" template-tag, which allows for HTML to be repeated for each item of some given data (e.g. "every blog post gets it's own <li> element", or "every field of data gets it's own form field").

Syntax

Unlike template variables or filters, they use {% and %} (instead of {{ and }}) to designate where they are in the Template code. Template tags are in the format of {% tag %}. They allow for more complicated transformations to the HTML code generated. For example, here are a few: {% include other_template %} {% comment %} ... {% endcomment %}

The if-tag

One of the most useful template tags you will use is the if tag, written like this: {% if %}. The if-tag allows for conditional rendering of HTML code based on the condition supplied.

See below for two examples of using the "if" tag:

{% if state.expanded %}
<p>Details: {{ props.details }}</p></div>
{% endif %}
{% if props.link %}
<a href="{{ props.link }}">Read more...</a>
{% else %}
<em>(No link provided)</em>
{% endif %}

Note that there are two other tags in the mix. These a related to the if tag, and will only show up after the if tag. The first is the {% endif %} tag. This is required, since it shows Modulo what you want the if tag to conditionally include. The second is the {% else %} tag. The {% else %} is optional, as evidenced by the first example: You don't need it for all uses of the if tag.

Step 1: Optionally show the Kombucha checkbox

Let's start with an if-statement based on state.subscribe. The logic is that if the user doesn't want to subscribe at all, we shouldn't even show the extra newsletter options. We can accomplish this with the following:

{% if state.subscribe %}
<label>
<input [state.bind] name="newsletters.kombucha" type="checkbox" />
Kombucha Enthusiast Newsletter
</label>
{% endif %}

This will now only show the option to choose which newsletter when you click "subscribe".

Step 2: Use "else" to show a hint about filling in the email

Now, let's get practice using a more complex if statement to show a hint instead of the "subscribe" form button, until they start typing a few characters. Emails should (probably) never be shorter than 4 characters, so let's use that as the thresh-hold. We can use the lt (less-than, a.k.a. <) operator to compare. See below:

{% if state.email|length lt 4 %}
<p><em>Hint: Start by entering your email</em></p>
{% else %}
(... subscribe form goes here ...)
{% endif %}

Step 3: Use for loop to list the newsletters

Let's start with a simple for-loop "test", and then we'll expand on it in the next step:

{% for key, value in state.newsletters %}
<label style="{% if value %}background-color: #11991133;{% endif %}">
{{ key }}
</label>
{% endfor %}

Important Note: Always put your template tags inside your HTML values! Do not do something like {% if value %}style="color: blue"{% endif %}, instead do style="{% if value %}color: blue{% endif %}". Otherwise, the {% and such could get interpretted as value-less attributes, your code to get littered with {%="".

Step 4: Adding back in the input

This will loop through each newsletter, and render it as green if "value" is true. However, it won't create toggle inputs. We'll need to use the {{ key }} property inside of the name= attribute. Examine the following tweak to the input:

<input [state.bind] name="newsletters.{{ key }}" type="checkbox" />

Put this inside the for-loop, and it will auto-generate checkboxes, no matter how many newsletters you might have!

<x-NewsletterSubscribe> - Complete Example

Finally, we put everything together, add a |capfirst for formatting, and toss in a Style part with some very basic styling, to make the form look a little better, and we end up with the final results. Feel free to copy and paste the following to try it out:

Due to a bug with Dev.To, I cannot include the source code. However, you can see it in the following Gist:

https://gist.github.com/michaelpb/9bac99ba0985859742961c3d1e1f310a

Conclusion

In this section, we practice using template-tags to make more user-friendly forms. In the next tutorial we'll start digging into some of Modulo's strengths, with data-types, StaticData and API integration, so be sure to follow to learn how to write declarative code to hook up APIs in just a few lines!

Top comments (2)

Collapse
 
dannyengelman profile image
Danny Engelman

Your post has an error:

Collapse
 
michaelpb profile image
michaelb

True, thanks for pointing it out! That's very odd - it's preventing me from publishing any syntax that resembles liquid syntax (Modulo templates included). So {% if %} doesn't work in code blocks. I think this is a bug with Dev.To, since it's not supposed to behave like this.

For now, I had to change all my code blocks which removed indentation and made it harder to copy, but at least it published this time. Very annoying!