Make a Quote Generator using Vue: Part 2

In the previous part, we learned about how data defined in a Vue object can be used inside our HTML. We then went on to include values for font family and background color in our Vue object. We set up our basic HTML and CSS.

In this part, our task is to help our HTML interact with our data. We can do this by using Vue directives. Let’s see how it is done.

Step 4: Vue’s v-model directive

Let’s go ahead and get over with the most obvious ones – message and author. In the previous part, we discussed how v-model can be used to bind data for form elements. All you have to do is include v-model=”message” for the textarea and v-model=”author” for the input field. Type {{message}} inside the #quote div and {{author}} inside the #author div within #preview.

 

<div id="controls">

    <h1>Enter Quote</h1>

    <textarea v-model="message" id="inputQuote" spellcheck="false" maxlength="80"></textarea>

    <input v-model="author" id="inputAuthor" type="text" spellcheck="false" maxlength="20">

</div>
.
.
.

<div id="preview">

    <div id="main">

    <div id="quote"> {{ message }} </div>

    <div id="author"> {{ author }} </div>

</div>

To test it out, type in a message or author’s name. The text should update in the Preview section on the right. Once you’ve made sure that it works well, move on to the next part.

Step 5: Vue’s v-for directive

Let’s populate our list of fonts. Vue has a directive v-for that can help us out here. Think of v-for as a for loop for HTML. To use it include v-for=”font in fonts” in the li tag of #fontsList as shown below

<ul class="optionsList" id="fontsList">
    
    <li v-for="font in fonts">{{ font }}</li>

</ul>

Here, font is the iterator and fonts is the name of the data array. {{font}} displays the current iterator’s value i.e. the font’s name inside the li tag. Just like {{message}} displayed the message text inside the #quote div.

An improvement over this would be to display these font labels in their respective font styles. We can do that by setting styles for each li tag inline. v-bind:style let’s us to specify inline styles for an HTML element.

 

<ul class="optionsList" id="fontsList">
 
    <li v-for="font in fonts" v-bind:style="{fontFamily: font}">{{ font }}</li>

</ul>

 

v-bind:style takes the value of an iterator and assigns it to the fontFamily for each li tag. I’d like to take a minute and appreciate how simple and elegant this is. Trying to achieve this in a traditional way would mean applying styles separately to each li or using JS to apply styles to each li. In contrast, Vue let us apply styles to an element while rendering it – all in a single line.

We can use v-bind:style to list our background colors as well. You can update the li for background colors like so

<ul class="optionsList">

    <li v-for="theme in themes" v-bind:style="{backgroundColor: theme.backgroundColor}></li>

</ul>

theme contains two properties – backgroundColor and fontColor. We use theme’s backgroundColor property and assign it to the style backgroundColor. This should list all of you background colors.

Our next step will be to set the font family, background color, and font color for our preview. This is where currentBackgroundColor, currentFontColor, and currentFont we defined in our data, will be used. We’ll use the v-bind:style, again, to do this.

<div id="main" v-bind:style="{backgroundColor: currentBackgroundColor,

color: currentFontColor,

fontFamily: currentFont}">

    <div id="quote">{{ message }}</div>

    <div id="author">- {{ author }}</div>

</div>

Launch your app again and check if everything is working fine. Let’s go ahead and add a way for this app to update to user’s selection.

Step 5: Adding interaction

In the previous step, we defined the styles for preview using the currentBackgroundColor, currentFontColor, and currentFont properties. These properties are defined in our data and so Vue will react to and re-render and relevant HTML, if these properties are changed.

So, we’ll need to somehow update the values of currentBackgroundColor, currentFontColor, and currentFont properties based on user’s selection. We don’t need to do this for message and author because the v-model directive handles it for us. It’s designed specifically with the intention of keeping the app aware of the freshest form data.

For non-form elements, we can use v-on:click. In your li tag for fonts add v-on:click=”currentFont = font”.

<ul class="optionsList" id="fontsList">
    <li v-for="font in fonts" v-bind:style="{fontFamily: font}" v-on:click="currentFont=font">
        {{ font }}
    </li>
</ul>

This tells the app to set the currentFont to the font value for that li tag when the user clicks on it. Try it out, when you click a font option the font in the #preview should update instantly. Similarly, we can update the code for background color.

<ul class="optionsList">
    <li v-for="theme in themes" 
        v-bind:style="{backgroundColor: theme.backgroundColor}
        v-on:click="currentBackgroundColor=theme.backgroundColor, currentFontColor=theme.fontColor"></li>
</ul>

Notice that we set the currentBackgroundColor and the currentFontColor here. Again, test it out. Works brilliantly, doesn’t it? You quote generator with a live preview is now ready.

Next Steps

You’ll agree that this still is a very basic quote generator. Even though we’ve mostly achieved what Behappy does, I’m sure you can think of ways to improve it. How about adding those stamps we left out at the beginning. Small hint: try using Font Awesome (or your favorite icon font) for this (instead of images). Icon fonts will render better and it’ll essentially be like loading text instead of trying to manage image icons. If you want to allow your users to download their quote as an image, check out html2Canvas created by Niklas von Hertzen. It’s an amazing library that takes your HTML elements and adds them to an HTML canvas. You can use this canvas to download its contents as an image.

Conclusion

We’ve created a very simple project and it does not even begin to measure Vue’s full capabilities. Vue has a lot more to offer. From conditional rendering, to state transitions, to custom directives – the list just goes on. And their documentation is full of detailed explanations and examples. Don’t forget to check it out.

I will not compare Vue with Angular or React because I don’t think it would be fair. They all have features that set them apart and they may have limitations that might undesirable for your project. The best way to asses this is to test it yourself.

Leave a Reply

Your email address will not be published. Required fields are marked *