Reacting On Page Button Click In SolidJS

2023-01-07
HTML
Javascript
Frontend
SolidJS
programming

What

SolidJS is a nice little reactive framework that allows to add reactivity to the page without the need to have the whole page rendered by it. Not that it cannot be, but my use case was specifically that - to add a dynamic element to a page without changing rendering engine or writing much raw JS.

It all works nicely (example below), but I was confused how to change variable state when I click on buttons that are not rendered by SolidJS - because I wanted to have most of the page in Markdown/HTML, as it's easier to manage.

It could be done via assigning functions wo window object like e.g.

    window.myFunc = () => {...}

inside SolidJS code, and then call them from onclick() handler in button elements, but that would pollute the window namespace so not nice.

Instead, there's a way to find all required DOM elements and add event listeners to them like so:

    function sliderClickSetter(event) {
        setSliderValue(event.target.value);
    }

    document.querySelectorAll('button.set-slider').forEach((item) => item.addEventListener('click', sliderClickSetter));

Here I select them by element type and style class (button.set-slider) and use element's value, but it could be ID selector as well (and querySelector instead of querySelectorAll, as it'd return just one element).

Example

Buttons in HTML code:

Set slider or

Rendered by SolidJS:


Code

HTML part (without styles)

    <div class="frame">
        Set slider <button class="set-slider" value="90">to 90</button> or <button class="set-slider" value="20">to 20</button>
    </div>
    
    <div class="frame" id="slider-app"></div>

Javascript

    import { createSignal } from "https://cdn.skypack.dev/solid-js";
    import { render } from "https://cdn.skypack.dev/solid-js/web";
    import html from "https://cdn.skypack.dev/solid-js/html";

    const [sliderValue, setSliderValue] = createSignal(50);

    const SliderApp = () => {
    
        const valueFromEvent = (event) => {
            setSliderValue(parseInt(event.target.value));
        };
    
        return html`
            <input type="range" id="slider" min="0" max="100" value="${sliderValue}" onchange="${valueFromEvent}">
            <p>Slider value: <em>${sliderValue}</em></p>
        `;
    };
    render(SliderApp, document.getElementById("slider-app"));

    function sliderClickSetter(event) {
        setSliderValue(event.target.value);
    }

    document.querySelectorAll('button.set-slider').forEach((item) => item.addEventListener('click', sliderClickSetter));