Search code examples
reactjssemantic-ui

React form values not being displayed on form submission


Let's say I have some properties which can be equal to some possible options. I'll define these both in someConstants.js

const possibleOptions = [
    {key: '1', text: "some text 1", value: "some_text_1"},
    {key: '2', text:  "some text 2", value:  "some_text_2"},
];

const someProperties = {
    flags: []
};


export { someProperties, possibleOptions };

I want someProperties.flags to be updated by possibleOptions upon submission of the form someForm.js

import React from "react";
import { someProperties, possibleOptions } from "./someConstants";
import { Form } from "semantic-ui-react";
import "./styles.css";

class SomeForm extends React.Component {
    state = someProperties;

    handleSubmit = event => {
        event.preventDefault();
        this.props.onSubmit(this.state);
    };

    onChange = event => {
        const {
            target: { name, value }
        } = event;

        this.setState({
            [name]: value
        });
    };

    render() {
        return (
            <Form onSubmit={this.handleSubmit} onChange={this.onChange}>
                <Form.Dropdown
                    label="Flags"
                    placeholder="Flags"
                    name="flags"
                    fluid
                    multiple
                    search
                    selection
                    options={possibleOptions}
                />

                <Form.Button type="submit">Submit</Form.Button>
            </Form>
        );
    }
}

export { SomeForm };

These values will be displayed by showFlags.js

import React from "react";
import "./styles.css";

class ShowFlags extends React.Component {
    displayList = list => {
        return(
            <ol>
                {list.map(flag => (
                    <li key={flag}>{flag}</li>
                ))}
            </ol>
        );
    }

    render() {
        return (
            <div>
                {this.props.flagProps.flags}
            </div>
        );
    }
}

export { ShowFlags };

The interaction of these classes can be shown further in index.js

import React from "react";
import ReactDOM from "react-dom";
import { SomeForm } from "./someForm";
import { ShowFlags } from "./showFlags";

class App extends React.Component {
    state = {
        flagProps: {},
        submitted: false
    };

    handleSubmit = fields => {
        this.setState({
            flagProps: { ...fields },
            submitted: true
        });
        console.log("handleSubmit flagProps:" + this.state.flagProps);
    };

    render() {
        return (
            <>
                <div className="Section">
                    <div className="Title">flagProps form</div>
                    <SomeForm flagProps={this.state.flagProps} onSubmit={this.handleSubmit} />
                </div>
                <div className="Section">
                    <div className="Title">The result</div>
                    {this.state.submitted ? (
                        <ShowFlags flagProps={this.state.flagProps} />
                    ) : (
                        <div>Appears on submission.</div>
                    )}
                </div>
            </>
        );
    }
}

ReactDOM.render(<App />, document.getElementById("root"));

How can I achieve this? To summarize:

Current behavior I am able to choose options, but submission of the form does not yield any display. ShowFlags.render() shows nothing.

Desired behavior I am able to choose options, and those options are displayed by ShowFlags.render() upon submission of the form.

If it matters, this is using semantic-ui.


Solution

  • Here's your fixed code:

      onChange = (event, data) => {
        this.setState({
          [data.name]: data.value
        });
      };
    
      render() {
        return (
          <Form onSubmit={this.handleSubmit}>
            <Form.Dropdown
              label="Flags"
              placeholder="Flags"
              name="flags"
              fluid
              multiple
              search
              selection
              options={possibleOptions}
              value={this.state.flags}
              onChange={this.onChange}
            />
    
            <Form.Button type="submit">Submit</Form.Button>
          </Form>
        );
      }
    

    https://codesandbox.io/s/exciting-kare-31l7w?file=/src/SomeForm.jsx

    You forgot to apply the onChange handler to the Form.Dropdown in SomeForm, though the way semantic-ui-react works is that the change handlers have the props passed down to them as the second argument to the change function. Then the new value would be data.value.

    You also should set the value of the Form.Dropdown to be value={this.state.flags} so it's a fully controlled component since you are bringing it into state anyway.

    I also removed the Form's onChange handler as that doesn't affect the Dropdown at all. Semantic UI React (SUI) doesn't have it listed in their Form's Props.

    Having an onChange handler on the form is a html property rather than an SUI prop. Which would explain why it doesn't work for Dropdowns. As they don't have a normal input/select html element base. This would also mean that the normal SUI's data argument to the onChange handlers wouldn't exist, so you'd need to get the attributes directly off the element.

    Entire form onChange has an example of a form onChange handler, which looks to be very powerful for anything that has a base element that normally goes in a form.

    Base html elements being: input, select, and textarea.