如何在jQuery中动态添加嵌套属性 [英] how to dynamically add nested attributes in rails with jquery

查看:245
本文介绍了如何在jQuery中动态添加嵌套属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在问这个问题的一段时间 - 但是从SO社区获得了很多帮助,我几乎可以正常工作。首先,谢谢!



我有一个表单来创建一个新的 student_group 并使用 Cocoon code> gem:

 <%= form_for @student_group do | f | %GT; 

< p>
该组的名称是
< span class =field form_field><%= f.text_field:name%>< / span>
,它是一个/一个
< span class =字段下拉列表><%= f.select:type_of_group,[[选择一个组类型,],年轻学习者班(0-6),小学班(7-12),中学班(13-17),成人班(18+),儿童运动队,成人运动队] %GT;< /跨度>
< / p>

< p>

< span id =nosclass =field dropdown><%= f.select:number_of_students,(0..60)%>< / span>
这组学生。
< / p>


< 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 | %GT;
<%=呈现student_fields,:f =>助剂%>
<%end%>
< / tbody>
< / table>

< p>
<%= f.submitSubmit,:class => 'big_button round unselectable'%>
< / p>

<%end%>

和'student_fields'部分:

 < tr class =nested-fields> 
< td id =student_nameclass =field form_field><%= f.text_field:name,placeholder:Student name%>< / td>
< td id =student_genderclass =field dropdown><%= f.select:gender,[[select a gender,],'Female','Male', '变性人']%>< / td>
< td id =remove_link><%= link_to_remove_associationremove student,f%>< / td>
< / tr>

现在问题的核心:

我有以下的.js文件来动态地将正确数量的学生字段添加到表单中:

  var row_i = 0; 

函数emptyRow(){
row_i ++;
this.obj = $(< tr>< / tr>);
this.obj.append('< td id =student_nameclass =field form_field>< input id =student_group_students_attributes ___ Student:0x00000103c4ead8__namename =student_group [students_attributes] [#& lt;学生:0x00000103c4ead8& gt;] [name]type =text/>< / td>');
this.obj.append('< td id =student_genderclass =field dropdown>< select id =student_group_students_attributes ___ Student:0x00000103c4ead8__gendername =student_group [students_attributes] [#& lt;学生:0x00000103c4ead8& gt;] [性别]><选项值=>选择性别< / option>< option value =女性>女性< / option>< option value =男性>男性< / option>< /选择>< / td>');选择值=变性人>变性人< /选项>
this.obj.append('< td id =remove_link>< input id =student_group_students_attributes ___ Student:0x00000103c4ead8 ___ destroyname =student_group [students_attributes] [#& lt; Student:0x00000103c4ead8& gt; ] [_ destroy]type =hidden/>< a href =#class =remove_fields dynamic> remove student< / a>< / td>')
}

