Zero-Dependency Reactive DOM from JSON Data – Sprout

Category: Javascript | June 4, 2025
Author:calebporzio
Views Total:24 views
Official Page:Go to website
Last Update:June 4, 2025
License:MIT

Preview:

Zero-Dependency Reactive DOM from JSON Data – Sprout

Description:

Sprout is a zero-dependency JavaScript library that transforms JSON data into reactive DOM elements. using native browser APIs.

It uses standard HTML <template> elements with data attributes to create reactive interfaces that automatically update when underlying data changes.

Features

  • Declarative Templates: Uses native HTML <template> elements with data attributes
  • Automatic Reactivity: Re-renders when data-json attribute changes
  • Minimal Bundle Size: Lightweight footprint for performance-conscious applications
  • Browser-Native: Leverages MutationObserver and template elements
  • Keyed Rendering: Efficient list updates with optional key-based diffing

How to use it:

1. Install Sprout and import it into your project.

# NPM
$ npm install @sprout-js/sprout
<script type="module">
  import '@sprout-js/sprout';
</script>

2. Create reactive templates using the is="🌱" attribute and data-json for data binding:

  • is="🌱": Identifies a <template> as a Sprout root component. This is where Sprout starts its work.
  • data-json: Supplies the JSON data string to the root template. Changes to this attribute trigger re-renders.
  • data-for="{item in items}": Iterates over an array. items should be an array in your data context, and item is the name you’ll use to reference each element in the loop. The special variable _ can be used to refer to the current data context. If your data-json is an array itself, data-for="{item in _}" iterates that array.
  • data-if="{condition}": Renders the content of the template if the condition evaluates to a truthy value.
  • data-unless="{condition}": Renders the content of the template if the condition evaluates to a falsy value.
  • data-key="{expression}": Provides a unique key for items in a data-for loop. This is crucial for performance and maintaining state if your list items can be reordered or have their own internal state. I’ve found that using a unique ID from your data (data-key="{item.id}") is generally the best practice here.
<template is="🌱" data-json='{"title": "User Dashboard", "users": [{"name": "Alice", "role": "admin"}, {"name": "Bob", "role": "user"}]}'>
  <div class="dashboard">
    <h1>{title}</h1>
    <template data-for="{user in users}">
      <div class="user-card {user.role}">
        <span>{user.name}</span>
        <template data-if="{user.role === 'admin'}">
          <badge>Admin</badge>
        </template>
      </div>
    </template>
  </div>
</template>

3. Sprout monitors the data-json attribute of the root template. If you update this attribute with a new JSON string, Sprout automatically re-renders the template.

const newData = [{ ... }];
templateElement.setAttribute('data-json', JSON.stringify(newData));

FAQs

Q: Can I nest Sprout templates within each other?
A: Yes, nested templates work as expected. Inner templates inherit the parent’s data context unless they define their own data-json attribute.

Q: What happens if JSON parsing fails?
A: Sprout includes basic error handling that falls back to rendering nothing if JSON.parse() throws. In production applications, I recommend validating data before setting the data-json attribute to avoid silent failures.

Q: Can I use async data or fetch results?
A: Absolutely. Fetch your data, stringify it, and set the data-json attribute. The library doesn’t care about data sources. I frequently use this pattern with API endpoints that return user lists or configuration objects.

Q: How do I handle form inputs and user interactions?
A: Sprout focuses on rendering, not event handling. Attach event listeners using standard DOM APIs after the template renders. The comment markers help identify the rendered content boundaries for event delegation patterns.

You Might Be Interested In:


Leave a Reply