React.js: submit form programmatically does not trigger onSubmit event

时间:2016-06-18 20:13:25

标签: forms reactjs onsubmit

I want to submit a React form after a click on a link.

To do so I need to submit the form programmatically if the link is clicked.

my problem is : onSubmit handler is not being fired after the form submit .

Here is a code snipped that I made for this purpose:

var MyForm = React.createClass({
  handleSubmit: function(e){
    console.log('Form submited');
     e.preventDefault();
  },
  submitForm : function(e){
    this.refs.formToSubmit.submit();
  },
  render: function() {
    return (
    <form ref="formToSubmit" onSubmit={this.handleSubmit}>
    <input name='myInput'/>
    <a onClick={this.submitForm}>Validate</a>
    </form>);
  }
});

ReactDOM.render(
  <MyForm name="World" />,
  document.getElementById('container')
);

The handleSubmit is not invoked and the default behavior is executed (the form being submitted). Is this a ReactJs bug or a normal behavior? Is there a way to get the onSubmit handler invoked ?

8 个答案:

答案 0 :(得分:6)

我成功了。单击后触发handleSubmit。希望这会有所帮助。

<form onSubmit={this.handleSubmit} ref={el => this.form = el}>
    <a onClick={() => { this.form.dispatch(new Event('submit'))}}>Validate</a>
</form>

从这里找到:https://github.com/facebook/react/issues/6796

答案 1 :(得分:5)

2021 年更新

接受的答案中的解决方案对我不起作用,所以我决定更新这个主题。

React 16(及更早版本)

在原始答案中,缺少 Event 构造函数的第二个参数。如果没有 {cancelable: true} 参数,则无法运行 preventDefault() 方法。

<div>
    <form onSubmit={e => e.preventDefault()} ref={ref => this.form = ref}>
        <input name="tmp" />
    </form>

    <button onClick={e => this.form.dispatchEvent(
        new Event("submit", { cancelable: true })
    )}>
        Submit form
    </button>
</div>

React 17(未来可能还有更新的版本)

在当前版本的 React (17) 中,事件委托发生了相当大的变化(详情here)。因此,上面的解决方案需要一个小的改进才能使用这个版本的库。此更改是 bubbles: true 参数。工作代码如下所示:

<div>
    <form onSubmit={e => e.preventDefault()} ref={ref => this.form = ref}>
        <input name="tmp" />
    </form>

    <button onClick={e => this.form.dispatchEvent(
        new Event("submit", { cancelable: true, bubbles: true })
    )}>
        Submit form
    </button>
</div>

答案 2 :(得分:4)

您当前的onSubmit必然会触发React SyntheticEvent,而不会触发原生表单提交事件。这解释了为什么this.refs.formToSubmit.submit();没有触发你的处理程序。据我所知,试图手动触发SyntheticEvent不是推荐或值得追求的。

我认为实现此目的的惯用方法是将JSX / HTML结构化为使用提交类型<button><input>。其中任何一个都会触发您的handleSubmit处理程序。在我看来,它将降低复杂性,巩固您的处理程序,并且似乎是您最好的解决方案。

e.g。

  • <input type="submit" value="Validate" />
  • <button type="submit">Validate</button>

答案 3 :(得分:2)

我遇到了同样的问题,但无法修复。无论我做了什么,执行document.querySelector('form').submit()都不会触发onSubmit处理程序。我尝试包含一个不可见的<input type="submit">,但仍然.submit()不会触发它。所以我只是更改为保持隐形提交(style="display:none"),然后对该隐形提交按钮执行.click(),令人惊讶的是它甚至可以与display:none一起使用。我只在Firefox中测试过。

答案 4 :(得分:2)

默认情况下,您不应期望表单引用为submit添加额外的回调。当使用编程方式设置DOM元素refs等内容时,这将是框架的糟糕设计。

您应该使用ref以您想要的任何顺序实例化所需的所有事件,而不是依赖于ref的无法实现的内部实现[由form实例化时元素]。

这有效:

this.refs.formToSubmit.onSubmit();
this.refs.formToSubmit.submit();

实际submit应始终排在最后。

答案 5 :(得分:0)

您应该使用带有提交类型的输入标记而不是锚标记,因为锚标记不会触发提交事件。

main

答案 6 :(得分:0)

这与React无关。这是DOM API的“功能”:.submit()方法实际上不会触发submit事件,它也不会触发输入验证。参见http://codetheory.in/javascript-fire-onsubmit-by-calling-form-submit/

根据建议,可能的解决方法是创建一个提交按钮,并以编程方式在其上调用.click()。 或者,您可以使用submit以编程方式创建new Event()事件,并使用.dispatchEvent()进行调度。但是,new Event()在IE中不可用。

答案 7 :(得分:0)

您宁愿使用dispatchEvent(new Event('submit'))而不是submit()。只需相应地更换即可。