8

Tôi đang gặp khó khăn khi tích hợp đá quý nested_form tuyệt vời của ryanb vào ứng dụng đường ray 3.1.3 của tôi. Tôi sợ kỹ năng Javascript của tôi quá hạn chế để biết liệu đó là mã của tôi (có thể) hoặc đá quý cần thay đổi. Có lẽ ai đó ở đây có thể giúp đỡ.Đường ray nested_form link_to_add không hoạt động khi xây dựng sơ bộ mẫu lồng nhau

Thiết lập: Tôi có lớp ": hộ gia đình" là: accepted_nested_attributes_for ": members (people)". Tôi đang chạy một máy chủ phát triển. Tôi đã chuyển nested_form.js vào thư mục/app/assets/javascripts. Tôi gần như tích cực nó chỉ có nguồn gốc một lần.

Vấn đề: nếu, trong bộ điều khiển hộ phương pháp "mới", tôi làm điều này:

@household = Household.new 

Tôi chỉ thấy các lĩnh vực hộ gia đình có nguồn gốc trong giao diện (dự kiến), và "link_to_remove" và liên kết "link_to_add" hiển thị/xóa một phần thành viên (dự kiến). Tuy nhiên, nếu tôi làm điều này:

@household = Household.new 
@household.members.build 

Tôi thấy các trường hộ gia đình có nguồn gốc trong giao diện (dự kiến), một vẽ của các trường thành viên có nguồn gốc từng phần (dự kiến), nhưng "link_to_remove" và "link_to_add "không làm gì cả (bất ngờ). Tôi không thể thêm một thành viên khác: thành viên một phần tại điểm đó, cũng như không xóa phần đã được hiển thị: thành viên.

Tôi đang bối rối. Dưới đây là các tệp nguồn bị tước xuống có vẻ có liên quan. Tôi nhận được plugin nested_form từ kho git (cuối cùng kèm 2012/04/18) ...


/app/models/household.rb

class Household < ActiveRecord::Base 
    has_many :members, :class_name => "Person" 
    accepts_nested_attributes_for :members 
    attr_accessible :id, :name, :member_ids 
    attr_accessible :members_attributes 
end #class 

/app/models/person.rb

class Person < ActiveRecord::Base 
    belongs_to :household 
    attr_accessible :id, :name_given, :name_middle, :name_family, :household_id 
end #class 

/app/controllers/households_controller.rb

<snip> 
    # GET /households/new 
    # GET /households/new.json 
    def new 
    @household = Household.new 
    @household.members.build  # <---- Removing this changes the behavior 

    respond_to do |format| 
     format.html # new.html.erb 
     format.json { render json: @household } 
    end 
    end 

/app/views/households/new.html.haml

.headbg 
    .pad 
    %h2 Enter a New Household 
= render 'form' 

/app /views/households/_form.html.haml

= nested_form_for @household, :html => { :class => "form-horizontal"} do |f| 

    %fieldset 
    %legend Household 

    .control-group 
     = f.label(:name, { :class => 'control-label'}) 
     .controls 
     = f.text_field(:name, { :class => 'span5', :placeholder => '[household name]'}) 

    %fieldset 
    %legend Household Members 
    = f.fields_for :members, :html => { :class => "form-inline"} do |nested_f| 
     = render :partial => 'people/nested_person_form', :locals => { :f => nested_f } 
     = yield :nested_person_form 
    %p 
     = f.link_to_add "New Household Member", :members 

    .form-actions 
    = button_tag(:class => "btn btn-primary", :disable_with => "Saving..." ) do 
     %i.icon-ok.icon-white 
     Save 
    = link_to households_path do 
     .btn.btn-info 
     %i.icon-arrow-left.icon-white 
     Back to Households 

/app/views/people/_nested_person_form.html.haml

