Why sp-picker does not respond on change?

I created some sp-picker, but I can’t find why it not respond onChange.
Maybe I do it something wrong, but it not even log onChange.
I need to set value of textfield based on picker chose.
Also I tried with addEventListener but I got error during debugging that "Cannot read properties of null (reading ‘addEventListener’)…

Please help

Screenshot 2023-09-28 at 11.53.30

const Home = () => {
    var officeArray =["Office 1", "Office 2", "Office 3"]

    // document.querySelector("#emp").addEventListener("change",console.log("selected new") )

    function officeHandler() {
        console.log("selected new")
        document.querySelector("#emp").value = "Marko"

    }
    return(
        <>
            <div className="toolName">Home</div>
            <div className="board">

                <sp-label>Office:</sp-label>

                <sp-picker id="office" size="m" placeholder="Select office"  onChange={()=>officeHandler()}>
                    <sp-menu>
                        { 
                            officeArray.map((e,index) => {
                                return(
                                    <sp-menu-item key={index} size="m">{e}</sp-menu-item>
                                )
                            })
                        }
                    </sp-menu>
                </sp-picker>

                <sp-label>Employee:</sp-label>
                <sp-textfield id="emp" size="m"></sp-textfield>

             </div>
        </>
    )
}

export default Home;

Hey man, had a similar issue when building a previous plugin. I was having issues getting the value from the slider when it was updated. This worked for me:

const slider = document.querySelector(‘sp-slider’);

const endListener = ({ target }) => {
target.addEventListener(‘input’, startListener);
target.removeEventListener(‘input’, streamListener);
target.removeEventListener(‘change’, endListener);
console.log(target.value);
globalThis.scaleSetting = slider.value;
};

const streamListener = ({ target }) => {

};

const startListener = ({ target }) => {
target.removeEventListener(‘input’, startListener);
target.addEventListener(‘input’, streamListener);
target.addEventListener(‘change’, endListener);
};

slider.addEventListener(‘input’, startListener);
console.log(slider.value);

Hopefully replacing the slider object with your picker object might work

1 Like

You need some Wrapper Component. Example and some explaining can be found in this topic, but I ended up using wc-react

import {wrapWc} from "wc-react";

export default () => {
    const SpCheckbox = wrapWc("sp-checkbox")

    return (
        <SpCheckbox
            onChange={(e) => func()}
        >Checkbox</SpCheckbox>
    )
}

Same with sp-picker

1 Like

Thank you guys. Second one works great. :clap:

@Karmalakas could you please help, how to resolve previous situation in case that fields use data from json? For example I make this json about office’s and I need to change values of textfileds based on selection value. I make this solution with for/if block, but I am sure that there is a better way, but I don’t know how. Thanks in advance

/// data.json

[
{
    "office":"Management",
    "responsable":"Marko",
    "seats":"1"
},
{
    "office":"Design",
    "responsable":"Alex",
    "seats":"10"
}
]

/// home.jsx

import {wrapWc} from "wc-react";
import data from "../components/data.json"

const Home = () => {
    const SpPicker = wrapWc("sp-picker")
    function officeHandler() {
        for(var i=0; i<=data.length; i++){
            if( data[i].office === document.querySelector("#office").value){
                document.querySelector("#responsable").setAttribute("value",data[i].responsable)
                document.querySelector("#seats").setAttribute("value",data[i].seats)
            }
        }
    }
    return(
        <>
            <div className="toolName">Home</div>
            <div className="board">

                <sp-label>Office:</sp-label>
                <SpPicker id="office" size="m" placeholder="Select office"  onChange={()=>officeHandler()}>
                    <sp-menu>
                        { 
                            data.map((e,index) => {
                                return(
                                    <sp-menu-item key={index} size="m">{e.office}</sp-menu-item>
                                )
                            })
                        }
                    </sp-menu>
                </SpPicker>
                <sp-label>Responsable:</sp-label>
                <sp-textfield id="responsable" size="m"></sp-textfield>
                <sp-label>Seats:</sp-label>
                <sp-textfield id="seats" size="m"></sp-textfield>
             </div>
        </>
    )
}

export default Home;

Screenshot 2023-10-03 at 07.56.14

You can check starter plugin how state is used there for each color. In your case it probably would be something like:

import { useState } from "react";
import {wrapWc} from "wc-react";
import data from "../components/data.json"

const Home = () => {
    const SpPicker = wrapWc("sp-picker")

    const [office, setOffice] = useState({});

    return(
        <>
            <div className="toolName">Home</div>
            <div className="board">

                <sp-label>Office:</sp-label>
                <SpPicker size="m" placeholder="Select office"  onChange={(evt) => setOffice(data[evt.target.value])}>
                    <sp-menu>
                        { 
                            data.map((e,index) => {
                                return(
                                    <sp-menu-item key={index} size="m" value={index}>{e.office}</sp-menu-item>
                                )
                            })
                        }
                    </sp-menu>
                </SpPicker>
                <sp-label>Responsable:</sp-label>
                <sp-textfield size="m" value={office.responsable || ""}></sp-textfield>
                <sp-label>Seats:</sp-label>
                <sp-textfield size="m" value={office.seats || ""}></sp-textfield>
             </div>
        </>
    )
}

export default Home;

Keep in mind, that I didn’t test this and wrote directly here in the forum reply box :sweat_smile: So it might be wrong in some syntax or something, but the basic idea should be clear

1 Like

Thanks, It works perfectly. Now I understand how to use usestate properly :raised_hands:

1 Like