I have a form field where a user enters contact information, including name, email, etc. If they already have contacts saved I want to have a dropdown with their saved contacts. When a contact from the dropdown is selected, the contact fields should be populated with that data to allow for easy editing.
For some reason this approach isn't working:
In my new.html.erb view:
<%= f.collection_select :id, #contacts, :id, :name, :onchange =>
remote_function(:url =>{:action => 'populate_contact_form'}, :with => 'id') %>
In my controller:
def populate_contact_form
raise "I am working up to this point"
#contact = current_account.contacts.find(params[:id])
end
In populate_contact_form.rjs:
page['contact_name'].value = #contact.name
page['contact_email'].value = #contact.email
It seems my controller method is never called... can anyone explain how to do this?
It's not getting called because you're using remote_function incorrectly. Rails assumes the current action/controller/id/etc if any of those options are missing from the :url option to remote_function. You're passing :action as a top level option to remote_function, and it gets ignored. With a :url option Rails assumes the same action and controller that rendered this view.
This should fix your problem:
<%= f.collection_select :id, #contacts, :id, :name, :onchange =>
remote_function(:url =>{:action => 'populate_contact_form'}, :with => 'id') %>
Related
I am building a rails application using ActiveAdmin, and want to build a form for a custom action in the controller. I am trying to pass #listings from a collective_action to the rendered file, allowing me to edit multiple records at once. The #listings are based on an ActiveRecord query which draws record IDs from the URL.
It seems to be successfully accessing the parameters from the URL, and querying the database. When the form is served to the browser however, it is not able to produce the values of listing.title. Any ideas?
Here is my Listing.rb:
ActiveAdmin.register Listing do
collection_action :batch_upload do
ids = params[:id]
#listings = []
#listings = Listing.find(ids)
render template: 'listings/edit_batch'
end
end
Here is my edit_batch.html.haml:
= semantic_form_for :listing, :url => {:controller => 'listings', :action => 'batch_upload'}, :html=>{:method=>:put} do |f|
-#listings.each do |listing|
=f.hidden_field :id, :value => listing.id
=f.input :title, :value => listing.title
=f.submit "Submit"
If the form is correctly displaying listing.id but not listing.title then I suspect the record does not have title set, or listing does not have a title attribute.
To check, run the Rails console and find the record using the id from the form:
$ Listing.find(1)
Check the returned object to see whether it is missing the title.
I changed the code to the input so that it accesses its html directly and it worked:
=f.input :title, :input_html => { :value => listing.title }
Using Formtastic's inputs block might help simplify the inputs for each listing. Doing so will allow the form to create attribute fields for each Listing object.
# edit_batch.html.haml
= semantic_form_for :listing, :url => {:controller => 'listings', :action => 'batch_upload'}, :html=>{:method=>:put} do |f|
- #listings.each_with_index do |listing, index|
f.inputs for: listing, for_options: { index: index } do |l|
= l.input :id, as: :hidden
= l.input :title
= f.submit "Submit"
The :for and :for_options scope inputs fields to a specific object.
I'm trying to create a select box that takes data from my db. I'm having trouble setting this up. I tried this code:
<%= f.fields_for :unit do |u| %>
<%= u.label :name %>
<%= u.select :name, :class => "ingredient_unit", :prompt => "Please Select" %>
<% end %>
but I'm missing the part of the choices, I don't know how to pull them out of the database. I tried using collection_select, which worked, but then the class option wasn't working... collection_select went like this:
<%= u.collection_select :unit, Unit.all, :id, :name, :class => "ingredient_unit", :prompt => "Please Select" %>
I also don't understand what the first symbol means (:unit), it seems to be setting the html id and name, so that can be anything I want it to be?
You should look at the documentation for collection_select and select. But to answer your question, for the select part, you forgot to pass the list of options to choose from. You also need to swap the order for prompt and class since prompt is an option for the helper and class is an html option
<%= u.select :unit_id, Unit.all.map { |u| [u.name, u.id] }, { :prompt => "Please Select" }, { :class => "ingredient_unit" } %>
For the collection select
<%= u.collection_select :unit_id, Unit.all, :id, :name, { :prompt => "Please Select" }, { :class => "ingredient_unit" } %>
The first parameter passed to both helper is the column name where you want the selected answer to be saved. The 2 codes above just shows 2 different ways to generate the same select tag.
The first symbol tells it which field to populate with the id returned from the user selection.
Also, you should wrap your class section in {}
:unit refers to the model attribute that you're using for the select element. Yes, it will setup the name/id of the element (and name is the most important for the params hash).
To set a class in the collection_select, specify it as a hash as that helper takes it as an html_option.
<%= u.collection_select :unit, Unit.all, :id, :name, { :prompt => "Please Select" }, { :class => "ingredient_unit" } %>
I have players and fixtures that are in a HABTM relationship. This works well however when I am trying to add more that one player to the fixture using the following in my create new fixture view:
<li>Player 1<%= f.collection_select(:player_ids, Player.all, :id, :first_name, :prompt => true) %></li>
Only one player is submitted.
Controller
I have this at the moment in my fixture Controller
def create
#fixtures = Fixture.new(params[:fixture])
if #fixtures.save
flash[:notice] = "Fixture Created"
redirect_to(:action =>'list')
else
render('new')
end
end
View
<%=form_for(#fixtures, :url => {:action =>'create'}) do |f| %>
<li>Player 1<%= f.collection_select(:player_ids, Player.all, :id, :first_name, :prompt => true) %></li>
<li>Player 2<%= f.collection_select(:player_ids, Player.all, :id, :first_name, :prompt => true) %></li>
<li>Player 3<%= f.collection_select(:player_ids, Player.all, :id, :first_name, :prompt => true) %></li>
Could anyone help me out? I would prefer check boxes or a multiple select box where i could hold shift however I am finding these really hard to use. This I managed to submit values.
Thanks
If anyone needs any more informations on controllers or models I can edit these in to the quesiton
You need appropriate naming of fields. Each select must have name like fixture[player_ids][]
I doubt this is possible with #collection_select method, try more common #select_tag instead
I'm trying to create a <select> element using the collection_select method, but it seems that in order for the proper <option> to be selected, the identifier passed into collection_select needs to be an instance variable and not a local variable (this is happening in a partial).
So when I create a <select> for the categories of a product, the proper category is NOT selected by default.
_product_row.erb (DOES NOT WORK):
My product: <%= product.name %>
<%= collection_select(:product, :category_id, #current_user.categories, :id, :name, options = {:prompt => "-- Select a category --"}) %>
Screenshot:
alt text http://img534.imageshack.us/img534/8929/screenshot20100421at120.png
I discovered that I was able to get it to work by declaring an instance variable before hand, but this seems like a huge hack to me.
_product_row.erb (WORKS):
<% #product_select_tmp = product %>
<%= collection_select(:product_select_tmp, :category_id, #current_user.categories, :id, :name, options = {:prompt => "-- Select a category --"}) %>
Screenshot:
alt text http://img534.imageshack.us/img534/1958/screenshot20100421at120l.png
Because this partial is iterating over a collection of products, I can't just have #product declared in the controller (IOW unless I'm missing something, product must be a local variable in this partial).
So how do I get collection_select to select the appropriate item when calling it with a local variable?
Have you tried passing in the :selected key in the options hash? If you provide it with the current product.id it should behave the way you're expecting.
<%= collection_select(:product, :category_id, #current_user.categories, :id, :name, {:prompt => "-- Select a category --", :selected => product.category.id}) %>
You can pass collections to partials and designate a local variable to pass them as:
<%= render :partial => "products/product_row", :collection => #products, :as => :products %>
Relevant documentation: http://apidock.com/rails/ActionView/Partials
I am trying to implement something seemingly very simple, and I have been beating my head against it for days at this point.
My desired end result is a Country select drop-down, tied to a State select drop-down, in such a way that when a given country is selected, IF states are known THEN those states are displayed in a select drop down, and if NO states are known for that country, then a text field is displayed instead.
I feel like I am almost there. At this point the interface will actually generate that list of states based on the persons' country, except it is refusing to update the drop-down dynamically.
The portion of my view where country and state location is gathered looks like:
# _person_setup.html.erb
<td>
<%= f.label :country, 'Select your country' %>*<br />
<%= f.select :country, Carmen::country_names, {},
{:style => 'width: 200px',
:id => 'country_select',
:onchange => remote_function(
:url => {:action => 'update_states'},
:with => "'country='+value")} %>
</td><td>
<p>
<div id="states_div">
<%= render :partial => 'states',
:object => Carmen::states(
Carmen::country_code(
#person.country)),
:locals => {:form => f} %>
</div>
</p>
</td>
The partial being referenced in the DIV is as follows:
# _states.html.erb
<% unless states.nil? or states.empty? %>
<%= form.label :state, 'Select your state' %>*<br />
<%= form.select :state, states.collect{|s| [s[0], s[0]]} %>
<% else %>
<%= form.label :state, 'Please enter state or province' %>*<br />
<%= form.text_field :state %>
<% end %>
Finally, the controller code which is intended to update the list of states dynamically:
def update_states
puts "Attempting to update states..."
q = params[:country]
states = Carmen::states(Carmen::country_code(q))
puts "Country = #{q}, states = #{states.collect{|s| s[0]}.join(", ")}."
render :update do |page|
page.replace_html "states_div",
:partial => 'states',
:object => states,
:locals => {:form => form_for(#person)}
end
puts "OK"
end
Now, this code is being called at the proper time and generating the appropriate lists of states. For example, when the user clicks Australia, "Attempting to update states... Country = Australia, states = Australian Capital Territory, New South Wales, Northern Territory, Queensland, South Australia, Tasmania, Victoria, Western Australia" shows up in the server process. However it doesn't update the page, and won't print the "OK" at the end. In short the line which is failing is undoubtedly
page.replace_html "states_div",
:partial => 'states',
:object => states,
:locals => {:form => form_for(#person)}
Note that replacing this line with
page.replace_html 'states_div', "<b>is it working</b>"
properly replaces the div, but of course not with anything useful.
Can someone help me understand what is going on here?
It looks like you're assuming that the #person variable is still available from your original action. This could be set up by a filter for the current person but you don't show that in your question.
If you do need to lookup the #person again you'll have to pass the id through in your remote_function I think.
Ryan Bates has a Railscast that shows how to select a category for a product or create a new category by typing the name. It sounds like a similar scenario to what you have, so you might want to check it out: Create Model Through Text Field.
This took me a full day to figure out something that would at least "work". I am also using Carmen and also messing with the select tag in a form_for model form (actually, fields_for nested within forms_for...which adds additional complications).
I would think there is a better solution but this worked for me. The select needs to be referenced by the form but the options don't. Thus, first time through, I use the Carmen state_select method which populates the select tag correctly and all the nested options tags. The second time through, I just replace the options. Take a look:
In the view, I chose to use an observe_field method since I do other things besides update the states (some other localization changes) but this should work for remote_function and others, too:
<%= address_form.country_select :country, {:prompt => "--Select One--"} %>
Don't be confused by the id (user_address_attributes_country) it is just my silly forms_for/fields_for implementation)
<%= observe_field :user_address_attributes_country, :url => { :action => :changecountry }, :with => 'new_country' %>
<%= address_form.state_select :state, #user.address.country, {:prompt => "--Select One--"}, :style => 'width: 90px' %>
Then in my controller, it just looks like this:
def changecountry
c = params[:new_country]
respond_to do |format|
format.html
format.js {
render :update do |page|
page['user_address_attributes_state'].innerHTML = \
"<option>--Select One--</option>" + state_options_for_select(nil, c)
end
}
end
end
Note: state_options_for_select is also from Carmen. I could not get it to work unless I put it inside the respond_to block where I guess the view helpers are available. Also, I hard code user_address_attributes_state which is my nested id generated from the form_for/fields_for address_form.state_select rendering call in the view.
I hope this helps. If anyone can do it better, believe me, I'm all ears. I'll change the design in time...but needed something that just worked today and this was the best I could figure out in a limited time.