- content_for :nested_person_form do 

    .nested-fields 
    .row 
     .span8 
     .control-group 
      = f.label("Name", { :class => 'control-label'}) 
      .controls 
      = f.text_field(:name_given, { :class => 'span2', :placeholder => '[first]'}) 
      = f.text_field(:name_middle, { :class => 'span2', :placeholder => '[middle]'}) 
      = f.text_field(:name_family, { :class => 'span2', :placeholder => '[last]'}) 
     .span1 
     = f.link_to_remove "Remove" 

/app/tài sản/Javascripts/nested_form/nested_form.js

jQuery(function($) { 
    window.NestedFormEvents = function() { 
    this.addFields = $.proxy(this.addFields, this); 
    this.removeFields = $.proxy(this.removeFields, this); 
    }; 

    NestedFormEvents.prototype = { 
    addFields: function(e) { 
     // Setup 
     var link = e.currentTarget; 
     var assoc = $(link).attr('data-association');   // Name of child 
     var content = $('#' + assoc + '_fields_blueprint').html(); // Fields template 

     // Make the context correct by replacing new_<parents> with the generated ID 
     // of each of the parent objects 
     var context = ($(link).closest('.fields').find('input:first').attr('name') || '').replace(new RegExp('\[[a-z]+\]$'), ''); 

     // context will be something like this for a brand new form: 
     // project[tasks_attributes][new_1255929127459][assignments_attributes][new_1255929128105] 
     // or for an edit form: 
     // project[tasks_attributes][0][assignments_attributes][1] 
     if (context) { 
     var parentNames = context.match(/[a-z_]+_attributes/g) || []; 
     var parentIds = context.match(/(new_)?[0-9]+/g) || []; 

     for(var i = 0; i < parentNames.length; i++) { 
      if(parentIds[i]) { 
      content = content.replace(
       new RegExp('(_' + parentNames[i] + ')_.+?_', 'g'), 
       '$1_' + parentIds[i] + '_'); 

      content = content.replace(
       new RegExp('(\\[' + parentNames[i] + '\\])\\[.+?\\]', 'g'), 
       '$1[' + parentIds[i] + ']'); 
      } 
     } 
     } 

     // Make a unique ID for the new child 
     var regexp = new RegExp('new_' + assoc, 'g'); 
     var new_id = new Date().getTime(); 
     content  = content.replace(regexp, "new_" + new_id); 

     var field = this.insertFields(content, assoc, link); 
     $(link).closest("form") 
     .trigger({ type: 'nested:fieldAdded', field: field }) 
     .trigger({ type: 'nested:fieldAdded:' + assoc, field: field }); 
     return false; 
    }, 
    insertFields: function(content, assoc, link) { 
     return $(content).insertBefore(link); 
    }, 
    removeFields: function(e) { 
     var link = e.currentTarget; 
     var hiddenField = $(link).prev('input[type=hidden]'); 
     hiddenField.val('1'); 
     // if (hiddenField) { 
     // $(link).v 
     // hiddenField.value = '1'; 
     // } 
     var field = $(link).closest('.fields'); 
     field.hide(); 
     $(link).closest("form").trigger({ type: 'nested:fieldRemoved', field: field }); 
     return false; 
    } 
    }; 

    window.nestedFormEvents = new NestedFormEvents(); 
    $('form a.add_nested_fields').live('click', nestedFormEvents.addFields); 
    $('form a.remove_nested_fields').live('click', nestedFormEvents.removeFields); 
}); 

Trả lời

6

Tôi chỉ có cùng một vấn đề và cố định nó theo cách sau:

Hãy chắc chắn rằng bạn có một trong các tập tin jQuery.js mới nhất được liên kết trong đầu của bạn. Sau khi được tải không sử dụng tệp nested_form.js cài đặt từ đá quý. Thay vào đó hãy sử dụng jquery_nested_form.js.

Đây là một giải pháp mà sẽ làm việc tốt, miễn là bạn có jquery liên kết trước khi các tập tin jquery_nested_form:

<%= javascript_include_tag :defaults, 'jquery_nested_form' %> 

Đây là mã cho file jquery_nested_form.js:

