Material-ui: TextItems between <form> tags submit the form on enter keypress.

Created on 13 Jan 2017  路  8Comments  路  Source: mui-org/material-ui

  • Material-UI: 0.16.6
  • React: 15.4.2
  • Browser: Chrome 55.0.2883.95 (64-bit)

Encapsulating Textfield between enter.

This works fine:
~~~




~~~

But when replacing the outer

Not that this is a bug needs to be fixed pers茅, but it might be a good idea to put a warning in the docs somewhere for oldSkool guys like me, who have learned to always put input-items between form tags.

Most helpful comment

Here is how i would implement your component :

import React, { Component, PropTypes } from 'react';
import { browserHistory } from 'react-router';

// Form elements
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';

export default class ExperimentForm extends Component {

  constructor(props) {
    super(props);
    const { title = '', description = '' } = this.props.experiment
    this.state = { title, description };
  }

  handleChange = (event, value) => this.setState({ [event.target.name]: value });

  submit = (event) => {
    event.preventDefault();
    this.props.saveData({
      title: this.state.title.trim(),
      description: this.state.description.trim()
    });
  };

  render() {
    const { title, description } = this.state
    return (
      <form onSubmit={this.submit}>
        <TextField
          name="title"
          floatingLabelText="Title"
          value={title}
          onChange={this.handleChange}
          fullWidth
          /><br />
        <TextField
          name="description"
          multiLine
          floatingLabelText='Description'
          value={description}
          onChange={this.handleChange}
          fullWidth
          /><br/><br/>
        <RaisedButton
          type="submit"
          label="Save" 
          primary
        />
        <RaisedButton
          type="cancel"
          label="Cancel" 
          onClick={browserHistory.goBack}
          style={{ marginLeft: 10 }}
        />
      </form>
    );
  }
}

All 8 comments

try adding event.preventDefault in your onChange handler ?

Doesn't prevent the problem. For completeness, here is the complete component including javascript functions:

~~~jsx
import React, { Component, PropTypes } from 'react';
import { browserHistory } from 'react-router';

// Form elements
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';

export default class ExperimentForm extends Component {

constructor(props){
    super(props);
    this.state = {
        title: this.props.experiment ? this.props.experiment.title :'',
        description: this.props.experiment ? this.props.experiment.description:''
    };
}

handleChange = (event, value) => {
    event.preventDefault();
    this.setState({ [event.target.name]: value });
};

submit = ( event ) => {
    event.preventDefault();
    const data = {
        title: this.state.title.trim(),
        description: this.state.description.trim()
    }
    this.props.saveData(data);
};

render() {
    return (
        <form>
            <TextField
                name="title"
                floatingLabelText="Title"
                value={this.state.title}
                onChange={this.handleChange}
                fullWidth={true}
            /><br />
            <TextField
                name="description"
                multiLine={true}
                floatingLabelText='Description'
                value={this.state.description}
                onChange={this.handleChange}
                fullWidth={true}
            /><br/><br/>
            <RaisedButton 
                label="Save" 
                primary={true}
                onClick={this.submit}
            />
            <RaisedButton 
                label="Cancel" 
                onClick={browserHistory.goBack}
                style={{marginLeft: 10}}
            />
        </form>
    );
}

}
~~~

Here is how i would implement your component :

import React, { Component, PropTypes } from 'react';
import { browserHistory } from 'react-router';

// Form elements
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';

export default class ExperimentForm extends Component {

  constructor(props) {
    super(props);
    const { title = '', description = '' } = this.props.experiment
    this.state = { title, description };
  }

  handleChange = (event, value) => this.setState({ [event.target.name]: value });

  submit = (event) => {
    event.preventDefault();
    this.props.saveData({
      title: this.state.title.trim(),
      description: this.state.description.trim()
    });
  };

  render() {
    const { title, description } = this.state
    return (
      <form onSubmit={this.submit}>
        <TextField
          name="title"
          floatingLabelText="Title"
          value={title}
          onChange={this.handleChange}
          fullWidth
          /><br />
        <TextField
          name="description"
          multiLine
          floatingLabelText='Description'
          value={description}
          onChange={this.handleChange}
          fullWidth
          /><br/><br/>
        <RaisedButton
          type="submit"
          label="Save" 
          primary
        />
        <RaisedButton
          type="cancel"
          label="Cancel" 
          onClick={browserHistory.goBack}
          style={{ marginLeft: 10 }}
        />
      </form>
    );
  }
}

That's super informative, thanks! I'm still getting the hang of these expanders (although I used them a lot in Python). Didn't know you could pass default values too.
I can't see if you changed anything critical that prevents the unwanted submission on enter problem, or did you just tidy up the code?

Ah wait, I do now. You set the type of the submit button to submit and attached the submit function to form's onSubmit handler.

That works!

Exactly
This is a basic feature of html

Also, in the case of Material-UI, use onTouchTap instead of onClick if applicable.

You can also replace those ugly
with styling, or wrap components in a div (since they are display: block)

Still can't find a solution for this. Whenever I hit enter, instead of calling this.handleSubmit, it seems to try to do its own form submit.

Component:

handleSubmit(e) {
    e.preventDefault();
    const email = this.emailInput.input.value;

    if (email.match(/\w{1,}\.?\w{0,}@gmail\.com/g)) {
      this.props.resetPassword(email);
      this.props.toggleResetPassword(false);
    }

    this.props.toggleNotification(true, 'Email is invalid.', 'error');
    return null;
  }

render() {
    return (
      <section className="reset-password">
        <form
          className="reset-pass-form"
          onSubmit={this.handleSubmit}
        >
          <div className="reset-pass-header">
            <h2>Reset Password</h2>
            <button
              className="x-close"
              onClick={this.closeResetPasswordModule}
            >
              X
            </button>
          </div>
          <TextField
            hintText="Email"
            ref={(ref) => { this.emailInput = ref; }}
            onTouchTap={this.handleSubmit}
          />
          <RaisedButton
            type="submit"
            label="Submit"
          />
        </form>
      </section>
    );
  }
}

using onClick or onTouchTap does not solve the issue

I ma having this issue, but only if my multiline text area is composed within another MUI component

Was this page helpful?
0 / 5 - 0 ratings

Related issues

TimoRuetten picture TimoRuetten  路  3Comments

activatedgeek picture activatedgeek  路  3Comments

pola88 picture pola88  路  3Comments

rbozan picture rbozan  路  3Comments

revskill10 picture revskill10  路  3Comments