2016-07-13 21 views
2

Ich habe an einer Schiene App gearbeitet, die grundlegende Ereignisse verfolgt, die ich hoffe, zu erweitern (es ist eine Lebensdaten-Tracking-App für mich). Ich habe eine EventTemplate-Klasse, die EventTemplateAttributes speichert. Beim Erstellen eines neuen Ereignisses verwendet es rails-jquery-autocomplete, um nach einer vorhandenen Vorlage zu suchen und das Formular mit seinen Attributen mit einem Hash zu füllen. Hier ist der Code für diese Funktion zur automatischen Vervollständigung:Cocoon Autocomplete Modal dynamische Felder zweimal bevölkern

def autocomplete_eventtemplate_name 
    respond_to do |format| 
     format.json { 
      @eventtemplates = Eventtemplate.where("name like ?", "%#{params[:term]}%") 

      render json: json_for_autocomplete_eventtemplates(@eventtemplates) 
     } 
    end 
end 
def json_for_autocomplete_eventtemplates(eventtemplates) 
    eventtemplates.collect do |eventtemplate| 

     attributes = Hash.new 
     unless eventtemplate.templateattributes.empty? 
      eventtemplate.templateattributes.each do |templateattribute| 
       attributes[templateattribute.id] = [templateattribute.name,templateattribute.value,templateattribute.unit] 
      end 
     end 
     hash = {"id" => eventtemplate.id.to_s, "value" => eventtemplate.name,"eventattributes" => attributes} 

     hash 
    end 
end 

Hier ist meine Form:

<%= simple_form_for(@event) do |f| %> 
    <% if @event.errors.any? %> 
    <div id="error_explanation"> 
     <h2><%= pluralize(@event.errors.count, "error") %> prohibited this event from being saved:</h2> 
     <ul> 
     <% @event.errors.full_messages.each do |message| %> 
      <li><%= message %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 
    <div class="field"> 
    <% if @event.new_record? %> 
     <% #,{:class=>"form-control"} %> 
     <%= f.autocomplete_field :name, autocomplete_eventtemplate_name_events_path,{:class => "form-control"} %> 
    <% else %> 
     <%= f.label :name %><br> 
     <%= f.text_field :name, class: 'form-control' %> 
    <% end %> 
    </div> 
    <div id="#find-subj"></div> 
    <table class="table-striped table table-bordered"> 
    <thead> 
     <td>Name</td> 
     <td>Value</td> 
     <td>Unit</td> 
     <td></td> 
    </thead> 
    <tbody id=eventattributes> 
     <tr> 
     <%= f.simple_fields_for(:eventattributes, :wrapper => false) do |tattribute| %> 
      <% if modal == false%> 
      <%= render 'eventattribute_fields', :f => tattribute %> 
      <% end %> 
     <% end %> 
     </tr> 
    </tbody> 
    </table> 
    <div class="links"> 
    <%= link_to_add_association f, :eventattributes, :"data-association-insertion-node" => "tbody#eventattributes", :"data-association-insertion-method" => "append", class: 'btn btn-info' do %> 
     <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> 
    <% end %> 
    </div></br> 
    <div class="actions"> 
    <%= f.submit class: 'btn btn-primary'%> 
    <%= link_to 'Cancel', events_path, class: 'btn btn-warning' %> 
    </div> 
<% end %> 

Und hier ist die _eventattribute_fields:

<tr class='nested-fields table'> 
    <td><%= f.input_field :name ,class: 'form-control'%></td> 
    <td><%= f.input_field :value, class: 'form-control' %></td> 
    <td><%= f.input_field :unit, class: 'form-control' %></td> 
    <td><%= link_to_remove_association f, class: 'btn btn-danger' do %> 
    <span class="glyphicon glyphicon-remove" aria-hidden="true"></span> 
    <% end %></td> 
</tr> 

Wenn ich Ereignisse aus/events/neu hinzufügen Das Formular wird korrekt ausgefüllt From New Page aber wenn ich sie über ein modales Fenster hinzufügen, dupliziert es die Felder: Modal View

