8

У меня есть грубый переход, интегрирующий потрясающий камень nested_form ryanb в приложение rails 3.1.3. Я боюсь, что мои навыки Javascript слишком ограничены, чтобы узнать, действительно ли это мой код (вероятно) или драгоценный камень, который нужно изменить. Может быть, кто-то здесь может помочь.Rails nested_form link_to_add не работает при создании экземпляра вложенной модели перед установкой

Установки: У меня есть класс «: домохозяйства», который: accepts_nested_attributes_for »: members (people)». Я запускаю сервер разработки. Я переместил nested_form.js в каталог/app/assets/javascripts. Я почти уверен, что это только один источник.

Проблема: если в контроллере домохозяйств «новый» метод, я делаю это:

@household = Household.new 

Я вижу только бытовые родной полей зрения (ожидается), и «link_to_remove» и Ссылки «link_to_add» визуализировать/удалять части-части элементов (ожидается). Однако, если я делаю это:

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

Я вижу домашние родной полей зрения (ожидается), один рендеринг членов родной полей парциальных (ожидается), но «link_to_remove» и «link_to_add «ничего не делать (неожиданно). Я не могу добавить еще одно: частичные части в этот момент или удалить уже отображаемые: частичные части.

Я в тупике. Ниже приведены урезанные исходные файлы, которые кажутся релевантными. Я получаю nested_form плагин из репозитория мерзавца (последний в комплекте 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 

/приложение/модели/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' 

/приложение /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" 

/приложение/активы/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); 
}); 

ответ

6

Я просто была такая же проблема и фиксировали его следующим образом:

Убедитесь, что вы один из последних jquery.js файлов, связанных в вашей голове. После загрузки не используйте файл nested_form.js, который устанавливается из драгоценного камня. Вместо этого используйте jquery_nested_form.js.

Вот решение, которое будет работать нормально до тех пор, пока у вас есть JQuery связывающую перед файлом jquery_nested_form:

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

Вот код для файла 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); 

Надежда это помогает!

+0

Это точно. Я использую nested_form 0.2.3 и в том числе через конвейер активов, то есть '// = требует jquery_nested_form', и теперь все работает как шарм. Благодаря! – admgc