函数刷新(new_count){
//我们有多少学生?
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);
//计算所需行数/行之间的差值current
var rows_difference = parseInt(new_count) - old_count;
console.log(Rows diff =+ rows_difference);
//如果我们有行添加
if(rows_difference> 0){
for(var i = 0; i< rows_difference; i ++)
$('tbody ').append((new emptyRow())。obj);
} else if(rows_difference< 0)//我们需要删除行...
{
var index_start = old_count + rows_difference + 1;
console.log(Index start =+ index_start);
$('tr:gt('+ index_start +')')。remove();
row_i + = rows_difference;


$ b $(document).ready(function(){
//默认隐藏表
$('#students_form_table') .hide();

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

});

所以这种形式非常有效 - 所有的格式都正确,当我选择'x' ,'x'数量的学生表格被编译 - 然而,因为这个 -

 函数emptyRow(){
row_i ++;
this.obj = $(< tr>< / tr>);
this.obj.append('< td id =student_nameclass =field form_field>< input id =student_group_students_attributes ___ Student:0x00000103c4ead8__namename =student_group [students_attributes] [#& lt;学生:0x00000103c4ead8& gt;] [name]type =text/>< / td>');
this.obj.append('< td id =student_genderclass =field dropdown>< select id =student_group_students_attributes ___ Student:0x00000103c4ead8__gendername =student_group [students_attributes] [#& lt;学生:0x00000103c4ead8& gt;] [性别]><选项值=>选择性别< / option>< option value =女性>女性< / option>< option value =男性>男性< / option>< /选择>< / td>');选择值=变性人>变性人< /选项>
this.obj.append('< td id =remove_link>< input id =student_group_students_attributes ___ Student:0x00000103c4ead8 ___ destroyname =student_group [students_attributes] [#& lt; Student:0x00000103c4ead8& gt; ] [_ destroy]type =hidden/>< a href =#class =remove_fields dynamic> remove student< / a>< / td>')
}

...这些字段的显示不正确 - 因为它们不会创建新学生的谨慎实例领域。我知道问题是由轨道生成的html的id /名称部分中的散列,但我不知道如何替换它,以便这将工作。我来的最近的是试图改变这个 coffeescript网站,但我无法得到它的工作。

那么如何动态地为使用jquery的模型生成新的表单呢?



编辑:其实我刚刚意识到第一个和最后一个表格会正确保存 - 也就是说,如果我添加八个学生,那么student1和student8将被输入到数据库中,但其他人不会。这只会让我更加困惑:/ b / b>

编辑2 :我发现 this jquery api在

知道了!



这是最后的结果:



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:'防御性编码'http://stackoverflow.com/questions/14502508/undefined-method-for-nilnilclass-when-推送值到数组
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
#新主题路径
redirect_to class_path(@student_group),flash:{success:#{@student_group.name}已成功添加}
else
@title =创建一个新组
flash.now [:错误] =出现问题,请重试!
渲染'新'
结束
结束

_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 | %GT;
<%=呈现student_fields,:f =>助剂%>
<%end%>
< / tbody>
< / table>

最后, student_groups.js

 函数emptyRow(){
row_i ++;
this.obj = $(< tr>< / tr>);
this.obj.append('< td id =student_nameclass =field form_field>< input id =student_group_students_attributes__namename =student_group [students_attributes] [] [name]placeholder = Student namesize =30type =text/>< / td>');
this.obj.append('< td id =student_genderclass =field dropdown>< select id =student_group_students_attributes__gendername =student_group [students_attributes] [] [gender]> < option value =>选择性别< / option><选项值=女性>女性< / option><选项值=男性>男性< / option><选项值= 变性 >变性< /选项>< /选择>< / TD>');
this.obj.append('< td id =remove_link>< input id =student_group_students_attributes ___ destroyname =student_group [students_attributes] [] [_ destroy]type =hidden/> < a href =#class =remove_fields dynamic>删除学生< / a>< / td>')
}


I've been asking iterations of this question for a while now - but with a lot of help from the SO community i've very nearly got it working. So first, thanks!

I have a form to create a new student_group and am using the Cocoon gem:

<%= 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 %>

and the 'student_fields' partial:

<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>

Now the heart of the question:

I have the following .js file to dynamically add the correct number of student fields to the form:

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());
  })

});

So this form very nearly works - everything formats correctly, and when I select 'x' number of students, 'x' number of student forms are built - however, because of this -

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>')
}

...the fields aren't being rendered correctly - in that they aren't creating discreet instances of new student fields. I understand that the problem is the hash in the id/name portion of the html generated by rails, but i'm not sure how to replace it so that this will work. the closest i've come is trying to adapt the coffeescript from this site, but I couldn't get it working.

So how to dynamically generate new forms for models using jquery?

EDIT: Actually I've just realized that the first and last forms will save properly - that is, if I add eight students, student1 and student8 will be entered into the database, but the others will not. this only confuses me more :/

EDIT 2: I've found this jquery api called 'serialize' in the context of this question and i think it might be what i need, but having trouble adapting it. Help me!

解决方案

Got it!

Tried out a lot of things but this is what worked in the end:

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

relevant section of _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>

and finally, the relevant portion of 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>')
}

这篇关于如何在jQuery中动态添加嵌套属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