Я уже некоторое время задавал итерации этого вопроса, но с большой помощью сообщества SO я почти добился, чтобы он заработал. Итак, во-первых, спасибо!

У меня есть форма для создания нового student_group, и я использую гем Cocoon:

<%= form_for @student_group do |f| %>

  <p>
    The name of this group is 
    <span class="field form_field"><%= f.text_field :name %></span>
    and it is a/an 
    <span class="field dropdown"><%= f.select :type_of_group, [["select a group type", ""], "young learners class (0-6)", "primary class (7-12)", "secondary class (13-17)", "adult class (18+)", "children's sport team", "adult's sport team"]  %></span>       
  </p>

  <p>
    There are 
    <span id="nos" class="field dropdown"><%= f.select :number_of_students, (0..60) %></span>
    students in this group.   
  </p>


  <table id="students_form_table">
    <tbody>
      <!-- https://stackoverflow.com/questions/11445831/how-to-submit-multiple-new-items-via-rails-3-2-mass-assignment -->
      <%= f.fields_for :students, @student, child_index: @student do |builder| %>
        <%= render "student_fields", :f => builder %>
      <% end %>
    </tbody>    
  </table>

  <p>
    <%= f.submit "Submit", :class => 'big_button round unselectable'%>
  </p>

<% end %>

И партиал student_fields:

<tr class="nested-fields">
  <td id="student_name" class="field form_field"><%= f.text_field :name, placeholder: "Student name" %></td>
  <td id="student_gender" class="field dropdown"><%= f.select :gender, [["select a gender", ""],'Female', 'Male', 'Transgender'] %></td>
  <td id="remove_link"><%= link_to_remove_association "remove student", f %></td>
</tr>

Теперь суть вопроса:

У меня есть следующий файл .js для динамического добавления правильного количества полей учеников в форму:

var row_i = 0;

function emptyRow() {
row_i++;
this.obj = $("<tr></tr>");
this.obj.append('<td id="student_name" class="field form_field"><input id="student_group_students_attributes___Student:0x00000103c4ead8__name" name="student_group[students_attributes][#&lt;Student:0x00000103c4ead8&gt;][name]" type="text" /></td>');
this.obj.append('<td id="student_gender" class="field dropdown"><select id="student_group_students_attributes___Student:0x00000103c4ead8__gender" name="student_group[students_attributes][#&lt;Student:0x00000103c4ead8&gt;][gender]"><option value="">select a gender</option><option value="Female">Female</option><option value="Male">Male</option><option value="Transgender">Transgender</option></select></td>');
this.obj.append(' <td id="remove_link"><input id="student_group_students_attributes___Student:0x00000103c4ead8___destroy" name="student_group[students_attributes][#&lt;Student:0x00000103c4ead8&gt;][_destroy]" type="hidden" /><a href="#" class="remove_fields dynamic">remove student</a></td>')
}

function refresh(new_count) {
  //how many students we have got?
  console.log("New count= " + new_count);
  if (new_count > 0) {
    $('#students_form_table').show();
  } 
  else {
    $('#students_form_table').hide();
  }

 var old_count = parseInt($('tbody').children().length);
   console.log("Old count= " + old_count);
   //calculates difference between rows needed/rows current
 var rows_difference = parseInt(new_count) - old_count;
   console.log("Rows diff= " + rows_difference);
   //if we have rows to add
 if (rows_difference > 0) {
   for (var i = 0; i < rows_difference; i++)
   $('tbody').append((new emptyRow()).obj);
 } else if (rows_difference < 0) //we need to remove rows ..
 {
   var index_start = old_count + rows_difference + 1;
   console.log("Index start= " + index_start);
   $('tr:gt(' + index_start + ')').remove();
   row_i += rows_difference;
 }
}

$(document).ready(function () {
  //hide table by default
  $('#students_form_table').hide();

  $('#nos').change(function () {
    var opt=$('#nos option:selected');
    refresh(opt.text());
  })

});

Таким образом, эта форма почти работает - все форматируется правильно, и когда я выбираю количество учеников «x», создаются формы учеников «x» - однако из-за этого -

