Ruby on Rails: link_to_remote javascript broken? - ruby-on-rails

I have this
<%= link_to_remote "Next",
{:url => { :controller=>:objects,
:action=>:filter_recent,
:page=>#objects.next_page},
:with => "Form.serialize('filter')" },
:after => "alert('hello')"%>
I've tried :before, :after, :loading, :complete... none of them appear to be working... I know the button works, cause the table advances to the next page.

It looks like your arguments are incorrectly split up by the hash you wrapped them in.
Your :after JS snippet/callback is being passed to the html_options argument hash, not the options hash (where it would be used).
Change to the following:
<%= link_to_remote "Next",
:url => {
:controller=>:objects,
:action=>:filter_recent,
:page=>#objects.next_page
},
:with => "Form.serialize('filter')",
:after => "alert('hello')"%>

Related

Rails link_to URL and HTML options with remote: true

My current link
link_to title, params.merge(:sort => column, :direction => direction, :page => nil, :search => nil), {class: css_class}
I want to add remote: true into the mix but when I encapusulate it with the params.merge (i.e. {params.merge(), remote: true} I get a syntax error. In rails I need to encaps the url options and the html options separately right?
title and css_class are both variables inside the helper method this link is in
Better to use:
link_to 'title', params.merge(:sort => column, :direction => direction, :page => nil, :search => nil), {class: css_class}, :remote => true
You can do it like this:
link_to title, params.merge(:sort => column, :direction => direction, :page => nil, :search => nil), class: css_class, remote: true
In Rails 5, ActionController::Parameters no longer inherits from Hash, in an attempt to discourage people from using Hash-related methods on the request parameters without explicitly filtering them.
As part of this pull request, which was backported into Rails 5.1 and partially into Rails 5.0, an exception is raised if you try to call to_h on the parameters object without calling permit.
Calling merge on the original params object (params.merge(:sort => column, :direction => direction, :page => nil)) returns a new ActionController::Parameters object with the same permitted status (that is, permit has not been called on it). The link_to method then ends up calling to_h on that object, which raises the exception.
If you know which parameters should be allowed in the link, you can call permit with those listed.
params.permit(:param_1, :param_2).merge(:sort => column, :direction => direction, :page => nil)
# OR
params.merge(:sort => column, :direction => direction, :page => nil).permit(:param_1, :param_2, :sort, :direction, :page)
If you don't know which parameters could be included in the link, then it's possible to call request.parameters.merge(...) (as mentioned in this answer) or params.to_unsafe_h.merge(...). However, as pointed out in comments, this is a security risk when the result is passed to link_to, as a parameter like host would be interpreted as the actual host for the link instead of a query parameter. There are several other keys that also have special meaning in link_to (everything accepted by url_for, plus :method), so it's generally a risky approach.

Rails: Setting class and data-tag of an HTML attribute with a single rails method

I'm currently working on a tour interface that guides new users around my site. I have a Tour model that has many TourStops, each of which contains information about a section of the site.
Basically, I'd like to write a function for the Tour model that -- when passed the number of a TourStop -- generates the correct class and data attribute for the HTML element it's attatched to. For example, I'd like
<%= link_to image_tag("new_button.png", tour.stop_data(1), :title => 'Add new asset'), new_asset_path %>
to call a function and return something like
def stop_data(order)
" :class => '#{tour_stops.find_by_order(order).name}',
:data => '{:order => order}'"
end
creating a link_to tag like:
<%= link_to image_tag("new_button.png", :class => 'tour_stop_1',
:data => {:order => 1}, :title => 'Add new asset'), new_asset_path %>
The above code doesn't work. Is something like this even possible? If not, what's a better approach I might take?
The image_tag accepts two parameters. A source, and a options Hash.
What you are trying to do is squeezing your return value from stop_data into this options Hash.
In order to get this to work, you first, need to return a Hash from stop_data, and second, make sure you pass only two arguments to image_tag - the source, and the options.
First:
def stop_data(order)
{
:class => tour_stops.find_by_order(order).name,
:data => { :order => order } # you may need order.to_json
}
end
Second:
link_to image_tag("new_button.png", tour.stop_data(1), :title => "Add new asset"), new_asset_path
This looks like it will work, but it won't, since your'e passing three parameters to image_tag.
When you do the following:
image_tag("new_button.png", :class => "tour_stop_1", :data => { :order => 1 }, :title => "Add new asset")
It looks like you're passing even 4 parameters to image_tag, but in fact they are only two. In Ruby, when the last parameter of a method is a Hash, you don't need to wrap the Hash key/value pairs in curly braces ({}), so the example above is essentially the same as
image_tag("new_button.png", { :class => "tour_stop_1", :data => { :order => 1 }, :title => "Add new asset" })
Now, to get your helper to work with image_tag, you need to merge the options, so they become only one Hash.
link_to image_tag("new_button.png", tour.stop_data(1).merge(:title => "Add new asset")), new_asset_path
Again, we're omitting the curly braces when calling merge, because it's only (and therefore last) parameter is a Hash. The outcome is the same as:
tour.stop_data(1).merge({ :title => "Add new asset" })

Problem with jQuery in rails

How create a link_to_remote in a jQuery script where url need a parameter that is a javascript variable.
I need create a link_to_remote in pure jQuery.
Thanks in advance
You'll want to use the :with parameter with link_to_remote:
link_to_remote( args[:title],
:update => args[:update],
:url => { :action => args[:action],
:id => id,
:starting => args[:starting]
},
:with => "'filter[viewer_id]=' + $('filter_viewer_id').value",
:loading => "Element.hide('#{args[:update]}');Element.show('#{args[:loading]}')",
:complete => "Element.show('#{args[:update]}');Element.hide('#{args[:loading]}')" )
Notice how I am sending the filter_viewer_id by getting it's value from a form field with jQuery. If you don't need that level of detail, just pass the name of your javascript variable.
Like this:
<%= link_to_remote('Hello', :url => "/test?id='+ id +'&test=true") %>
This will result in:
# => Hello
Very little info on your post. Are you using Rails 3? If so, did you check the jquery-rails gem out?
Best regards,
-- J. Fernandes

haml and no javascript? (rails: form_remote_tag and :with parameter)

i am trying to call a remote method to update page content via ajax/js.
either i am too tired already or haml is not parsing the following code correctly to send the value of the query field via prototype. any ideas?
- form_remote_tag(:url => {:controller => "search", :action => "line"},:with => "'query=' + $('query').value" ) do
%input{:type => 'text', :id => 'query'}
%input{:type => 'submit', :value => 'Search'}
thanks a lot!
t
Have you tried a
= form_remote_tag
instead of
- form_remote_tag
I'm new to HAML myself but I was under the impression that you'll need the form tag to be actually generated not just executed...
Try passing the :with as part of the options hash.
- form_remote_tag({ :url => {:controller => "search", :action => "line"}, :with => "'query=' + $('query').value" }) do
If that doesn't work, debug the problem: Look at the generated html. Is the text field with id query the only element in the page with that id? Is the js code correct? Use the Firebug console to ensure $('query').value returns whatever you've entered into the text field.
Still stuck? Add your generated html into your question so we can better help.
EDIT: Your query input tag does not have a name attribute. Without a name, the javascript helper code skips that field when serializing the form fields...also, you do not need the :with code.
%input{:type => 'text', :id => 'query', :name => 'query'}

remote_form_for in rails with the :with option

Is it possible to use the :with option with remote_form_for?
It works with link_to_remote, and the api docs seems to indicate :with should work with any of the remote_ methods.
Here is the code I'm using, and output it's producing:
Link_to_remote (works):
= link_to_remote 'ARGH', {:url => {:action => 'load_item', :id => #policy.id} , :with => "'elephant=mouse'"}
arg
Remote_form_for (doesn't work)
= remote_form_for :policy, #policy, :url => {:action => 'load_item', :id => #policy.id} , :with => "'elephant=mouse'" do |f|
<form action="http://localhost:3000/quote_edit/load_item/5" method="post" onsubmit="new Ajax.Request('http://localhost:3000/quote_edit/load_item/5', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">
Does anyone know how to make remote_form_for pick up on this option?
Or is it being ignored by remote_form_for as it needs to use parameters:Form.serialize(this) to pick up the values from the current form?
Cheers
Dave Smylie
I had the same problem when I wanted to use javascript to calculate the id of the url.
Researched the source code and determined that remote forms and submits don't seem to allow the :with statement to work.
I got around this using a hidden field called overridden_id on the form. Then in the :before option, I added javascript to set the hidden fields value.
Inside the controller I added "params[:overriden_id] || parmam[:id]" to my Find to override the default id passed into the url.

Resources