Web Development

Getting Started with Riot.js

May 2nd, 2017 | By Lamin Sanneh | 9 min read

Javascript fatigue is still an ongoing thing. Even before introducing our new framework, Riot.js, there seems to be an acknowledgment of the above.

Even with this acknowledgment, one should always keep tabs on what’s new even if it’s not used immediately.

A couple of reasons why. You might find it a good fit for a future project. Secondly, you may learn a better paradigm of programming in what’s new, sometimes even without switching to the new framework, you may still be able to incorporate it into the one you’re currently using, as a framework user or developer.

Regardless of the number of libraries out there, it is vital to give room for newcomers. This is because there is always a chance for improvement or otherwise. I say otherwise due to other frameworks such as Ember.js that cater to and promote the idea that "more is better". I have discovered a library that says otherwise.

Let’s say you need something structured as in React.js or Ember.js, but only need to integrate it into an existing application in a very minimal way. Something you can just drop in and get going. Here, I introduce you to Riot.js.

Before we proceed, if you are curious, you can see the demo and download the repository.

Riot.js, React.js, and Angular.js

Riot.js, such as React.js, uses a self-contained single file component. However, Riot.js takes this to the next level because you do not need to import a component to use it inside of another.

The Riot.js acknowledges the brilliance of React.js, yet they believe they are addressing some of the library’s weak points.

The most appealing thing to me about Riot.js is how easy it is to drop it into an existing application.

We can link to our Riot.js components, instantiate the main one, pass it some JSON data, and have it be part of our program.

All of this without sacrificing things we’ve grown to love with Angular.js and React.js, such as code manageability with components, familiar APIs, for example, looping over data, templating, handling DOM events such as clicks, and easy component nesting.

The Application

So now that we have been introduced to Riot.js, let's describe the application we’ll be building.

We will build a tab of contents application called tabs. It can potentially be used as a categorized list of links or categories of anything. We will use a static array of data but as you’ll see, this data could come from some JSON call and is easily switchable.

To get started, Riot.js comes with a command line interface. However, it is not necessary as Riot.js has an in-browser compiler that you can include as a script. In fact, we will build the tabs application without using the CLI. For production or larger applications, it may be worth looking into.

The CLI makes it easy to include a large number of component files as you do not have to include them individually as we will do in this article. However, for small projects like ours, manual inclusion is fine. We will touch on its usage in the last part of this article. To get it out of the way you can install it using the below npm command:

npm install riot - g


Now let’s start writing our application. Create a html file called index.html, and add it the boilerplate below:

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Tabs</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
    <div class="main-container">

    </div>
    <script type="text/javascript">
        var tabs = [{
                id: 1,
                title: "tab 1",
                content: "some content 1"
            },
            {
                id: 2,
                title: "tab 2",
                content: "some content 2"
            },
            {
                id: 3,
                title: "tab 3",
                content: "some content 3"
            }
        ];
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/3.3.0/riot+compiler.min.js"></script>
</body>

</html>


In this boilerplate, we are linking to the Riot.js CDN link which contains the main library, and the in-browser compiler. This removes the need for a command line compiler. We are also creating an array, which is a list of objects, each representing a tab and its content.

Next, in the head of the document, add the styles below for our tabs:

<style>
    .tab-content {
        display: none;
    }

    .tab-headers {
        display: flex;
    }

    .tab-header {
        background-color: #eff0f2;
        color: #888;
        padding: 5px 10px;
        border-bottom: 2px solid #87d3b7;
    }

    .tab-header:hover {
        cursor: pointer;
    }

    .tab-header.active {
        background-color: #87d3b7;
        color: #FFF;
    }

    .tab-content {
        padding: 5px;
    }

    .tab-content.active {
        display: block;
    }
</style>


After the inclusion of the Riot.js library, add in this line:

<script>
    riot.mount('*', {
        tabs: tabs,
        defaultTabIndex: 1
    })
</script>


This bootstraps our application and passes in an optional object as the application data and options. The options and data are pure javascript data types. Here, we are passing on the list of tabs we created moments ago. We are also passing in the index of the currently visible tab by default.

Let’s create our main Riot.js component. Create a file within a components directory called components/tabs.tag.

The file extension .tag is not a compulsory one to use but it is a common convention used in the Riot.js documentation. In this file put in the following:

<tabs>
    <tab-headers isclicked={this.isclicked} tabs="{opts.tabs}"></tab-headers>
    <tab-contents tabs="{opts.tabs}"></tab-contents>

    <script>
        this.on('before-mount', function() {
            if (typeof opts.defaultTabIndex !== "undefined") {
                opts.tabs[opts.defaultTabIndex].active = true;
            }
        })

        this.isclicked = (event) => {
            opts.tabs.forEach((tab) => {
                if (event.item.tab.id == tab.id) {
                    tab.active = true;
                } else {
                    tab.active = false;
                }
            });

            this.update();
        }
    </script>
</tabs>


This is how a Riot.js component file is created. First, we wrap the whole of the component using the custom tags as we intend to use them in our application, in this case:

<tabs>
</tabs>


