Executing a rails .js.erb file from a jquery mobile form - ruby-on-rails

My form spans several jquery mobile pages all within one file and wrapped by this form
new.html.erb
<%= form_tag submit_path, :method => :post, :remote => true do%>
create.js.erb
alert("Hello");
<% debugger %>
$.mobile.changePage("#confirm");
The create.js.erb gets hit as my console stops on the debugger, but the alert never fires and neither does the jquery mobile command.
My url goes from /new#confirm to just /new
I can do the (seemingly) exact same thing in a normal rails form and I get the alert.

Apparently you need to do this completely with Ajax to get rails to respond properly and have the js.erb execute:
In your form add
"data-ajax" => "false"
then
$('#submit_button').click(function(){
handleSubmit();
return false
});
function handleSubmit() {
$.ajax({
url: "/post_url",
type: 'POST',
cache: false,
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content')); $.mobile.showPageLoadingMsg("a", "Submitting"); },
data: $("#the_form").serialize(),
success: function(data){
handleResponse(data):
}
});
}

Related

Rails is rendering an empty partial from js.erb

I'm trying to render a partial from a js.erb file but nothing is shown in the view.
There is an AJAX call that triggers the report_announcement action in the announcements_controller when a button is pressed.
reports.js
$.ajax({
type: "POST",
contentType: "application/json",
url: "/announcements/report_announcement.js",
data: json_data
});
reports/_report_content.html.erb
<div id="report_announcements_container"></div>
announcements_controller.rb
def report_announcement
#announcement = Announcement.new(announcement_params)
respond_to do |format|
if #announcement.save
format.js {}
end
end
end
announcements/report_announcement.js.erb
I know that announcements/report_announcement.js.erb is rendering ok because I can see the logging statement in the console and also in the development.log as well as the report_announcement object being logged to the console.
<% announcement_json = #announcement.to_json.html_safe %>
var report_announcement = <%= announcement_json %>;
console.log('report_announcement');
console.log(report_announcement);
// this is where something is not right I think
$("#report_announcements_container").html("<%= escape_javascript(render partial: 'announcements/report_announcements', locals: { announcement: #announcement }) %>");
console.log('inside announcements....');
announcements/report_announcements.html.erb
This is where I'm having an issue because the logging statement for the partial is shown however nothing from the partial is shown on the page. I see in the development.log that the page rendered but nothing is actually shown in the view. The partial is not showing on the page in the report_announcements_container div.
<h1>test</h1>
<%= announcement %>
<script>
console.log('inside partial...');
</script>
You're using the wrong content-type in your ajax call. Rails recognizes both application/javascript and text/javascript as the :js format.
Also when you request a js format you actually have to execute the returned javascript for anything to happen in the client.
$.ajax({
type: "POST",
contentType: "application/javascript",
url: "/announcements/report_announcement.js",
data: json_data
}).done(function(data){
jQuery.globalEval(data); // Yeah eval is evil.
});
If you have done any "real" ajax calls before this will seem completely backwards - thats because it is. js.erb is a poor mans ajax framework for the javascript impaired which consists of a bunch of routes and views that mutate the DOM in the client.
Manually creating calls for a js.erb template is just a silly excerise in masocism. If you really want to use it create a form and use it send the request instead so that you can just leverage the javascript handlers that rails provide:
<%= form_with(url: "/announcements/report_announcement", remote: true) do |f| %>
# ...
<% end %>

Rails 5: How Can a Form Submit with Custom HTTP Headers?

I cant seem to find any information on how to get a webform in Rails 5 to submit with custom headers. I would like the URL to which I am sending a PUT request to also receive some custom headers. I am surprised that there is no argument for form_for for this.
I could accomplish this by submitting the form to an action where I modify the headers there, e.g., request.headers['my-header'] = 'xyz'. I would then have to make the PUT request from within this "middle" controller action, and I feel this additional step is clunky and unconventional.
I could also use jQuery to bind to the submit click, and submit the form data after adding the headers via JavaScript. Id rather not involve another layer (i.e., JS) in this process.
I would rather not do either. Is there a way I can just use the Rails form helpers (or some controller helper) to add some custom headers to the request made by the form submission?
Rails does not have any tags that allows us to do that and therefore cannot add custom headers to your request.
In fact, you cannot set custom headers in html forms without xhr plugins,
You have to use it with ajax. Something like this:-
<%= form_tag("/your_url", method: :post, :remote => true, :html => { id: "form-id" }) do |f| %>
...your form here...
<% end %>
and then you ajax code:-
$('#form-id').submit(function() {
var valuesToSubmit = $(this).serialize();
$.ajax({
type: "POST",
url: $(this).attr('action'),
data: valuesToSubmit,
headers: { 'Xmlrpc-Token': 'value' , 'Token': 'another_value'}
}).success(function(response){
//success code
});
return false;
});
Using only remote: true in rails will make ajax call, but you want to be able to customize it using the code above.
Browser will send only standard headers like cookies, contenttype, etc. You can not send Authorization header (or other custom) using HTML form submit. You should use AJAX to do that.
$("#idForm").submit(function(e) {
var url = "path/to/your/script.php"; // the script where you handle the form input.
$.ajax({
type: "POST",
url: url,
data: $("#idForm").serialize(), // serializes the form's elements.
success: function(data)
{
alert(data); // show response from the php script.
}
});
e.preventDefault(); // avoid to execute the actual submit of the form.
});
<%= form_tag("/your_url", method: :post, :remote => true, :html => { id: "form-id" }) do |f| %>
...your form here...
<% end %>
$("#idForm").submit(function(e) {
var url = "path/to/your/script.php"; // the script where you handle the form input.
$.ajax({
type: "POST",
url: url,
data: $("#idForm").serialize(), // serializes the form's elements.
success: function(data)
{
alert(data); // show response from the php script.
}
});
e.preventDefault(); // avoid to execute the actual submit of the form.
});

