简体   繁体   中英

How to load rails form partials with jquery and submit as one form

In an attempt to make my rails html more readable I extracted several parts of it into partials. I then use jquery to render the partials. The issue is that now the form has come all "unhooked" so to speak, meaning when I attempt to submit the form it acts as though the partials don't exist. I suspect I am not understanding quite how forms work, because it seems like in other answers related to this the form builder isn't even addressed.

This SO question seems related to what I want to do but I think I'm too inexperienced to grasp it properly

The code I have thus far goes as follows:

/assets/javascripts/work_order.js
$(document).ready(function(){
$('.best_in_place').best_in_place();
$('#work_order_dueDate').datepicker();
$.datepicker.setDefaults({ dateFormat: 'dd-mm-yy'});
var selection_made = false
$('#work_order_project_type_id').change(function(){
    if (!selection_made){
        selection_made = true
        var selection = $(this).find('option:selected').text();
        if (selection == "Variable Data Mailing"){
            $.get('/presort_informations/new');
            $.get('/printing_instructions/new');
        }
        else if (selection == "Mailing"){
            $.get('/presort_informations/new');            
        }
        else if (selection == "Print Job"){
            $.get('/printing_instructions/new');            
        }
    }
  });
});

and then

/views/work_orders/_form.html.erb

<%= form_for(@workorder) do |f| %>

  <% if @workorder.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@workorder.errors.count, "error") %> prohibited this workorder from being saved:</h2>

      <ul>
      <% @workorder.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>
  <fieldset class="general-info">
    <legend>General</legend>
    <div class="col-md-12">
      <div class="col-md-3">
        <div class="form-group">
          <%= f.label :Job_Title, class: "control-label" %>
          <%= f.text_field :title, class:"form-control" %>
        </div>

        <div class="form-group">
          <%= f.label :Project_Type, class: "control-label" %>
          <%= f.collection_select(:project_type_id, ProjectType.all, :id, :name, {:prompt => true}, {:class => "form-control"}) %>
        </div>
      </div>
    <div class="col-md-3">
      <div class="form-group">
        <%= f.label :Rep, class: "control-label" %>
        <%= f.text_field :rep, class:"form-control" %>
      </div>
      <div class="form-group">
        <%= f.label :Labels, class: "control-label" %>
        <%= f.collection_select(:labels_id, Labels.all, :id, :name, {:prompt => true}, {:class => "form-control"}) %>
      </div>
    </div>
    <div class="col-md-3">
      <div class= "form-group">
          <%= f.label :Due_Date, class: "control-label" %>
          <%= f.text_field :dueDate, class: "form-control" %>
      </div>
      <div class="form-group">
        <%= f.label :Project_Description, class: "control-label" %>
        <%= f.text_area :projectDescription,  class: "form-control" %>
      </div>
    </div>
  </div>
  </fieldset>
  <fieldset class="presort-information">

  </fieldset>
  <div class="col-md-6 printing">

  </div>
  <fieldset class="production-details">
    <legend>Production</legend>
    <%= f.fields_for :production_details, ProductionDetails.new do |ff| %>

    <%end%>
  </fieldset>
  <%= f.hidden_field(:number, :value => @workorder.number) %>
  <%= f.hidden_field(:client_id, :value => @workorder.client_id) %>
  <%= f.submit(class: "btn btn-default") %>
<% end %>

and as an example of one of the partials:

/app/views/presort_informations/new.js.erb
$('.presort-information').append( '<%= j render("presort_informations/form") %>' );

/app/views/presort_informations/_form.html.erb
<legend>Mailing</legend>
<%= fields_for :presort_information, PresortInformation.new do |ff| %>
.
.
.
<% end %>

I'm not really sure how to tie this all together so that I can load the partials based on the select box, but then submit them all as one form.

Edit: I found this SO question which deals with the same issue, but I suspect that because I am rendering the partial after the page has been loaded I no longer have access to the form builder variable.

$('.presort-information').append( '<%= j render("presort_informations/form", f: f) %>' );

gives an undefined variable error when it's called. I'm still not sure how to bridge this gap between jquery and rails.

Turns out it was a relatively (if new conceptually to me) easy fix First, load each DOM partial in along with hidden sections.

<%= form_for(@workorder) do |f| %>
  <% if @workorder.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@workorder.errors.count, "error") %> prohibited this workorder from being saved:</h2>
      <ul>
      <% @workorder.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <fieldset id="general-info-partial">
    <%=render("genInfo", f: f)%>
  </fieldset>
  <fieldset id="presort-information-partial">
    <%=render("presort_informations/form",  f: f)%>
  </fieldset>
  <div class="col-md-6">
    <fieldset id="printing-information-partial">
    <%=render("printing_instructions/form", f: f)%>
    </fieldset>
  </div>
  <fieldset id="production-details-partial">
    <%=render("production_details/form", f: f) %>
  </fieldset>
  <%= f.hidden_field(:number, :value => @workorder.number) %>
  <%= f.hidden_field(:client_id, :value => @workorder.client_id) %>
  <input type="submit" value="Submit" class="btn btn-default">
<% end %>

<div id="hidden-general-info" class="hidden"></div>

<div id="hidden-presort-information" class="hidden"></div>

<div id="hidden-printing-information" class="hidden"></div>

Then the Javascript to move things in and out of the form:

$(document).ready(function(){
$('.best_in_place').best_in_place();
$('#work_order_dueDate').datepicker();
$.datepicker.setDefaults({ dateFormat: 'dd-mm-yy'});

var presortFields = $('#presort-information-partial');
var printingFields = $('#printing-information-partial');

var presortHidden = $('#hidden-presort-information');
var printingHidden = $('#hidden-printing-information');

presortHidden.html(presortFields.html());
presortFields.html('');

printingHidden.html(printingFields.html());
printingFields.html('');

$('#work_order_project_type_id').change(function(){

        var selection = $(this).find('option:selected').text();

        if (selection == "Variable Data Mailing"){
            if (printingFields.html() == '' && presortFields.html() == ''){
                printingFields.html(printingHidden.html()).hide().slideDown();
                presortFields.html(presortHidden.html()).hide().slideDown();
            }
            else if(printingFields.html() == '' && !(presortFields.html() == '')){
                printingFields.html(printingHidden.html()).hide().slideDown();
            }
            else if(!(printingFields.html() == '') && presortFields.html() == ''){
                presortFields.html(presortHidden.html()).hide().slideDown();
            }
        }
        else if (selection == "Mailing"){
            if(!(printingFields.html() == '')){
                printingFields.slideUp();
                printingFields.html('');
                presortFields.html(presortHidden.html()).hide().slideDown();

            }else{
                presortFields.html(presortHidden.html()).hide().slideDown();
            }

        }
        else if (selection == "Print Job"){
            printingFields.html(printingHidden.html()).hide().slideDown();
            presortFields.slideUp();
            presortFields.html('');
        }
});

Basically, the idea was to load everything in as if I was going to use it all, and then just move the partials into a hidden section of the DOM, and then use JS to put them back in when the user makes a selection

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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