Inside of the custom tag, we have the contents of the component which can be static HTML content or inclusion of other components as we have above. Those components have not been created yet but we will do so in a moment.

Finally, you have an optional scripts tag which is where the logic of the component will live. In our component above, we have an event handler we want to run before the component is inserted into the DOM.

We also have a function we want to use as part of the component. This is used to handle the click event on a tab heading but we will get to that shortly.

Now that we have the basic foundation of a component, let’s create the other components.

The main component will include contents, a list of tab headers, and a list of tab contents. When we click on a tab header, the corresponding content tab will be visible and the others will be hidden.

Create the tab-headers component components/tab-headers.tag with the contents:

<tab-headers>
    <div class="tab-headers">
        <tab-header onclick="{parent.opts.isclicked}" each={tab in opts.tabs} tab="{tab}"></tab-header>
    </div>
</tab-headers>


Then create the component components/tab-header with the component:

<tab-header>
    <div class="{active: opts.tab.active} tab-header">{opts.tab.title}</div>
</tab-header>


In the tab-headers component, we are looping over the list of tabs that were passed in when we mounted the components in index.html.

In each loop instance, we are creating a tab-header component instance and passing in event handlers and values. The list of tabs is accessible through a special property called opts which is available in all components. The property lets you access properties passed in by a parent component.

In Riot.js, you can pass in values and functions as data properties as we are doing in tab-headers.

We are passing in a click handler from the top-level parent tabs component onto each child tab-header component. A component can access the parent properties and functions of a component using the property called parent. Remember there is a distinction between parent properties and passed-in properties.

To access a passed-in property you can directly go through that component’s opt property. However, to access a parent’s property, you must go through the parent property of the component.

In the tab-header component, we are displaying the tab title as the title of the tab. We are also adding or removing the class active depending on whether the tab is active or not.

Now that we have created the tabs, tab-headers, and tab-header components, let’s add them to our main HTML page. Before the mount statement, add the following lines to include the components:

<script src="components/tab-header.tag" type="riot/tag"></script>
<script src="components/tab-headers.tag" type="riot/tag"></script>
<script src="components/tabs.tag" type="riot/tag"></script>


Finally, let’s create the components for the tab contents. Create a component in components/tab-contents with the content:

<tab-contents>
    <div class="tab-contents">
        <tab-content each={tab in opts.tabs} tab="{tab}"></tab-content>
    </div>
</tab-contents>


Create components/tab-content with the content:

<tab-content>
    <div class="{active: opts.tab.active} tab-content">{opts.tab.content}</div>
</tab-content>


Link to the component file by using:

<script src="components/tab-content.tag" type="riot/tag"></script>
<script src="components/tab-contents.tag" type="riot/tag"></script>


Now our application has been created but we still need to use the main component to make it appear. In index.html, inside of the main-container div put:

<tabs></tabs>


Events

Let's revisit the isclicked function in the main component:

<script>
    // Some code here
    ...

    this.isclicked = (event) => {
        opts.tabs.forEach((tab) => {
            if (event.item.tab.id == tab.id) {
                tab.active = true;
            } else {
                tab.active = false;
            }
        });

        this.update();
    }
</script>


What we are doing here is setting which tab in the list is active when a header is clicked. We achieve this by setting a click event handler on the tab-header. When clicked, this function is called:

<tab-header onclick="{parent.opts.isclicked}" each={tab in opts.tabs} tab="{tab}"></tab-header>


Now point a web server to the root directory which contains the index.html file. Open the web server URL in a browser and now, we should have a functional tabs application.

So now the application is functional but let’s revisit the riot compiler we mentioned earlier. Currently, we are manually linking to components. This is fine for our simple application but it could become tedious if we have tens or even hundreds of components to link to. Let's combine all the components into one file.

We will compile and concatenate all the component files into one file called app.js which is the only file we will link to.

On the command line, navigate to the project root folder and run the command:

riot components app.js


This will run the compiler just once. To have a watcher on the components folder that’ll run the compiler automatically when the contents change, run the following instead:

riot components app.js - w


Link to the newly created file by removing all the links to the individual component files, and adding the following just before we mount the components:

<script src=“app.js”></script>


Conclusion

Riot.js takes many of the good parts of React.js and makes it even simpler.

There are many tools available to use Riot.js but as you have seen above, they are just complementary to Riot.js but are not absolutely necessary to get a functional application up and running.

Have you used Riot.js before or are considering it for your next project?

Jscrambler

The leader in client-side Web security. With Jscrambler, JavaScript applications become self-defensive and capable of detecting and blocking client-side attacks like Magecart.

View All Articles

Must read next

Web Development

Getting Started with Three.js

3D graphics in the browser have been a hot topic ever since they were first introduced. Three.js may look complex at first but the heavy lifting is done without sacrificing much flexibility.

April 20, 2017 | By Daniela Grams | 9 min read

Web Development

Getting Started with Angular 2

Angular 2 has been built to be completely decoupled from the DOM, meaning that developers can use the framework to build more than just web applications.

November 10, 2016 | By Thomas Greco | 6 min read

Section Divider