In the ever-evolving world of JavaScript frameworks and libraries, choosing the right foundation for your development can feel overwhelming. Once you commit to a specific framework, switching to another is no easy feat, often impossible due to time and budget constraints.
So, why Ractive.js?
Unlike tools that generate static HTML, Ractive transforms templates into dynamic blueprints for interactive applications. While some might argue that Ractive’s impact is more of a refinement than a revolution, its value remains undeniable.
Ractive’s strength lies in its ability to provide robust capabilities with a refreshingly user-friendly approach. It’s elegant, fast, unobtrusive, and lightweight.
This article will guide you through building a simple search application with Ractive, highlighting its key features and showcasing how it simplifies web app development.

What is Ractive.js?
Ractive was initially designed to address the complexities of data binding. It achieves this by converting templates into a lightweight virtual representation of the DOM. This allows for efficient and intelligent updates to the real DOM whenever data changes.
However, it soon became evident that Ractive’s underlying approach and architecture could be applied to streamline other tasks. For instance, it can automatically manage tasks like reusing event handlers and unbinding them when no longer needed, eliminating the need for event delegation. This approach, similar to its data binding, prevents code bloat as the application scales.
Crucially, essential features like two-way binding, animations, and SVG support are available out of the box, with plugins readily available for custom functionality.
Unlike tools and frameworks that impose a rigid structure and new vocabulary, Ractive adapts to your workflow, seamlessly integrating with other libraries.
Our Sample App
Our example application will enable users to search a database of developers based on their skills. The app will have two views:
- Search: Displays a searchable list of skills.
- Results: Shows a skill view with a list of developers possessing that skill.
For each developer, we’ll display their name, photo, a short bio, and a list of skills, each linking to the respective skill view.
(Note: Links to a live demo and the source code repository are provided at the end of this article.)
To focus on the Ractive framework, we’ll make some simplifications not recommended for production:
- Default theme: We’ll use Bootstrap with its default styling instead of custom theming.
- Dependencies: Dependencies will be added as separate scripts defining global variables instead of using ES6 modules, CommonJS, or AMD with proper loaders for development and a build process for production.
- Static data: We’ll use pre-scraped static data from publicly available pages.
- No client-side routing: The URL will remain constant as we switch between views. While not ideal for SPAs, it’s acceptable for smaller interactive components. Ractive lacks a built-in router but can integrate with third-party ones, as shown in this example.
- Templates inside script tags: While suitable for smaller applications, especially with the advantage of being processed client-side alongside server-side templates (e.g., for internationalization), larger apps benefit from pre-compiling (a.k.a., pre-parsing) templates into internal JS representations.
Getting Started
Let’s build our application the app iteratively, adding features and exploring concepts as we go.
Start by creating a folder with two files: index.html and script.js. Our application will be simple, running directly from the file:// protocol, eliminating the need for a development server (though you can use one if you prefer).
The Search Page
We’ll begin by creating the search page where users can select a skill to find matching developers.
HTML Structure
Let’s start with a basic HTML page:
| |
This is a straightforward HTML5 document. It loads Bootstrap from the CDN, Lodash (for data manipulation), and Ractive.js.
Ractive doesn’t require dedicating the entire page to a SPA; thus, we can have static content. Here, it’s a container element and the page title.
Finally, we load the pre-prepared demo data and the script containing our application logic.
With the HTML skeleton in place, let’s add functionality.
Skill List
One of Ractive’s strengths is its focus on the desired HTML output, allowing developers to concentrate on the code necessary to achieve it.
Let’s create a skill list as our initial view. This involves:
- Adding an HTML element to display the list.
- Adding a template snippet to our HTML.
- Writing JavaScript to provide data to the template, rendering it within the added HTML element.
Here’s the modified HTML:
| |
Ractive has no strict conventions for designating the HTML element to receive the displayed data; using an ID is the simplest approach. I typically use the “root” ID for this. We’ll see its usage during Ractive initialization shortly. For those interested, there are other ways to specify the root element.
The unusual type="text/html" script element is a clever way to load a chunk of HTML without parsing or rendering it, as browsers ignore scripts with unknown types. The script’s content is a Mustache/Handlebars-like template (Ractive also supports some extensions).
We write the template code assuming access to a “skills” array. The {{#each}} mustache directive directive defines iteration. Inside, the current element is accessible as “this.” Assuming “skills” holds an array of strings, we render it using an interpolation mustache {{this}}.
Now, let’s look at the JavaScript that connects the data to the template:
| |
In just ten lines:
- We “retrieve” data from our “database.”
- Instantiate a new Ractive app.
- Instruct it to render inside the element with
id="root". - Tell it to fetch the template from the script element with
id="tpl-app"(there are other ways for this). - Pass initial data (or “scope” in Angular terms), which we’ll learn to change dynamically.
- Use lodash’s “keys” method to get skill names, which are object keys in our “DB.”
This script tells the framework what to do, leaving the “how” to the template. I find this approach intuitive and elegant.
Now, let’s add more functionality.
Skills Search
Our search page needs a search field. As the user types, we’ll dynamically filter the skill list to display matching skills (case-insensitive).
Following Ractive’s approach, we start with the template:
| |
There are several important additions:
First, we added a <div> for our search box. We’ll connect this input to a variable using Ractive’s two-way binding feature. This allows retrieving input values without manual DOM manipulation. The interpolation mustache value="{{ skillFilter }}" binds the “skillFilter” variable to the input’s value attribute. Ractive automatically updates this variable by monitoring the input.
Second, as the comment indicates, instead of displaying all skills, we’ll use a JavaScript function skills() to filter the skill list, returning only those matching the user’s input:
| |
While clean and straightforward, you might wonder about performance implications. Calling a function on every input seems inefficient. However, Ractive only re-renders necessary template parts (and calls their functions) when their dependencies (variables) change.
For the curious, a more elegant approach using a computed property exists, which I encourage you to explore.
The Results Page
With a functional skill list, let’s create the results view, displaying developers matching the selected skill.
Switching Between Views
We’ll implement two distinct views: one for the skill list and another for the developer results based on the selected skill.
First, we need to hide the skill list and display the selected skill as the heading when the user clicks a skill. Conversely, the skill view should allow returning to the skill list.
Here’s the first step:
| |
We’ve made several changes:
- We’ve moved the existing list view into a partial. Partials are reusable template chunks we’ll include elsewhere.
- To make skills clickable, we use proxy events. This lets us react to physical events (like “on-click”) and proxy them to logical events (like “select-skill”) with arguments (in this case, the skill name).
- _ (Note: An alternative syntax, method calls, achieves the same.)_
- We introduce a variable,
currentSkill, to store the selected skill name (or an empty string if none). - We define another partial to display the
currentSkilland a “CLOSE” link to deselect the skill.
In the JavaScript, we subscribe to the “select-skill” and “deselect-skill” events, updating currentSkill (and skillFilter):
| |
Listing Developers
With the skill view prepared, let’s populate it with a list of matching developers:
| |
We’ve added an iteration section to the skillView partial, iterating over the result of a new skillDevelopers function. This function will return an array of developers matching the selected skill. For each developer, we render a panel displaying their name. (While I could use the implicit form {{name}} and let Ractive traverse the context chain, I prefer being explicit. More on contexts and references can be found in Ractive’s documentation documentation.)
Here’s the implementation of skillDevelopers():
| |
Enhancing Developer Entries
Let’s add more details and a photo to each developer’s entry:
| |
This utilizes Bootstrap’s features without introducing new Ractive concepts.
Displaying Clickable Developer Skills
Finally, let’s display each developer’s skills as clickable links leading to their respective skill views.
This functionality mirrors our existing clickable skill list. To avoid redundancy, we’ll leverage partials for reusability.
(Note: Ractive offers a more advanced approach for reusable view components called components, which we won’t cover here for simplicity.)
Here’s how we achieve this using partials (without writing additional JavaScript!):
| |
Since the developer object from our “DB” already contains the skills list, we only need to modify the template:
- Move the skill label rendering to a separate partial.
- Reuse this partial in both the main skill list and the developer’s skill iteration.
This provides clickable skill labels throughout our app, leading to the relevant skill view.
Adding a Preloader
Our app is functional, but we’ll add a preloading animation while resources load, enhancing the user experience.
| |
The trick is simple:
- Add content (a Bootstrap progress bar in this case, but it could be any loading indicator) directly within the “root” element.
- This content is displayed immediately as it doesn’t depend on JavaScript.
- Once the Ractive app initializes, it overwrites the “root” element’s content with the rendered template, effectively removing the preloader.
This achieves a smooth loading experience with minimal code.
Conclusion
We’ve built a fairly comprehensive application with minimal code: a searchable, dynamically updated skill list, navigation to skill views, and developer listings with clickable skills. All of this is achieved in under 80 lines of HTML and 40 lines of JavaScript. This demonstrates the power, elegance, and simplicity of Ractive.
You can experience the working application here and access the complete source code here.
This article only scratches the surface of Ractive’s capabilities. I encourage you to dive into the Ractive’s 60 second setup and explore its full potential.