jQuery(function($) { 
    window.NestedFormEvents = function() { 
    this.addFields = $.proxy(this.addFields, this); 
    this.removeFields = $.proxy(this.removeFields, this); 
    }; 

    NestedFormEvents.prototype = { 
    addFields: function(e) { 
     // Setup 
     var link = e.currentTarget; 
     var assoc = $(link).attr('data-association');   // Name of child 
     var content = $('#' + assoc + '_fields_blueprint').html(); // Fields template 

     // Make the context correct by replacing new_<parents> with the generated ID 
     // of each of the parent objects 
     var context = ($(link).closest('.fields').closestChild('input, textarea').eq(0).attr('name') || '').replace(new RegExp('\[[a-z]+\]$'), ''); 

     // context will be something like this for a brand new form: 
     // project[tasks_attributes][new_1255929127459][assignments_attributes][new_1255929128105] 
     // or for an edit form: 
     // project[tasks_attributes][0][assignments_attributes][1] 
     if (context) { 
     var parentNames = context.match(/[a-z_]+_attributes/g) || []; 
     var parentIds = context.match(/(new_)?[0-9]+/g) || []; 

     for(var i = 0; i < parentNames.length; i++) { 
      if(parentIds[i]) { 
      content = content.replace(
       new RegExp('(_' + parentNames[i] + ')_.+?_', 'g'), 
       '$1_' + parentIds[i] + '_'); 

      content = content.replace(
       new RegExp('(\\[' + parentNames[i] + '\\])\\[.+?\\]', 'g'), 
       '$1[' + parentIds[i] + ']'); 
      } 
     } 
     } 

     // Make a unique ID for the new child 
     var regexp = new RegExp('new_' + assoc, 'g'); 
     var new_id = new Date().getTime(); 
     content  = content.replace(regexp, "new_" + new_id); 

     var field = this.insertFields(content, assoc, link); 
     // bubble up event upto document (through form) 
     field 
     .trigger({ type: 'nested:fieldAdded', field: field }) 
     .trigger({ type: 'nested:fieldAdded:' + assoc, field: field }); 
     return false; 
    }, 
    insertFields: function(content, assoc, link) { 
     return $(content).insertBefore(link); 
    }, 
    removeFields: function(e) { 
     var $link = $(e.currentTarget), 
      assoc = $link.data('association'); // Name of child to be removed 

     var hiddenField = $link.prev('input[type=hidden]'); 
     hiddenField.val('1'); 

     var field = $link.closest('.fields'); 
     field.hide(); 

     field 
     .trigger({ type: 'nested:fieldRemoved', field: field }) 
     .trigger({ type: 'nested:fieldRemoved:' + assoc, field: field }); 
     return false; 
    } 
    }; 

    window.nestedFormEvents = new NestedFormEvents(); 
    $('form a.add_nested_fields').live('click', nestedFormEvents.addFields); 
    $('form a.remove_nested_fields').live('click', nestedFormEvents.removeFields); 
}); 
// http://plugins.jquery.com/project/closestChild 
/* 
* Copyright 2011, Tobias Lindig 
* 
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 
* 
*/ 
(function($) { 
     $.fn.closestChild = function(selector) { 
       // breadth first search for the first matched node 
       if (selector && selector != '') { 
         var queue = []; 
         queue.push(this); 
         while(queue.length > 0) { 
           var node = queue.shift(); 
           var children = node.children(); 
           for(var i = 0; i < children.length; ++i) { 
             var child = $(children[i]); 
             if (child.is(selector)) { 
               return child; //well, we found one 
             } 
             queue.push(child); 
           } 
         } 
       } 
       return $();//nothing found 
     }; 
})(jQuery); 

Hope điều này có ích!

+0

Chắc chắn rồi. Tôi đang sử dụng nested_form 0.2.3 và bao gồm thông qua đường dẫn nội dung, nghĩa là '// = require jquery_nested_form' và mọi thứ hoạt động như một nét duyên dáng ngay bây giờ. Cảm ơn! – admgc

Các vấn đề liên quan