I'm following this railscast on nested forms to create a similar application.
In Ryan's application he has a structure like:
So a user can create a survey and add/delete questions, with corresponding answers that they can add/delete.
I'm trying to do it a little differently. I have:
For my application, after a user has created a question, the user can create an answer (just like Ryan's app). But there is a select box next to each answer, with the default being "Answer" and the other being "Comment". I'm trying to get basically the same functionality of Ryan's app, but with two tables: comments table and answers table.
My code mimics the railscast, except for my answer_fields partial looks like:
<fieldset>
<%= f.label :content, "Answer" %>
<%= f.select :switch_answer_table options_for_select(["Answer", "Comment"]), class: "change-type" %>
<%= f.text_field :content %>
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "remove" %>
</fieldset>
and I have a comment_fields partial that looks like:
<fieldset>
<%= f.label :content, "Comment" %>
<%= f.select :switch_answer_table options_for_select(["Comment", "Answer"]), class: "change-type" %>
<%= f.text_field :comment_content %>
... (leaving out some stuff) ...
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "remove" %>
</fieldset>
My question.rb model looks like:
class Question < ActiveRecord::Base
belongs_to :survey
has_many :answers
has_many :comments
accepts_nested_attributes_for :answers, allow_destroy: true
accepts_nested_attributes_for :comments, allow_destroy: true
end
I've been working on this, and I'm stuck. My jQuery only looks like this so far:
jQuery ->
$('form').on 'click', '.remove_fields', (event) ->
$(this).prev('input[type=hidden]').val('1')
$(this).closest('fieldset').hide()
event.preventDefault()
$('form').on 'click', '.add_fields', (event) ->
time = new Date().getTime()
regexp = new RegExp($(this).data('id'), 'g')
$(this).before($(this).data('fields').replace(regexp, time))
event.preventDefault()
$('form').on 'change', '.change-type', (event) ->
# Confused on how to change partials
Basically, I need a way to onChange, the partial for the selected answer/comment.
alejandro babio is correct. render both partials. give one of them a style of display:none and then toggle the class in your coffescipt onchange handler. In the case that a user starts to type an answer and then switches to a comment you'll also want to clear the fields associated with the newly hidden fields otherwise on submit you could have both comment and answer submitted.
I haven't tested this, but perhaps you want to use dependent-fields-rails . Depending on the state of the select box you can then show either the comment box or answer box.
The example given on the github page (uses simple form, but you can apply the same to your form_for):
= simple_form_for(@filing) do
= f.input :registration_office, collection: ['habm', 'dpma']
.js-dependent-fields[data-select-id='filing_registration_office' data-option-value='habm']
= f.input :language, collection: ['english', 'german']
Then I guess you use fields_for to satisfy your has_many relationship for example:
f.select :switch_answer_table, collection: ['answer', 'comment']
.js-dependent-fields[data-select-id='question_switch_answer_table' data-option-value='answer']
f.fields_for :answers do |abuilder|
...
.js-dependent-fields[data-select-id='question_switch_answer_table' data-option-value='comment']
f.fields_for :comments do |cbuilder|
...
Again, not tested and a best guess but it hopefully nudges you into the right direction.
First at all, you must render both partials (answer_fields and comments_fields) with the form.
At the comments_partial replace <fieldset>
with <fieldset style="display:none">
Change visibility of partials with coffeescript:
$('form').on 'change', '.change-type', (event) ->
$('.change-type').each ->
$(@).closest('fieldset').each ->
if $(@).is(':visible')
$(@).find('input').val('') # reset all filels to empty values
$(@).toggle()
I thing that do the trick.
I clear only input fields, but there must be all of them to prevent save de hidden element (like says hraynaud)
The partial fields are generated as a data attribute by the link_to_add_fields helper method. The js then gets the data object and renders it. Consider the following (this is untested but should be a good guide):
_form.html.erb
<select id="response_type_select_field">
<option value="comment">Comment</option>
<option value="answer">Answer</option>
</select>
<%= link_to_add_reply_fields "Add Reply", f, :answers, :comments %>
surveys_helper.rb
module SurveysHelper
def link_to_add_reply_fields(name, f, association_1, association_2)
object_1 = f.object.send(association_1).klass.new
object_1_id = object_1.object_id
object_1_fields = f.fields_for(association_1, object_1, child_index: object_1_id) do |builder|
render(association_1.to_s.singularize + "_fields", f: builder)
end
object_2 = f.object.send(association_2).klass.new
object_2_id = object_2.object_id
object_2_fields = f.fields_for(association_2, object_2, child_index: object_2_id) do |builder|
render(association_2.to_s.singularize + "_fields", f: builder)
end
link_to(name, '#', class: "add_reply_fields", data: {id_1: object_1_id, id_2: object_2_id, object_1_fields: object_1_fields.gsub("\n", ""), object_2_fields: object_2_fields.gsub("\n", "")})
end
end
Coffee script:
jQuery ->
$('form').on 'click', '.add_reply_fields', (event) ->
time = new Date().getTime()
reply_type = $("#response_type_select_field option:selected").val()
if reply_type is 'answer'
data_attribute = 'object_1_fields'
regexp = new RegExp($(this).data('id_1'), 'g')
else if reply_type is 'comment'
data_attribute = 'object_2_fields'
regexp = new RegExp($(this).data('id_2'), 'g')
$(this).before($(this).data(data_attribute).replace(regexp, time))
event.preventDefault()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.