Rails select_tag - how to send ajax request?

I want to send an AJAX request once an option is selected (changed) from the select_tag in Rails 3.1. Can we use :remote=>true or :onchange => remote_function() or is there some other way ?
You should definitely do this with jQuery (with an unobtrusive approach to keep things as clean as possible). On your .js file you should have something like this...
$('#select_tag_id').change(function(){
$ajax({
url: "remote_action_in_your_controller",
type: "GET",
data: {select_tag_value: $('#select_tag_id option:selected').text()},
})
});
this is as simple as it should be if you just want to call a remote action on your controller (notice I passed the value of the selected option since you probably want that value to do something with it). If you need to do something after the ajax call is executed use the succes option. Hope this helps.
You must to do it with JQuery. Something like this, when the document is ready, :
$('#your_select_tag').change(function() {
$.ajax({ type: "GET",
url: "http://your_url/",
success : function(text) {
alert('success')
}
});
});
See the doc : http://api.jquery.com/change/ and http://api.jquery.com/jQuery.ajax/.
remote: true adds data-remote="true" to the html element. Just add this as a CSS class in the select_tag options.
<%= select '', '', #coaches, {}, { data: {remote: true } } %>
Please note the data: { remote: true } is used because "data-remote" is not Ruby friendly.

Creating a :remote=>true post using AJAX rather than rails

I've spent a day spinning my wheels trying to understand how Rails :remote=>true works. The question below seems complicated but I'm trying to understand this simple question with the information I provide:
How can I make an Ajax call that simply renders as JS without using :remote=>true?
From my understanding :remote=>true simply generates and handles an AJAX call:
My view looks like this:
opts in a very complicated way, creates a link with :remote => true. This is omitted for simplicity
.e_list
= opts.sort_link(:name)
= opts.sort_link(:description)
- e_list.each do |e|
.entry
= link_to(e.name, '#', class: 'select_e', data: {e_id: e.id})
= e.description
= paginate e_list, remote: true, params: {search:"j", com_id: com.id}
Gallery.js.erb
$('#com<%= #com.id %>').replaceWith('<%= escape_javascript render(partial: "shared/com", locals: {com: #com}) %>');
My Controller:
def gallery
if params[:com_id]
#com = #s.com.find(params[:com_id])
#com.filter = params
end
if c = #s.com.where(:_type => "Com").first
#current_e = c.entries(#user.app_id).first
#current_e.og_url = view_context.og_url(#current_e)
end
render :text => "foobar" if !#current_e
end
logs, after the user clicks on the pagination links or sort links (the key is those links have :remote => true)
Started GET "super long url" for 127.0.0.1 at 2012-05-04 16:08:42 -0700
Processing by CController#gallery as JS
SO I TRY TO RECREATE THIS WITH AJAX:
$('button.search').live 'click', (e) ->
search = $(e.target).attr('search-term')
success_callback = (results) ->
if results
console.log(results)
update_components(results[0].entry, '.entry')
else
$.ajax(
url: 'super long url that is exactly the same url as above!'
).done ->
return false
MY FAILED RESPONSE THAT DOES NOT RENDER AS JS, YET I THOUGHT :remote => true was simply an ajax call wtf?:
Started GET "super long url identical as the one that renders JS" for 127.0.0.1 at 2012-05-04 16:07:22 -0700
Processing by ContestController#gallery as */*
What is going on? How can I make an Ajax call that simply renders as JS without using :remote=>true?
Try
$.ajax({
url: 'your url',
dataType: 'script'
})
http://www.alfajango.com/blog/rails-3-remote-links-and-forms-data-type-with-jquery/
try
/screens/4fa02763dc1c82269c0001da/contest/gallery.js?app_row_id=5....
If you want the js from the response to execute in the browser you should need to do something like eval(response), but i'm just suggesting, I never done it and even know how to eval code of a string in javascript.
You could use jQuery to accomplish what you are trying to do:
/* your jquery file */
jQuery.ajaxSetup({
'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})
...
$('#button').click(function() {
$.post('/controller/action', {
query_string1: value1
});
});

rails ajax request

I have a problem when sending the Ajax request. When you click on the link request is sent to the server 3 times and the answer did not come.
Why the request is sent three times to undermine?
Where did I go wrong in the formation of a query?
code:
run.html.erb
...
<%= link_to "Next", "#", :id => 'next', :class =>
...
run.js.erb
(function(){
$("#next").click(function(){
$.ajax({
type: 'POST',
url: '/engine/tff',
success: function(data){
alert("ok");
$("#question").html(data);
}
});
return false;
});
});
controller
def tff
respond_to do |format|
format.js render :text => "hello"
end
end
I am guessing the click event is being bound multiple times probably cos the script is being called multiple times. Not sure what is the reason for the multiple calls as I am not familiar with rails.
what you could do to avoid it is unbind the click event before binding it or use the on api.
function ajaxRequest(){
$.ajax({
type: 'POST',
url: '/engine/tff',
success: function(data){
alert("ok");
$("#question").html(data);
}
});
return false;
}
$("#next").unbind("click").bind("click",ajaxRequest);
or
$(document).on("click","#next",ajaxRequest);
also not sure if you were trying to bind on document ready and there is a typo in your code. but it should be wrapped like this:
$(function(){
$("#next").click(ajaxRequest);
});
One thing I ran into recently was that jquery tries to run the result, as the default dataType interprets the .js as a script, not text. You might need to add a dataType: "text" to the ajax call. I don't see how this translates into three calls though.
I thought returning false was supposed to prevent the click from moving on, but perhaps it is better form to use preventDefault() as apneadiving suggests.

Resources