【问题标题】:React form not submitting values to Postgres in Rails app反应表单未在 Rails 应用程序中向 Postgres 提交值
【发布时间】:2018-01-17 23:16:09
【问题描述】:

我有一个通过 Webpacker 安装的带有 React 的 rails 应用程序。我正在向现有表单添加几个动态字段,但我没有收到提交到数据库的值。非反应字段提交正常,没有错误。

我会显示不同的数字字段,具体取决于所选的选项。我明白我的反应组件中的以下内容:

<input type="text_field" id="roast_country" name="roast[country]" className="form-control" />

相当于轨道:

  <div class="form-group">
    <%= form.label :country, class: 'control-label' %>
    <%= form.text_field :country, id: :roast_country, class: "form-control" %>
  </div>

是不是太简单了?我从根本上错过了什么吗?

app/javascript/BlendSelector/beans.jsx

import React from 'react'
import ReactDom from 'react-dom'
import BlendSelector from 'BlendSelector'

document.addEventListener('turbolinks:load', function () {
  var element = document.getElementById("blend-type-component");
  ReactDom.render(<BlendSelector />, element);
});

app/javascript/packs/index.jsx

import React          from 'react'

import NoBlend        from './NoBlend';
import SingleOrigin   from './SingleOrigin';
import TwoBlend       from './TwoBlend';
import ThreeBlend     from './ThreeBlend';

class BlendSelector extends React.Component {
  constructor(props) {
    super(props);
    this.onBlendSelected = this.onBlendSelected.bind(this);
    this.state = { selectedBlend: null };
  }

  onBlendSelected(event) {
    this.setState({ selectedBlend: event.target.value });
  }

  render() {
    let BlendCustomComponent = NoBlend;
    if (this.state.selectedBlend == "Single Origin") {
      BlendCustomComponent = SingleOrigin;
    } else if (this.state.selectedBlend == "Two Country Blend") {
      BlendCustomComponent = TwoBlend;
    }  else if (this.state.selectedBlend == "Three Country Blend") {
      BlendCustomComponent = ThreeBlend;
    }
    return (
      <div>
        <div className="field">
          <label htmlFor="roast_beans">Beans</label>
          <select id="beans" onChange={this.onBlendSelected} name="roast[beans]">
            <option value="">Select a blend type</option>
            <option value="Single Origin">Single Origin</option>
            <option value="Two Country Blend">Two Country Blend</option>
            <option value="Three Country Blend">Three Country Blend</option>
          </select>
        </div>
        <BlendCustomComponent />
      </div>
    );
  }
}
export default BlendSelector

app/javascript/BlendSelector/SingleOrigin.jsx

import React from 'react'

class SingleOrigin extends React.Component {
  render() {
    return (
      <div>
        <div className="form-group">
          <label htmlFor="country">Country</label>
          <input type="text_field" id="roast_country" name="roast[country]" className="form-control" />
        </div>
        <div className="form-group">
          <label htmlFor="region">Region</label>
          <input type="text_field" id="roast_region" name="roast[region]" className="form-control" />
        </div>
      </div>
    );
  }
}
export default SingleOrigin

roasts_controller.rb

def roast_params
  params.require(:roast).permit(:roaster, :name, :country, :region, :country2, :region2, :country3, :region3, :bestfor, :beans, :roast, :tastingnotes, :notes, :slug)
end

我正在通过调用 &lt;div id="blend-type-component"&gt;&lt;/div&gt; 以 Rails 表单使用该组件:

app/views/roasts/_form.html.erb

<%= form_with(model: roast, local: true) do |form| %>
  <% if roast.errors.any? %>
    <div id="error_explanation">
      <div class="alert alert-danger" role="alert">
      <h2><%= pluralize(roast.errors.count, "error") %> prohibited this roast from being saved:</h2>

      <ul>
      <% roast.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  </div>
  <% end %>

<form>


  <div class="field form-group">
    <%= form.label :roaster, class: 'control-label' %>
    <%= form.text_field :roaster, id: :roast_roaster, class: "form-control" %>
  </div>

  <div class="form-group">
    <%= form.label :name, class: 'control-label' %>
    <%= form.text_field :name, id: :roast_name, class: "form-control" %>
  </div>

<div id="blend-type-component"></div>

  <div class="form-group">
    <%= form.label :bestfor, "Best for", class: 'control-label' %><br />
    <%= form.select :bestfor, [ 'Espresso','Filter' ], :prompt => 'Select One', id: :roast_bestfor, class: "form-control" %>
  </div>

  <div class="form-group">
    <%= form.label :roast, class: 'control-label' %><br />
    <%= form.select :roast, [ 'Light','Medium','Dark' ], :prompt => 'Select One', id: :roast_roast, class: "form-control" %>
  </div>

  <div class="form-group">
    <%= form.label :tastingnotes, "Tasting Notes (separate with commas, e.g chocolate, citrus)", class: 'control-label' %><br  />
    <%= form.text_area :tastingnotes, id: :roast_tastingnotes, class: "form-control" %>
  </div>
<br />

  <div class="actions">
    <%= form.submit class: "btn btn-primary" %>
  </div>
<% end %>

</form>

【问题讨论】:

    标签: ruby-on-rails reactjs


    【解决方案1】:

    我认为主要问题是您的 SingleOrigin 组件实际上并没有进行任何提交。下面是带有 handleSubmit 事件的组件的修改版本:

    class SingleOrigin extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          value: ''
        };
    
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }
    
      handleChange(event) {
        // handle multiple inputs
        const target = event.target;
        const value = target.value;
        const name = target.name;
    
        this.setState({
          [name]: value // set the key as the name of the input element
        });
    
        console.log(this.state);
      }
    
      handleSubmit(event) {
        // Modify this to handle your actual submits to Postgres.
        alert('The following was submitted: ' + this.state.country + ', ' + this.state.region);
        event.preventDefault();
      }
    
      render() {
        return (
          <form onSubmit={this.handleSubmit}>
            <div className="form-group">
              <label htmlFor="country">Country</label>
              {/* I modified your input names to just the keys so you can use the ES6 computed property name syntax, when you do your handle submit code, send it to the proper variables. */}
              <input type="text_field" id="roast_country" name="country" className="form-control" onChange={this.handleChange} />
            </div>
            <div className="form-group">
              <label htmlFor="region">Region</label>
              <input type="text_field" id="roast_region" name="region" className="form-control" onChange={this.handleChange}/>
            </div>
            <input type="submit" value="Submit" />
          </form>
        );
      }
    }
    

    另外,你想使用 form 元素来充分利用 React 的状态特性。要了解有关表单的更多信息,请参阅this doc article。您需要同样修改其他组件以处理表单数据的提交。

    【讨论】:

    • 谢谢安东尼奥。我应该说我正在使用现有导轨形式的组件。刚刚将该代码添加到原始帖子中。
    猜你喜欢
    • 2022-07-05
    • 2015-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    • 2021-09-14
    • 2020-11-11
    • 1970-01-01
    相关资源
    最近更新 更多