function emptyRow() {
  row_i++;
  this.obj = $("<tr></tr>");
  this.obj.append('<td id="student_name" class="field form_field"><input id="student_group_students_attributes___Student:0x00000103c4ead8__name" name="student_group[students_attributes][#&lt;Student:0x00000103c4ead8&gt;][name]" type="text" /></td>');
  this.obj.append('<td id="student_gender" class="field dropdown"><select id="student_group_students_attributes___Student:0x00000103c4ead8__gender" name="student_group[students_attributes][#&lt;Student:0x00000103c4ead8&gt;][gender]"><option value="">select a gender</option><option value="Female">Female</option><option value="Male">Male</option><option value="Transgender">Transgender</option></select></td>');
  this.obj.append(' <td id="remove_link"><input id="student_group_students_attributes___Student:0x00000103c4ead8___destroy" name="student_group[students_attributes][#&lt;Student:0x00000103c4ead8&gt;][_destroy]" type="hidden" /><a href="#" class="remove_fields dynamic">remove student</a></td>')
}

... поля отображаются неправильно - они не создают скрытых экземпляров новых полей учеников. Я понимаю, что проблема заключается в хэше в части id / name HTML-кода, сгенерированного рельсами, но я не уверен, как его заменить, чтобы это сработало. самое близкое, что я пришел, - это попытаться адаптировать coffeescript из этого site, но мне не удалось заставить его работать.

Итак, как динамически создавать новые формы для моделей с помощью jquery?

РЕДАКТИРОВАТЬ . На самом деле я только что понял, что первая и последняя формы будут правильно сохранены - то есть, если я добавлю восемь студентов, student1 и student8 будут внесены в базу данных, а остальные - нет. это меня только больше смущает: /

ИЗМЕНИТЬ 2 : я нашел этот jquery api под названием 'serialize' в контексте этот вопрос, и я думаю, что это может быть то, что мне нужно, но возникли проблемы с его адаптацией. Помоги мне!

1
dax 8 Июл 2013 в 17:03

1 ответ

Лучший ответ

Понял!

Пробовал много чего, но вот что в итоге сработало:

student_groups_controller.rb #create

def create
  @params = params[:student_group][:students_attributes]
  @student_group = @user.student_groups.build(params[:student_group])
    if @student_group.save
      ###   RE: 'defensive coding' http://stackoverflow.com/questions/14502508/undefined-method-for-nilnilclass-when-pushing-values-to-an-array  
      if @params.present?
        ### http://stackoverflow.com/questions/11355820/rails-3-2-iterate-through-an-array
        @params.each do |student|
          @student_group.students.create(name:"#{student[:name]}", gender: "#{student[:gender]}")
        end
      end    
      # new subject path
      redirect_to class_path(@student_group), flash: { success: "#{@student_group.name} has been added successfully" }   
    else
      @title = "Create a new group"
      flash.now[:error] = "Something's gone wrong.  Please try again!"
      render 'new' 
    end  
end

Соответствующий раздел _groups_form.html.rb

<table id="students_form_table">
  <tbody>
    <!-- http://stackoverflow.com/questions/11445831/how-to-submit-multiple-new-items-via-rails-3-2-mass-assignment -->
    <%= fields_for 'student_group[students_attributes][]', @student, index: nil do |builder| %>
        <%= render "student_fields", :f => builder %>
    <% end %>
    </tbody>    
</table>

И, наконец, соответствующая часть student_groups.js:

function emptyRow() {
  row_i++;
  this.obj = $("<tr></tr>");
  this.obj.append('<td id="student_name" class="field form_field"><input id="student_group_students_attributes__name" name="student_group[students_attributes][][name]" placeholder="Student name" size="30" type="text" /></td>');
  this.obj.append('<td id="student_gender" class="field dropdown"><select id="student_group_students_attributes__gender" name="student_group[students_attributes][][gender]"><option value="">select a gender</option><option value="Female">Female</option><option value="Male">Male</option><option value="Transgender">Transgender</option></select></td>');
  this.obj.append('<td id="remove_link"><input id="student_group_students_attributes___destroy" name="student_group[students_attributes][][_destroy]" type="hidden" /><a href="#" class="remove_fields dynamic">remove student</a></td>')
}
1
dax 11 Июл 2013 в 15:09