Ich habe überprüft, dass der JSON, der auf beide Seiten kommt, nicht dupliziert ist und dass er dieselbe Ansicht (/ events/new) zeigt, aber irgendwie werden die Felder dupliziert.

BEARBEITEN Mit weiteren Debugging habe ich abgeleitet, dass das Problem im Cocoon-Skript passiert, das ich das Formular ausfüllen muss. Die beiden Methoden werden für das/events/new bzw. das modale Fenster verwendet. Ich muss die neue Seite nicht behalten, wenn das Modal korrekt funktionieren kann. Überprüfen der Konsolenausgabe, ich habe gesehen, dass jede Cocoon: After-Insert-Funktion nur auf ihren jeweiligen Seiten ausgelöst wird. Sie feuern auch nur einmal pro Attribut.

$(function() { 

    var eventtemplate_array; 
    var modal = false; 

    $('#event_name').bind('railsAutocomplete.select', function(event, data){ 
    //$('#event_name').bind('change', function(event, data){ 
     console.debug("Template selected..."); 
     attributes = data.item.eventattributes; 
     console.debug("Removing existing attributes..."); 
     $('.event_eventattribute_destroy').click(); 
     console.debug("Adding attributes..."); 
     for(var id in attributes) { 
      eventtemplate_array = attributes[id]; 
      $('.add_fields').click(); 
     } 
     console.debug("Done adding all attribute..."); 
    }); 
    if(!modal){ 
    $('#eventattributes').bind('cocoon:after-insert', function(e, eventattribute) { 
     console.debug(modal); 
     eventattribute[0].getElementsByTagName('input')[0].value = eventtemplate_array[0]; 
     eventattribute[0].getElementsByTagName('input')[1].value = eventtemplate_array[1]; 
     eventattribute[0].getElementsByTagName('input')[2].value = eventtemplate_array[2]; 
    });} 

    $('#newevent-modal').on('shown.bs.modal', function() { 
     modal = true; 
    $('input#event_name').bind('railsAutocomplete.select', function(event, data){ 
     attributes = data.item.eventattributes; 
     $('.event_eventattribute_destroy').click(); 
     for(var id in attributes) { 
      console.debug(id); 
      eventtemplate_array = attributes[id]; 
      $('.add_fields').click(); 
     } 
     eventtemplate_array = ["","",""]; 
    }); 
    $('#eventattributes').bind('cocoon:after-insert', function(e, eventattribute) { 
     console.debug(modal); 
     eventattribute[0].getElementsByTagName('input')[0].value = eventtemplate_array[0]; 
     eventattribute[0].getElementsByTagName('input')[1].value = eventtemplate_array[1]; 
     eventattribute[0].getElementsByTagName('input')[2].value = eventtemplate_array[2]; 
    }); 
}); 


}); 

Antwort

0

Wirklich komplexe Frage zu verstehen. Nur damit ich es richtig verstehe: Sie verwenden ein "Autocomplete" -Element, um die Liste der Felder aus einer Vorlage zu erhalten, richtig? (Verwenden Sie einfach einen einfachen Ajax-Aufruf?) Und dann verwenden Sie dieses JSON, um das Formular in Javascript zu erstellen. Also, in diesem Skript, irgendwie erstellen Sie Doubles, oder? Es scheint eine sehr komplizierte Art und Weise, warum nicht nur die Form Server-Seite rendern?

Da Ihre IDs für beide Seiten identisch sind (input#event_name), fügen Sie das Ereignis tatsächlich zweimal an, wenn das Modal gerendert wird, und deshalb wird es auf der modalen Seite dupliziert. Verwenden Sie besser Bereichsauswahlen wie #newevent-modal input#event_name und #newevent-modal #eventattributes bei der Behandlung des Show-Ereignisses des Modal.

+0

Danke! Ich habe immer noch dieses Duplikat bekommen, auch nachdem ich die erste Hälfte des modalen JS-Bits auskommentiert habe, also habe ich es auf hacky Weise gemacht, indem ich eine boolesche Variable ein- und ausgeschaltet habe und nur die tatsächlichen Daten in die Tabelle geschrieben habe Zeit. Dann in der Steuerung ließ ich alle Kinder fallen, die leer sind. –