Draggable / formeo

Drag & Drop Form Builder
http://draggable.github.io/formeo/
MIT License
530 stars 198 forks source link

Rudimentary React Example #328

Open uzegonemad opened 2 years ago

uzegonemad commented 2 years ago

(I am unable to offer any support for this.) This is a simple example for adding formeo to React in 2022. This definitely doesn't cover all use cases but should be enough to get you started. If you use file inputs or buttons you'll probably need to modify/add to the addEventListener.

I am unable to offer any support for this. Seriously, you are on your own.

ReactFormeo.js

import React, { useEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom';
import { FormeoEditor, FormeoRenderer } from 'formeo'
import 'formeo/dist/formeo.min.css';// from 'formeo';
import PropTypes from 'prop-types';

function ReactFormeoEditor(props) {
    const ref = useRef();

    useEffect(() => {
        const options = {
            editorContainer: ReactDOM.findDOMNode(ref.current),
            events: {
                onUpdate: (event) => {
                    try {
                        props.onChange(event.detail);
                    } catch(e) {}
                },
            },
        };
        new FormeoEditor(options, props.formData || null);
    }, []);

    return (
        <div ref={ref} style={{width: '100%'}} />
    )
}
ReactFormeoEditor.propTypes = {
    formData: PropTypes.string,
    onChange: PropTypes.func,
};

function ReactFormeoRenderer(props) {
    const renderRef = useRef();
    const [formValues, setFormValues] = useState({});
    let renderer = null;

    useEffect(() => {
        const options = {
            renderContainer: ReactDOM.findDOMNode(renderRef.current),
        };

        const formData = typeof props.formData === 'string' ? JSON.parse(props.formData) : formData;

        renderer = new FormeoRenderer(options);
        renderer.render(formData);

        const fields = renderRef.current.querySelectorAll('input, select, textarea');
        for(const field of fields) {
            field.addEventListener('change', (e) => {
                setFormValues({
                    ...formValues,
                    [field.name]: field.value,
                });
            });
        }
    }, []);

    useEffect(() => {
        try {
            props.onChange(formValues);
        } catch(e) {}
    }, [formValues]);

    return (
        <div ref={renderRef} style={{width: '100%'}} />
    )
}
ReactFormeoRenderer.propTypes = {
    formData: PropTypes.string.isRequired,
    onChange: PropTypes.func,
};

export {
    ReactFormeoEditor,
    ReactFormeoRenderer,
};

Usage

import {ReactFormeoEditor, ReactFormeoRenderer} from "./ReactFormeo";

...

render() {
    // Editor
    <ReactFormeoEditor onChange={(formData) => console.log(formData)} />
    //or
    <ReactFormeoEditor formData={formData} onChange={(formData) => console.log(formData)} />

    // Renderer
    <ReactFormeoRenderer formData={formData} onChange={(formValue) => console.log(formValue)} />
}