npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

iobroker.vis-jsontemplate

v4.2.0

Published

vis-jsontemplate

Downloads

195

Readme

JSONTemplate - Adapter to visualize JSON data and other data in Vis/Vis2

Logo

NPM version Downloads Number of Installations Current version in stable repository

NPM

Tests: Test and Release

Overview

Adapter to visualize JSON data and other data in Vis/Vis2. You can customize the output of the data with a template system. In the templates you can include HTML, CSS and Javascript.

The jsontemplate widget was previously available in the rssfeed (for vis1) and vis-2-widgets-ovarious adapters. The widgets will be removed from these adapters in the near future.

Installation

Install the adapter as normal from the stable repository. If you want to test new features or bug fixes you can also install the adapter from the beta repository. For Features and news, please see the Test and Support thread for this adapter in the iobroker forum.

After Installation the adapter should then be displayed in the adapter section in the iobroker. Sometimes it happens that the changes are not visible, especially with web changes (widgets / configuration dialog), the following command may have to be executed on the command line:

iobroker upload jsontemplate

In the right area in the line of the adapter, an instance can be added using the plus button

Configuration

This adapter does not have a configuration dialog in the admin area.

vis and widgets

The following widgets actually exists

  • JSON Template - you can define a custom template to show any JSON-Data in vis.

JSON Template

Using this widget, any data point with JSON data can be displayed as desired. The display is done using a template format, which can be thought of as a combined form of HTML code + JavaScript + CSS + special tags that control the display of the JSON attributes. JSONTemplate now supports async calls with await.

| Setting | description | | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | json_template | The template can be used to determine the appearance of the JSON data. All valid HTML tags (including CSS attributes in style tags) can be used in the template. There are also special tags within which the JSON data is displayed and JavaScript instructions can be executed. | | json_oid | Selection of the data point with the corresponding JSON data. | | json_dpCount | Number of data points to be made available in the template. | | json_dp | Datapoint ID to be made available. |

For details on the template system, see chapter Template based on examples

Available data objects in the template:

| object/variable | description | | --------------- | ------------------------------------------------------------------------ | | widgetID | widgetID of the widget. | | data | JSON object referenced by the datapoint in json_oid. | | dp | Array of the datapoint data, referenced by the additional datapoints | | widget | internal widget data. object with all available widget settings | | style | internal style data. object with all available widget style informations |

The additional datapoints can be accessed by A) the name of the datapoint

<%- dp["0_userdata.0.test"] %>
<%- dp["0_userdata.0.abc"] %>

B) Indexnumber of the datapoint (the number always start with 0)

<%- dp[Object.keys(dp)[0]] %>
<%- dp[Object.keys(dp)[1]] %>

Example output of data, widget and style in the template

<%- JSON
    .stringify(style, null, 4)
    .replace(/\n/g, '<br>')
    .replace(/ /g, '&nbsp;'); %>

Advanced use case

In the examples above, only the pure output was covered. The template can now also be enriched with HTML tags to achieve a specific layout. Here is an example:

<h3>Output</h3>
<style>
    .mycssclassproperty {
        color: green;
    }
    .mycssclassdata {
        color: red;
    }
</style>
<% for (var prop in data.oneobject) { %>
<div>
    <span class="mycssclassproperty"><%- "data.oneobject." + prop + " = " %></span>
    <span class="mycssclassdata"><%- data.oneobject[prop] %></span>
</div>
<% } %>

Result:

    data.oneobject.attribute1 = 1
    data.oneobject.attribute2 = 2

