LiveJSON provides LiveView-like updating for JSON objects rather than DOM elements.

Overview

live_json

GitHub Hex.pm WIP

LiveJSON provides LiveView-like updating for JSON objects rather than DOM elements. It works within your existing LiveViews - just use push_patch as you would assign or push_event. Only the changes to the data are sent over the wire, not the whole object every time, so it can end up being quite fast indeed.

This may be useful for front-end frameworks, data visualization, games and anything else where you need dynamically updated data that lives outside of the DOM, like mobile apps.

Example

def handle_info({:new_data_to_visualize, new_data} = _event, socket) do
  {:noreply, 
    socket
    |> push_patch("viz_data", new_data)
  }
end

Now, check your JS console:

window.viz_data
// {1: ["a"], 2: ["b"] ... 99999: ["zzzzz"]}

The data is automatically updated, but if you check the WebSocket, you'll see that only the data that changed has been sent.

Problem / Solution

Phoenix LiveView is awesome for automatically updating your webpage's DOM. However, it doesn't work as well for data objects, since it only works at the DOM level out of the box, meaning any complex data objects need to be entirely re-sent every time. So, if you load your JS app's data via a templated script tag, LiveView will rewrite the whole tag, not just the elements that changed, which means sending a lot of data over the wire and other headaches on the client-side.

LiveJSON is a simple alternative - it uses Jsondiff/JSON-Patch (RFC 6902) to only send the delta of the data, which is then patched client side, similar to how morphdom works on the DOM.

Installation

First, the usual:

0.1.0"} ] end">
def deps do
  [
    {:live_json, "~> 0.1.0"}
  ]
end

Next, you'll need to set up the hooks in your app.js:

// Import the JS..
import { createLiveJsonHooks } from 'live_json';
const liveJsonHooks = createLiveJsonHooks();

// ..then define all your hooks..
const Hooks = {
  // your other hooks
  // ...
  ...liveJsonHooks,
};

// ..and use them!
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {
  hooks: Hooks,
  params: {_csrf_token: csrfToken},
});

If your app uses an assets/package.json, you'll also need to add:

{
  "dependencies": {
    "live_json": "file:../deps/live_json"
  }
}

and then npm install.

Finally, you'll need to put a tag for the hook somewhere on the related Heex:

">
<div id="lj" phx-hook="LiveJSON">div>

Usage

There are only two commands: initialize and push_patch.

On your mount, initialize the state:

def mount(_params, _, socket) do
  data = get_your_data()

  {:ok,
    socket
    |> LiveJson.initialize("dataviz", data)
  }
end

Then, to send updated data:

def handle_info({:new_data_to_visualize, new_data} = _event, socket) do
  {:noreply, 
    socket
    |> LiveJson.push_patch("dataviz", new_data)
  }
end

Or, in RFC 6902 mode:

def handle_info({:new_data_to_visualize, new_data} = _event, socket) do
  {:noreply, 
    socket
    |> LiveJson.push_patch("dataviz", new_data, :rfc)
  }
end

In your JS console window.dataviz will now hold the updated data for this example. Also note that dataviz is just an example - you can call it whatever you want the object to be called, and you can have multiple objects on the same page.

Each init/patch also emits a global event, which you can listen to with:

window.addEventListener('dataviz_initialized', event => doSomethingOnInit(), false)
window.addEventListener('dataviz_patch', event => doSomethingOnPatch(), false)

Capabilities and Limitations

Fast and Non-Standard

By default, LiveJSON uses jsondiff for diffing/patching data. This is fast, but isn't defined by an RFC and subject to change, and may not have a client available on all plaforms. This is the best solution if you just want performance on a page you control.

Slower and Standardized

Alternately, you can use :rfc mode to use JSON-Patch (RFC 6902) style patching. This is (currently) slower, but will mean that your data can be used by a larger number of consumers, such as a mobile applications.

TODO

  • Tests
  • Example Projects
  • Perf Testing, with Numbers
  • Elixirify Code

Standing on the Shoulders of Giants

There actually isn't very much code in this repo, just a convenient interface and application of work done by other people:

Other people have tried to solve this problem in other ways, but this was the solution that I wanted for my application. If you'd like to explore alternate approaches see:

The project structure for building and packaging hooks comes from:

License

2022, Rich Jones, MIT License

You might also like...

This is a basic app that allows user add/remove books from a list of books. It was created by using JavaScript arrays and objects to dynamically modify the DOM.

Awesome-Books This application lets you compile a dynamic collection of books using JavaScript. It is a single page app. You enter your book title & a

Oct 24, 2022

Solid Forms provides several form control objects useful for making working with forms easier.

