Rails jQuery Tokeninput Reload via AJAX - ruby-on-rails

I have an AJAX create action for a rails controller that will select the form and recreate it by doing a render partial of just the form. This way, the error messages get shown when the validation fails.
However, one of my text fields is using the jQuery TokenInput plugin, and when the ajax call redraws the form, the jQuery TokenInput plugin is no longer loaded on the form.
Is there any way to trigger rerunning of the corresponding assets/javascripts/.js.coffee file from the AJAX controller action javascript file?
Thanks in advance...

After the form is redrawn, you just need to rerun your Tokeninput script. The best way to do this would be to place your Tokeninput command into a function (so you don't repeat yourself) and then just call that function after the form render. For example, let's say you want a Dog model that has_many collars that you want tokenized:
dogs.js.coffee:
tokenizeDogCollars = ->
$("#dog_collar_tokens").tokenInput "/dogs.json"
tokenizeDogCollars
create.js.erb:
<% if #dog.errors.any? -%>
...
$('#dog-form-container').empty();
$('#dog-form-container').append('<%= j render("form") %>');
tokenizeDogCollars();
...
<% else %>
... whatever you want to do on a successful save ...
<% end %>

Related

rails form post action without changing path

I've got a view that renders a contact form. This contact form is rendered through javascript. There is also a javascript filter that the user can set viewing options in. (Depending on the settings, different markers are shown on a google map. The user can then click on the markers and in the viewbox click on a view button that renders some info and the contact form below the map)
If I were to make a normal form and use the post method with a #contact and contact routes, I would have to rerender the entire page after the #contact#create method was called. Which would mean all of the current users filter options would be unset. I could obviously save the settings, but feel like this is a hassle.
What I would like is for the contact form to call a method upon submit without actually changing paths, but I have no idea if this is even possible. (i'm using simple form so an answer for that would be preferable)
Since your question is quite broad, I'll have to answer as such:
if this is even possible
Yes it's possible.
You'll have to use ajax to send an asynchronous request to your server.
Ajax (Asynchronous Javascript And Xml) sends requests out of scope of typical HTTP; you can send/receive "hidden" data without reloading (this is what you want):
Don't worry - ajax is really simple once you understand it.
There's a great Railscast about it here:
Implementation
For you, you will just have to get your form to submit over ajax (javascript). There are two ways to do this:
Standard JS (JQuery)
Rails UJS (unobtrusive Javascript)
Basically, javascript acts as a mini browser, opening a url on your server, handling the returned data & doing what you tell it on the path:
<% form_tag contact_path, remote: true %>
<%= text_field_tag "name %>
<%= email_field_tag "email" %>
<%= submit_tag %>
<% end %>
You'll then be able to back this up with the corresponding controller action on your server:
#app/controllers/contact_forms_controller.rb
class ContactFormsController < ApplicationController
def create
... #-> your own logic here
respond_to do |format|
format.js #-> when receiving a pure xml request, this will fire
format.html
end
end
end
#app/views/contact_forms/create.js.erb
$("body").append("<%=j #variable %>");
Without going into too much detail, this is the most efficient way to achieve what you want. I can elaborate if required.

Rails remote: true only if requested through ajax

I've got my app working as I want it without AJAX.
I'm adding AJAX now to an item listing page with an 'add item' button.
Normally, clicking 'add item' it'd just go to the new item page, but with ajax it injects the new item form onto the page. On submit it updates the listing. This is all working fine, too.
However, if I visit the new item page directly, upon submitting the form it still fires the javascript. I want avoid any AJAX form submission if I'm on the form page itself.
Is it possible to only add remote => true to my form tag if the page has been requested through AJAX?
(...or suggest a better way to do this)
request.xml_http_request? will tell you if you are serving an ajax request:
<% if request.xml_http_request? %>
....
<% end %>

Rendering a completely new partial using jquery ajax

I'm trying to write an AJAX call that renders a new partial when a particular item is selected from a drop down list. I have been searching for a solution all day with no luck :(
The only way I got it working was not using AJAX, but having a hidden div containing my second partial, and then showing it and hiding the other div when the appropriate option is selected from the drop down box. Yes this worked but I was looking for a cleaner solution.
I'm not looking for a direct answer, but if anyone has any resources that could point me in the right direction it would be greatly appreciated :)
How about adding a controller action that would render the view (so it's view would just render the partial), and then using jquery to place it:
$('#id-of-box').load("<%= some_action_path %>")
You should perform a remote AJAX call when the onchange event from your select element is being triggered, so on the page which contains your select element there should be something like this (inside a script):
$('#select_id').live('change',function(){
$.ajax({
url: 'url_bound_to_partial_renderer'
});
}
and on the action of the controller which responds to your url_to_fetch_result, you should write something like this:
# controller
# action bound to 'url_bound_to_partial_renderer' by routes.rb
def partial_renderer
...
end
#view (partial) _partial_renderer.js.erb
$('jquery_selector_path_to_container_element_of_your_partial').html("<%= escape_javascript render(:partial => 'my_partial') %>");
#view (partial) to be rendered inside container element: _my_partial.html.erb
<p>Here goes the content of the partial you want to be rendered on the container!</p>
Hope this will respond to your question.

How to implement dynamic content render when form submited (newbie ask)

I am developing rails 3 application (I am newbie in Rails).
Currently, I have a form (use "form_for") for submit, there is a div area under the form. What I want is when user click the 'submit' button of the form, based on the user input data in the form, application will first go to the database to retrieve and organize some data, then the div area under the form will be rendered with the organized data.
That's the content of the div area is rendered dynamically based on user's input in the form, and the div render happens when user click "submit" form button .
The index.html.haml:
=form_for :myform do |form|
= ...
= ...
=form.submit "submit"
%div.result
/dynamic content to be rendered here, when user submit the form
=render :partial 'result'
I think my form submission should first go to run a controller method to organize the data from Database, and what's the next step I should do? As you noticed from the above code, I have a partial there under div, I would like to update the 'result' partial when user submit form, but how to implement this??
examples of how you may update your page in response to ajax polling
#some_controller.rb
def your_action
end
# javascript erb file. views/some_controller/your_action.js.erb
$('div.result').html('<%= escape_javascript(render :partial => 'your_action' -%>');
# _your_action.html.haml
= #dynamic_data
Rails scaffolding will give you a clue on how to do this. Just include the form as partial as well in your show template. Something like this:
index.html.haml (or new.htm.haml):
= render 'new'
show.html.haml:
= render 'new'
# display your #object

Posting a form through popup in Rails

I have a model called Details, and two controller methods new and create. New method displays a form to create Details (in new.html.erb), which gets posted to the Create method that saves it. (when it succesffully saves, it it renders the new.html.erb file with the details.) This works as expected.
Now i want a separate page with a link to fill in these details. I want the click to do the intended work through a popup, example redbox. When you click on that link, a popup should show the form, whose submit should post the form, and if it is successfully done, then refresh the original page. If the post is unsaved, then the same form should show the errors. What do i need to do to make it work in Ror? I guess i need some stuff to go in new.js.rjs and maybe create.js.rjs, but i can't really figure out what to put in those files.
Redbox updates the page's dom to add a div at the end of it. So your form is a part of the main page.
So if you add a form tag in this redbox, all your page will be reloaded as there's only one.
So you add anywhere in your page (preferably at the end) :
<div id="redbox" style="display: none;">
<%= form_for #details do %>
# Whatever form fields you want here
<% end -%>
</div>
You do a link that'll open the redbox :
<%= link_to_redbox 'Open The Details Form', 'redbox' %>
This will display your redbox with your form.
And as it is the same page, not a new windows, when you'll validate your form, it'll reload the all of it.
I used a link_to_remote_redbox for this, which on clicking, fetches the form rendered by the new method call in a popup widnow. it submits to the create function and it is now working. actually i had previously made it work without ajax and i was having difficulty in making it work with ajax. the problem was solved once i made separate partials for ajax calls, and doing:
respond_to do |format|
format.js { render :template => 'detail/ajax_template'}
...
end
I provided different templates for both create and new method calls, used the :html => {:id => 'some-id'} in form and the :update => {:some-id} to replace the form with the message that it worked correctly.
So I didnt know that i needed separate templates for the different styles of forms, and that i needed to use the :update option to replace the form when i asked the above question.

Resources