(In Markdown colors aren't visible)

Use case for async calls

Block 1:

call sendToAsync Function with await. This example calls a test function in the admin adapter.

Block 2:

stringify the result and output to html

Block 3:

definition of the sendToAsync function

<% req = await sendToAsync("admin.0","selectSendTo",{test:"test"}); %>
<%- JSON.stringify(req) %>
<% async function sendToAsync(instance, command, sendData) {
    console.log(`sendToAsync ${command} ${sendData}`);
    return new Promise((resolve, reject) => {
        try {
            vis.conn.sendTo(instance, command, sendData, function (receiveData) {
                resolve(receiveData);
            });
        } catch (error) {
            reject(error);
        }
    });
} %>

Result:

[{"label":"Afghanistan","value":"AF"},{"label":"Åland Islands","value":"AX"},{"label":"Albania","value":"AL"}]

Use case for a database-supported task list

Introduction

This use case describes how to visualize and interactively modify a to-do list from a MySQL database in ioBroker. The focus is on implementing a simple status change via a button click. This concept serves as a Proof of Concept (PoC) and can be included in future documentation.


Database Structure (MySQL)

First, a MySQL database named test is created. It contains a table test with the following fields:

  • id: Unique ID for each entry
  • todo: Title of the to-do entry
  • action: Status of the entry (0 = in progress, 1 = completed)
SQL Code for Table Creation

CREATE TABLE `test` (
`id` int(11) NOT NULL,
`todo` varchar(100) NOT NULL,
`action` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `test` (`id`, `todo`, `action`) VALUES
(1, 'Todo 1', 0),
(2, 'Todo 2', 1),
(3, 'Todo 3', 1),
(4, 'Todo 4', 0);

ALTER TABLE `test`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `id` (`id`),
ADD KEY `idx` (`id`);

ALTER TABLE `test`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
COMMIT;


Integration into ioBroker
SQL Adapter

To interact with the database, the ioBroker.sql adapter is required. It is configured accordingly to connect to the MySQL database test. Note that ioBroker automatically creates its own structures in the database to store history data points.

JSONTemplate Widget

For visualization, we use the JSONTemplate widget.

Integration into VIS

We place the JSONTemplate widget and fill in the following fields:

Template Code
<style>
    .btn {
        width: 100%;
    }
</style>
<table>
    <tr>
        <th>ID</th>
        <th>Todo</th>
        <th>Action</th>
    </tr>
    <% let todos = await getTodo(); for (let i = 0; i < todos.length; i++) { let todo = todos[i]; %>
    <tr>
        <td><%- todo.id %></td>
        <td><%- todo.todo %></td>
        <td><%- getButton(todo.id, todo.action) %></td>
    </tr>
    <% } %>
</table>

<script>
    window.vis-jsontemplate = { clicktodo: clicktodo };

    function getButton(id, action) {
        let text = action === 0 ? 'In Progress' : 'Completed';
        return `<button class="btn" onclick="window.vis-jsontemplate.clicktodo(this)" data-id="${id}" data-action="${action}">${text}</button>`;
    }

    function clicktodo(el) {
        let id = el.dataset.id;
        let action = el.dataset.action;
        let nextAction = action == 0 ? 1 : 0;
        setAction(id, nextAction);
    }

    async function getTodo() {
        let req = await sendToAsync('sql.0', 'query', 'SELECT * FROM test.test');
        return req.result;
    }

    async function setAction(id, action) {
        await sendToAsync('sql.0', 'query', `UPDATE test.test SET action = ${action} WHERE id = ${id}`);
        vis.setValue('local_trigger', Math.random());
    }

    async function sendToAsync(instance, command, sendData) {
        return new Promise((resolve, reject) => {
            try {
                vis.conn.sendTo(instance, command, sendData, receiveData => resolve(receiveData));
            } catch (error) {
                reject(error);
            }
        });
    }
</script>

Data Point for Refreshing Content

To ensure updates are reflected after a status change, we add the following local data point:

local_trigger

This data point does not need to be explicitly created, as local_? data points are processed internally within VIS (see vis documentation).

Code Explanation
Template Structure

| Line | Content | | ----- | ---------------------------------------------------------------------- | | 1-5 | CSS styles for button appearance | | 6-11 | Table header with columns ID, Todo, Action | | 12-16 | Fetching data from the MySQL database using getTodo() | | 17-21 | Loop to display to-do entries with buttons | | 23-28 | Global reference of the clicktodo() function | | 30-37 | getButton() function to create a button with the current status | | 38-44 | clicktodo() function to change the status via button click | | 45-48 | getTodo() function to fetch data via the SQL adapter | | 49-52 | setAction() function to update the database entry | | 53-58 | sendToAsync() function to use async/await with vis.conn.sendTo() |

Templatesystem

Important note for the template system in vis

In vis, all object notations in the following form are recognized and replaced as bindings.

Therefore, the opening and closing brackets of all object notations must be placed on separate lines:

Incorrect:

{ "a": 1, "b": 2 }

Correct

{
    "a": 1,
    "b": 2
}

Tags

The template system works with certain tags. The tags used mean the following

| tag | description | | ----- | ------------------------------------------------------------------- | | <%= | The content of the contained expression / variable will be escaped. | | <%- | The content of the contained expression / variable is unescaped. | | <% | No output, is used for enclosed javascript instructions | | %> | is generally a closing tag to complete one of the previous ones |

Everything that is outside of these tags is displayed exactly as it is or if it is HTML interpreted as HTML. Within the template you have 2 predefined variables available

Example object

For all the following examples the following json is used.

{
    "onearray": ["one", "two"],
    "oneobject": {
        "attribute1": 1,
        "attribute2": 2
    },
    "onenumber": 123,
    "onetext": "onetwothree"
}

Attributes could be output as follows

Template:

<%- data.onenumber %>
<%- data.onetext %>

Result:

    123 onetwothree

Arrays can be accessed via an index. The index always starts with 0. However, there are also fake arrays where the index does not start with 0 or even consists of text. Here the rules for objects apply. In the example above, this would be

Template:

<%- data.onearray[0] %>
<%- data.onearray[1] %>

Result:

    one two

If you try to output an array directly without an index, the template outputs all elements separated by commas

Template:

<%- data.onearray %>

Result:

    one,two

Arrays can also consist of a collection of objects. The example here contains only a simple array. An example of arrays with objects will be given later.

Template:

<% for (var i = 0; i < data.onearray.length ; i++ ) { %>
<%- data.onearray[i] %>
<% } %>

Result:

    one two

Objects can contain individual attributes, arrays or objects again. This means that JSON data can be nested to any depth.

Attributes of an object can be addressed using dot notation or bracket notation. The dot notation only works if the attribute conforms to certain naming conventions (first character must be a letter, rest numbers or letters or underscore). The bracket notation also works for attributes that do not conform to the naming convention.

Dot notation:

Template:

<%- data.oneobject.attribute1 %>

Bracket notation:

Template:

<%- data.oneobject["attribute1"] %>

Result for both examples:

    1

Loop over the attributes of an object

Template:

<% for (var prop in data.oneobject) { %>
<%- "data.oneobject." + prop + " = " + data.oneobject[prop] %>
<% } %>

Result:

    data.oneobject.attribute1 = 1
    data.oneobject.attribute2 = 2

Development and Debugging

Vis1 Widgets

  • Install dev-server
  • Start dev-server with --noStart option
  • On first start install additional adapter web and vis1
  • start vscode launch configuration "vis-1 editor"
  • if widgets are not available, upload adapter in expert mode on the adapter page
  • now you can set breakpoints in vscode in the jsontemplate.js file
  • if you change something in the js file the source must be compiled to the dist folder with npm run build-vis1widgets command.
  • the dev-server uploads the changed files to iobroker, but for vis1 you have to execute the iob visdebug command to reload the widgets
  • to translate additional entries in en.json use the translate-widgets-vis1 command

Vis2 Widgets

  • Install dev-server
  • Open a new vscode window (2. instance)
  • clone vis2 repository
  • follow the instructions in the readme of the vis2 repository in chapter Development and Debugging. you don't have to fork the repository. we only need a running instance of the vis2 adapter
  • start vis 2 with npm run start
  • back in in the vscode instance of this adapter
  • Start dev-server with --noStart option
  • start vscode launch configuration "vis-2 editor"
  • now you can set breakpoints in vscode in the jsontemplate.js file
  • if you change something you don't have to do anything else, because vite supports hot reload. sometimes it is useful to reload vis2 with F5
  • to translate additional entries in en.json use the translate-widgets-vis2 command

Todo

  • tbd

Changelog

4.2.0 (2025-11-14)

  • Improve documentation for the object notation in a template
  • fix some translations
  • align attribute name to vis1
  • add widget data to the available template objects in vis2
  • add style and widget object to the available template objects in vis1
  • improve documentation

4.1.3 (2025-11-03)

  • fix race condition if more than one widget use the same datapoint
  • switch to trusted publishing

4.1.2 (2025-09-13)

  • new try of publish

4.1.0 (2025-09-12)

  • rename widgetset of the vis2 widget

4.0.2 (2025-08-28)

  • remove v4.0.0 from io-package

4.0.1 (2025-08-28)

  • move vis1 and vis2 widgets to vis-jsontemplate adapter

License

MIT License

Copyright (c) 2021-2025 oweitman [email protected]

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.