In my view I want the user to be able to browse a catalog of products. The hierarchy is as following:
Category
Product
AdditionalInfoForm
In my main view I render a partial for the categories:
#opContent
= render :partial => 'op_main_categories'
The op_main_categories partial is defined as following:
- #controller.getPortalCategories.each do |c|
= link_to_function "#{c.name}", :class => 'opCategoryHeaderText' do |page|
- partial = escape_javascript(render :partial => 'op_secondary_categories', :locals => { :c => c })
- page << "$('opContent').update(\"#{partial}\")"
When the user clicks a link in the above partial, the products are rendered by means of the op_secondary_categories partial:
- #controller.getPortalProductsForCategory(c).each do |p|
= link_to_function "#{p.name}", :class => 'opCategoryHeaderText' do |page|
- partial = escape_javascript(render :partial => 'op_did_line', :locals => { :p => p })
- page << "$('opContent').update(\"#{partial}\")"
op_did_line is plain text for now:
%p Yes, this is form! Hello?
This setup will generate the following link (for one category):
<a class="opCategoryHeaderText" onclick="$('opContent').update("<a class=\"opCategoryHeaderText\" href=\"#\" onclick=\"$(\'opContent\').update("<p>Yes, this is form! Hello?</p>\n"); return false;\">IPSDN + PVC 3yr<\/a>\n<a class=\"opCategoryHeaderText\" href=\"#\" onclick=\"$(\'opContent\').update("<p>Yes, this is form! Hello?</p>\n"); return false;\">PVC<\/a>\n"); return false;" href="#">PVC</a>
Adding the second tier of link_to_function breaks all of the code. I am no longer able to browse the hierarchy. When there is only one link_to_function present, I can browse.
This project is still using Rails 2.3. What is a better way to implement this?
My problem was solved using the answer in page.insert_html does not insert html with link_to_function (rails) by "Jose"
The code provided in the answer was put in rails/lib/rails_ext.rb
Related
There's this button / link in my web app. It's a button for a pizza - margherita with price, ingredients, and category, all already loaded to the db. Clicking this button loads the item's id to params, which is then used to find the object.
I want the click to launch the following chain of events:
Load the id
Find the object by id
Instantly render the object and its attributes in adjacent div on the same site.
Is this possible without JavaScript, just Ruby on Rails?
I am stuck at point 3. I have an idea, but incomplete. Please, give me a hint.
PS. My idea is to render views for index and show in separate divs next to one another.
#NickM, I added your code and it's throwing ActionController::UnknownFormat error, pointing at respond_to do |format| in show_pizza method.
Here's my pizzas/index.html.haml:
%h1= t :all_pizzas
- #pizzas.each do |pizza|
= render pizza
.orders
%h1 Orders
And pizzas/_pizza.html.haml:
%tr
= link_to pizza.name, show_a_pizza_path(pizza.id), :method => :post
%br/
I am getting this error upon clicking the link in _pizza.html.erb. My show_pizza.js is now:
pizza_div = $("#orders");
pizza_div.html( "<%= j render( :partial => 'pizzas/pizza', :locals => { :pizza => #pizza } ) %>" );
What am I missing? Sorry, I don't know js.
The short answer is no. When the link is clicked you will need to either render another page or handle the data returned by the controller with Javascript. The best option would be to set up an action that responds with JSON and parse what you get back on the front end.
Even after your P.S. you will have to handle the response from the server with Javascript, unless you are okay with rendering a new page. You need to post some code, preferably routes and controller action. This would also work:
<%= link_to("Show Pizza", show_a_pizza_path(#pizza.id), :method => :post, :data => {:remote => true}) %>
routes.rb
post 'show_pizza/:id' => "pizzas#show_pizza", :as => :show_a_pizza
pizzas_controller.rb
def show_pizza
#pizza = Pizza.find(params[:id])
respond_to do |format|
format.js
end
end
views/pizzas/show_pizza.js
pizza_div = $("#the_name_of_your_div");
pizza_div.html( "<%= j render( :partial => 'pizzas/pizza', :locals => { :pizza => #pizza } ) %>" );
and then put the pizza markup in /views/pizzas/_pizza.html.erb
this is my simple code
<%= render :partial => '/manage/regions/get_by_country', :locals => {:country_id => #last_search.country_id} %>
the #last_search.country_id has value (checked)
but while rendering the control seems that the country_id is null or empty
what i cant understand is that i use same syntax in another control and work us expected
i try also add hardcoded country_id
<%#id = 118%>
<%= render :partial => 'manage/regions/get_by_country', :locals => {:country_id => #id} %>
<%end%>
and not working
the control rendering but the country_id is null
OK i got the problem
the variable on the partial named #country_id
and i passed country_id (with no the '#')
i actually don't know why in one controller its work and on the other it doesn't work
but when i change the variable on the partial to country_id (with no the '#')
its work as expected
thanks
I have the following method in my controller:
def update_fees_collection_dates_voucher
#batch = Batch.find(params[:batch_id])
#dates = #batch.fee_collection_dates
render :update do |page|
page.replace_html "fees_collection_dates", :partial =>"fees_collection_dates_voucher"
end
end
the method calls the following partial in _fees_collection_dates_voucher.html.erb file:
<%= select :fees_submission, :dates_id, #dates.map { |e| [e.full_name, e.id]},{:prompt => "#{t('select_fee_collection_date')}"},{:onChange => "#{remote_function( :url => {:action => "load_fees_voucher"},:with => "'date='+value+'&batch_id='+#batch.id") }"} %>
The partial makes a remote call to the load_fees_voucher method when a selection list value is selected or changed. However, I'm unable to pass the information in the #batch instance variable (from my original method) to the remote method via the partial. If I change the #batch.id to a hard-coded value in the last line (under :with) the code runs fine but not in the current format. Is there a different procedure to access instance variables in partials ? Thanks!
You can use the same instance variable in the partials.
Try this,
<%= select :fees_submission, :dates_id, #dates.map { |e| [e.full_name, e.id]},{:prompt => "#{t('select_fee_collection_date')}"},{:onChange => "#{remote_function( :url => {:action => "load_fees_voucher"},:with => "'date='+value+'&batch_id='+#{#batch.id}") }"} %>
I have a rails app with working reports that have tags. In the Report/Index.html.erb I want the user to be able to sort the reports by selecting a tag. They may only select one tag at a time so I feel that a select box would work best. I currently have this:
<%= select("preferences", :tag_with,
["Politics", "Technology", "Entertainment", "Sports", "Science", "Crime",
"Business", "Social", "Nature", "Other"], :prompt => "Filter Feed by:" )%>
I have a working preferences controller with a method call tag_with that updates the current tag. This code, however, only generates the select box. I want it to be that when the user selects one of the tags, it calls the tag_with method from the preferences controller.
I generated a series of link_to lines that complete the task, however I would really like a select box.
<%= link_to "Politics", :action => "tag_with", :tag => "Politics", :controller =>"preferences" %>
<%= link_to "Entertainment", :action => "tag_with", :tag => "Entertainment", :controller =>"preferences" %>
<%= link_to "Science", :action => "tag_with", :tag => "Science", :controller =>"preferences" %>
<%= link_to "Technology", :action => "tag_with", :tag => "Technology", :controller =>"preferences" %>
And so on for each tag. This works fine but is bulky and undesirable. Is there a way to do the same thing through a select box?
In your reports.js.coffee file, or whatever other js file you want.
jQuery ->
$('select#preferences').change ->
$.get 'preferences/tag_with',{ term: $('option:selected', this). val() }
Or, if you want to use regular javascript:
$(function(){
$('select#preferences').change( function() {
$.get('preferences/tag_with',{term: $('option:selected',this).val()});
});
});
A link is a GET request. The jQuery .change() method fires whenever someone makes a change. The $.get method sends a GET request to a URL and can pass data (the second argument). This data becomes your params hash, so in the example above you would get:
params[:term] #=> the value attribute of whatever option was selected by the user
See the jQuery docs on .change() and $.get() for more help.
Update
For this to refresh the page, the easiest thing would be to extract the table that you want changed into a partial, let's assume it's called _report.html.erb. The partial should look something like this:
<div id="report">
<%= render #report %>
</div>
*Note: render #report is just short for render :partial => 'report'. See http://guides.rubyonrails.org/layouts_and_rendering.html*
In your preferences controller, tag_with option you should be sure to set the #report object (or whatever else is delivering the data to your partial).
Then you should make a file called views/preferences/tag_with.js.erb and put something like this in it:
$('div#report').html('<%= escape_javascript( render #report ) %>');
This will update the report container with the new content.
I'm using haml so hopefully you can understand the html going on here. It's easier to read in my opinion but some people don't like it :p
I have a form on my edit page that looks like this:
.center_col
-# I got into this weird habit of using "data-remote" for remote submission, w/e
= form_for #content, :html => {"data-remote" => true, :id => "page_editor", "data-page-id" => #content.id} do |f|
%h2
= f.label :textile, "Text", :class => 'inline'
(Parsed with
= link_to("Textile", "http://redcloth.org/textile/", :class => 'external') + ")"
%ul.fields
%li.field
= f.text_area :textile, :class => "full-field", "data-remote-preview" => preview_page_path(#content)
= display_error(:content, :textile)
%li.submit.left
= f.submit "Save Changes", :class => "rm_lr_margin"
When you submit the form I want the controller action to be rendering the _page partial. Right now the controller action is attempting to render 'pages/_page.js.haml', but I want to use 'pages/_page.html.haml' because I have an after-success jquery hook that automatically replaces the content in the edited area of the page with the new text.
Here's my action:
def update
load_content(params[:id])
#content.textile = params[:page][:textile]
if #content.save
render :partial => "pages/page", :content_type => "text/html", :layout => false, :locals => {:page => #content}
else
render :action => 'edit', :layout => false
end
end
Elsewhere...
def load_content(page_name)
#content = Page.find_by_name!(page_name)
#page = #content.name
end
So this is all working. Except it's rendering the wrong view :( When you first get to the page a section of it is populated using the 'pages/_page.html.haml' partial, and when you update the content with this ajax action I would like to use that same partial instead of having to duplicate the contents verbatim under the name 'pages/_page.js.haml'. Does anyone know what I'm missing here to make the action render haml content, not js content? When I perform the update right now it gives me this error:
Template is missing
Missing partial pages/page with {:formats=>[:js, "application/ecmascript", "application/x-ecmascript", "*/*"], :locale=>[:en, :en], :handlers=>[:rxml, :haml, :builder, :rjs, :rhtml, :erb]}
If I copy the html.haml file and name is .js.haml it works as expected.
This is the jquery I'm using to handle the events that rails.js is giving me when the form is submitted:
$('form#page_editor').live({
"ajax:beforeSend": function(xhr, settings){
$.facebox.loading();
},
"ajax:success": function(e, data, status, xhr){
$.facebox.close();
$('#page_' + $(this).attr('data-page-id')).replaceWith(data);
},
"ajax:error": function(e, xhr, status, error){
$.facebox(xhr.responseText);
}
});
Don't think that part was relevant but it shows you when in the JS I'm updating the content on the page. I suspect the problem is either in my action's render call, or the view's form_for call. Any help would be appreciated :)
You can ask for a specific format:
render :partial => "pages/page.html"