简体   繁体   English

React表格不向Rails应用程序中的Postgres提交值

[英]React form not submitting values to Postgres in Rails app

I have a rails app with React installed via Webpacker. 我有一个通过Webpacker安装了React的Rails应用程序。 I'm adding a couple of dynamic fields to an existing form, but I'm not getting the values submitted to the database. 我向现有表单中添加了两个动态字段,但没有将值提交给数据库。 The non-react fields are submitting ok, and there's no errors. 未反应的字段提交正常,没有错误。

I have a different number fields displayed, depending on the option selected. 根据选择的选项,我将显示不同的数字字段。 I understood that the below in my react component: 我了解我的React组件中的以下内容:

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

would equate to rails: 相当于铁轨:

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

Is that too simplistic? 太简单了吗? Am I fundamentally missing something? 我从根本上缺少什么吗?

app/javascript/BlendSelector/beans.jsx 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 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 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 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

And I'm using the component in a Rails form by calling <div id="blend-type-component"></div> : 我通过调用<div id="blend-type-component"></div>以Rails形式使用该组件:

app/views/roasts/_form.html.erb 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>

I believe the main problem is that your SingleOrigin component isn't actually doing any submitting. 我相信主要的问题是您的SingleOrigin组件实际上没有进行任何提交。 Here's a modified version of the component with handleSubmit events: 这是带有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>
    );
  }
}

Also, you want to use the form element to make full use of React's state features. 另外,您想使用form元素来充分利用React的状态功能。 To read more on Forms, see this doc article . 要阅读有关Forms的更多信息,请参阅此文档文章 You'll want to modify your other components likewise to handle submission of the form data. 您将同样想要修改其他组件以处理表单数据的提交。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM