#debounce form input update with API callback

8 messages · Page 1 of 1 (latest)

rose valley
#

In this example I'm using createResource, I've obviously wrote my own code to handle debounce and setting and getting of the values. Does SolidJS already have this behavior baked in somewhere? - or is the above solution the only way to achieve such a method?

#

sorry for the snake case variables, its a preference and a bad habbit

#

I have around 60 form fields ... it's worrying me that I may need to be explicit about 60 getters and setters

rose valley
#
export class ResourceForm {
    constructor(fetcher, mutater, refetcher, apiSetFunc, apiSetArgs) {
        if (!fetcher) throw new Error('ResourceForm: fetcher is required');
        if (!mutater) throw new Error('ResourceForm: mutater is required');
        if (!refetcher) throw new Error('ResourceForm: refetcher is required');

        this.f = fetcher;
        this.m = mutater;
        this.r = refetcher;

        this.apiSetFunc = apiSetFunc;
        this.apiSetArgs = apiSetArgs;
    }

    getValue(key) {
        return this.f.loading ? null : this.f()[key];
    }

    setValue(key, value) {
        this.m((ogv) => {
            ogv[key] = value;
            if (this.apiSetFunc) {
                this.apiSetFunc(Object.values(this.apiSetArgs), ogv);
            }
            return ogv
        });
    }

}
#
    const client_form = new ResourceForm(
        client_fetch,
        client_mutate,
        client_re_fetch,
        apiSetClient,
        {
            client_id: url_params.client_id
        }
    );

    return (
        <div class={styles.App}>
            <form>
                <label for="first_name">First Name</label>
                <input
                    type="text"
                    id="first_name"
                    name="first_name"
                    value={client_form.getValue('first_name')}
                    onInput={debounce((e) => client_form.setValue('first_name', e.target.value))}
                />
            </form>
        </div>
    );
#

thoughts?

rose valley
#
import {createSignal} from "solid-js";

export class ResourceForm {
    __signal_registry__ = {};

    constructor(fetcher, mutater, refetcher, apiSetFunc, apiSetArgs) {
        if (!fetcher) throw new Error('ResourceForm: fetcher is required');
        if (!mutater) throw new Error('ResourceForm: mutater is required');
        if (!refetcher) throw new Error('ResourceForm: refetcher is required');

        this.f = fetcher;
        this.m = mutater;
        this.r = refetcher;

        this.apiSetFunc = apiSetFunc;
        this.apiSetArgs = apiSetArgs;
    }

    createSignal(key) {
        const [value, setValue] = createSignal(this.f()[key]);
        this.__signal_registry__[key] = {getter: value, setter: setValue};
    }

    getValue(key) {
        return this.f.loading ? null : this.f()[key];
    }

    setValue(key, value) {
        if (!this.__signal_registry__.hasOwnProperty(key)) {
            this.createSignal(key);
        }
        this.m((ogv) => {
            ogv[key] = value;
            if (this.apiSetFunc) {
                this.apiSetFunc(Object.values(this.apiSetArgs), ogv);
            }
            this.__signal_registry__[key].setter(value);
            return ogv
        });
    }

    watchValue(key) {
        if (!this.__signal_registry__.hasOwnProperty(key)) {
            this.createSignal(key);
        }
        return this.__signal_registry__[key].getter;
    }

    refresh() {
        this.r();
    }

}

Final version

#

🤷‍♂️ Seems to work