Reputation: 802
I am creating a form where a user can add many nested questions, and each question can have many nested answers, other fields have ActiveRecord validators and when they fail, the page gets reloaded, the inserted fields are still there.
All callbacks(such as cocoon:before-insert
) are not reloaded, for instance a change handler of a dropdown on an inserted object
What can I do to make these callbacks be respected if the page is reloaded on a server-side validator fail?
On another note, what would be, code-quality wise, the best way to add handlers created inside a cocoon callback to nested objects built when the new
method on the controller is called(i.e. objects which are not affected by after-insert/before-insert callbacks)?
Here's some sample coffeescript code for clarification:
$(document).ready ->
$('#questions').on("cocoon:after-insert", (e, added_question) ->
added_question.find('#type').change ->
if $(this).val() is "1"
added_question.find("#answers").hide()
else
added_question.find("#answers").show()
EDIT: changed question since removal problem was a lack of a proper wrapper-class
EDIT #2: added sample code
Upvotes: 1
Views: 1748
Reputation: 50057
When using rails4, you are using turbolinks, and you can no longer rely on the document.ready
event, instead you should listen to the page:change
event.
So your code would become:
$(window).bind 'page:change', () ->
$('#questions').on("cocoon:after-insert", (e, added_question) ->
added_question.find('#type').change ->
if $(this).val() is "1"
added_question.find("#answers").hide()
else
added_question.find("#answers").show()
alternatively you could write $(document).on 'page:change', () -> ...
which is imho identical.
[UPDATE: alternative solution]
I had not really read the event handler :) A few remarks:
before-insert
. That might work. #type
, but there will be more than one a page? That is asking for trouble :) If you are getting more than one, use a class. Also, use a more descriptive name.There is a simpler solution: jquery can bind dynamically, so you can write
$('#questions').on 'change', '.question-type', () ->
var this = $(this)
var question = $(this).parent('.your-question-class')
question.toggle()
Not sure if you really need to check for the value, just toggle the visibility?
This code is of course not tested, but I hope you get the gis of it. Look up the jquery on
handler, it allows to catch events with a selector. So in this case, any change event inside the #questions
div, on an element with class question-type
(instead of your incorrect #type
id) will be handled by this handler. It will by dynamic, since it is attached to the container element. So if questions are added or removed, it is still valid.
Upvotes: 1