0

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.

buratino
  • 1,408
  • 2
  • 17
  • 40
  • Is something preventing this theoretical from working? And if so are there any error messages in the console? Reading it over I'd say "onSubmit" might be a problematic name for a prop because it's the React version of `onsubmit`. Maybe try replacing it with something like "whenSubmit". – Sydney Y Feb 29 '20 at 02:20
  • @SydneyY Something is preventing it from working, but I am unsure what -- though I can confirm the name of `onSubmit` is not the issue. – buratino Feb 29 '20 at 23:56

1 Answers1

2

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.

Zachary Haber
  • 10,376
  • 1
  • 17
  • 31
  • So the Form.Dropdown has to have its onChange set explicitly? I didn't think that would be the case because the other Form components in my actual codebase default to the onChange specified in the parent
    attributes
    – buratino Apr 28 '20 at 02:58
  • 1
    Looks like dropdowns indeed have to have their own onChange handler. I haven't actually seen onChange as a prop on the Form element. I think that that might be just a base 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 base. https://stackoverflow.com/questions/10760847/entire-form-onchange has an example of it. – Zachary Haber Apr 28 '20 at 03:04
  • Would you mind editing that into the answer? I'll mark as complete and award the bounty when I am allowed to. – buratino Apr 28 '20 at 03:24
  • I added it to the answer and did a little reformatting while I was at it. – Zachary Haber Apr 28 '20 at 03:49