Solid Forms Solid Forms provides several form control objects useful for making working with forms easier. Demos and examples below. # solidjs yarn ad

Jan 2, 2023

JCS (JSON Canonicalization Scheme), JSON digests, and JSON Merkle hashes

JSON Hash This package contains the following JSON utilties for Deno: digest.ts provides cryptographic hash digests of JSON trees. It guarantee that d

Sep 2, 2022

Package fetcher is a bot messenger which gather npm packages by uploading either a json file (package.json) or a picture representing package.json. To continue...

package-fetcher Ce projet contient un boilerplate pour un bot messenger et l'executable Windows ngrok qui va permettre de créer un tunnel https pour c

Mar 29, 2022

javascript library to convert a list of objects to a nested json output format, depending on the names in the list

formToNestedJson javascript "library" to convert a list of objects to a nested json output format, depending on the names in the list Basic usage Give

Aug 2, 2021

A library for updating your immutable state in JavaScript applications.

ionic-bond A library for updating immutable states in JavaScript applications. Introduction This library is a very lightweight replacement for immer,

Nov 15, 2022

This is a demo of updating a map to show air quality data for the user’s current location using Next.js Advanced Middleware, powered by Netlify Edge Functions.

Show Local Air Quality Based on the User's Location Use AQI data to show the air quality near the current user. This is built using Next.js Advanced M

Nov 4, 2022

A simple App for creating, deleting and Updating To Do lists.

To-do-list-demo: Add & Remove Learning objectives Use webpack to bundle JavaScript. Learn how to use proper ES6 syntax. Use ES6 modules to write modul

Oct 18, 2022

Custom Vitest matchers to test the state of the DOM, forked from jest-dom.

vitest-dom Custom Vitest matchers to test the state of the DOM This library is a fork of @testing-library/jest-dom. It shares that library's implement

Dec 16, 2022
Comments
Owner
Rich Jones
Î̢̢ ̢̢̢̢̢̛ͪ̄̂å̢̢̢̢̢̢̜͐͢͝m̢̢ͦ ̢̢ͭa̢̢̝ ̢̢̢̢̢̢̗̱̩̆̅h̢̢̢ͩͭṵ̢̢̢͒ṃ̵̢̢̢̢̢̢ͮ͌̇a̢̢̢̢̢̟͂̌͠n̢̢̢̘ͨ ̵̢̢͉b̢̢̢̢̞͡ͅu̢̢̢̢̢̢͒͌͌́̕g̢͏̢ ̴̢̢̢̢ͤ͢r̢̢̄҉̢̢̱e̢̢͑p̢̢̒o̢̢̢̢̹r̷̢̢̢͊t̢̢͑.
Rich Jones
Create a deep copy of a set of matched elements with the dynamic state of all form elements copied to the cloned elements.

jq-deepest-copy FUNCTION: Create a deep copy of a set of matched elements while preserving the dynamic state of any matched form elements. Example Use

Michael Coughlin 5 Oct 28, 2022
Json-parser - A parser for json-objects without dependencies

Json Parser This is a experimental tool that I create for educational purposes, it's based in the jq works With this tool you can parse json-like stri

Gabriel Guerra 1 Jan 3, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
⏱️ Ultra-simple Stopwatch App using Phoenix LiveView

Stopwatch Create new phoenix "barebone" Phonenix application: mix phx.new stopwatch --no-mailer --no-dashboard --no-gettext --no-ecto Create folders a

dwyl 9 Nov 5, 2022
Google Chrome release and version info as JSON (self updating)

chrome-versions Self updating repository to store Google Chrome release and version info as JSON. Windows macOS Linux Android TL;DR Use a CDN to fetch

berstend̡̲̫̹̠̖͚͓̔̄̓̐̄͛̀͘ 9 Dec 15, 2022
📃 Fold up DOM elements like paper

OriDomi Fold up DOM elements like paper Dan Motzenbecker, MIT License @dcmotz Visit oridomi.com for examples, documentation and notes. Read the annota

Dan Motzenbecker 2.4k Dec 14, 2022
This project will be a basic website that allows users to add/remove books from a list. The main objective is to understand how to use JavaScript objects and arrays and dynamically modify the DOM and add basic events.

Awesome-books Awesome Books This project will be a basic website that allows users to add/remove books from a list. This project is part of the Microv

Aleksandra Ujvari 10 Oct 3, 2022
Basic website that allows users to add/remove books from a list. Achieved using JavaScript objects and arrays, dynamically modifying the DOM and adding basic events.

Awesome Books Basic website that allows users to add/remove books from a list. Achieved using JavaScript objects and arrays, dynamically modifying the

Didier Peran Ganthier 6 Dec 20, 2022