EDIT: looking for this: http://diminishing.org/extending-formtastic-with-a-sprinkle-of-jquery (If this works I'll answer my own question)
I've started to create an in and out type habtm (has many and belongs to many) form through formtastic. However I would like it to be more flexible to the user, meaning if you select a name on one side you either click a button that moves it right away (ajax on click) or after the form is submitted
(I'm using formtastic with this, but it doesn't have to in anyones examples)
What I am struggling with is the javascript, in and out buttons..
Comparison Model
class Comparison < ActiveRecord::Base
has_and_belongs_to_many :devices
end
Devices Model
class Device < ActiveRecord::Base
has_and_belongs_to_many :comparisons
end
Comparison Controller
def edit
#comparison = Comparison.find(params[:id])
#devices = Device.find(:all, :select => 'id, device_name', :order => 'device_name')
#devices_selected = #comparison.devices.find(:all, :order => 'device_name', :conditions => ["id IN (?)", #devices])
#devices_not_selected = Device.find(:all, :order => 'device_name', :conditions => ["id NOT IN (?)", #devices_selected])
end
Comparison Edit View
<% semantic_form_for #comparison do |f| %>
<% f.inputs do %>
<%= f.input :comparison_name %>
<%= f.input :description %>
<h3>
Select Devices
</h3>
<% f.inputs :class => 'inline_fields' do %>
<%= f.input :devices,
:collection => #devices_not_selected,
:label_method => :device_name,
:label => 'Add Devices',
:input_html => { :size => 20 },
:include_blank => false,
:hint => 'Select devices from this list to compare to the parent device' %>
<%= f.input :devices,
:collection => #devices_selected,
:label_method => :device_name,
:label => 'Remove Devices',
:input_html => { :size => 20 },
:include_blank => false,
:hint => 'Deselect devices from this list to take them off the comparison' %>
<% end %>
<% end %>
<%= f.buttons %>
<% end %>
I'll be using jquery to fix this problem:
http://quasipartikel.at/2009/05/10/jqueryui-multiselect/
or
http://blog.jeremymartin.name/2008/02/easy-multi-select-transfer-with-jquery.html#
Related
In our rails 3.1.4 app, there are user (parent) and user_levels (child) models.
class User < ActiveRecord::Base
attr_accessible :name, :login, :password, :user_levels_attributes, :as => :role_new
has_many :user_levels
ccepts_nested_attributes_for :user_levels, :allow_destroy => true, :reject_if => proc { |a| a['position'].blank? }
validates_associated :user_levels
end
class UserLevel < ActiveRecord::Base
belongs_to :user
validates_presence_of :position
end
The position column in user_level has to be filled. If it is not, both user and user_levels should NOT be saved. The problem with the above is that it always causes error of "position can't be blank" even there is a position value in the params.
{"utf8"=>"✓",
"user"=>{"name"=>"tester ceo",
"login"=>"testceo",
"update_password_checkbox"=>"[FILTERED]",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]",
"user_levels_attributes"=>{"1339886115748"=>{"position"=>"ceo"}}},
"commit"=>"Save"}
After deleting user_levels_attribues, the model saves user into users table no matter what kind of user_levels is filled int. We did extensive online search and haven't found a solution yet. For example, if validates_presence_of :user_levels is added to the user model, then none of the user levels can be saved or updated, even with a valid position.
Any suggestion about how to implement the orchestrated saving/updating of two associated models? Thanks so much.
UPDATE:
_user_level.html.erb:
<div class="fields">
<%= f.input :position, :collection => return_position, :prompt => "Choose position",
:label => false, :include_blank => true, :selected => i_id %>
<%= link_to_remove_fields "remove", f %>
</div>
_form_new.html.erb:
<%= simple_form_for #user do |f| %>
<%= f.input :name, :label => 'name:' %>
<%= f.input :login, :label => 'login:', :hint => '6 digits ' %>
<%= f.input :password, :label => 'password:', :hint => '6digits', :input_html => {:id => 'new_user_password'} %>
<%= f.input :password_confirmation, :label => 'confirmation:' %>
<%= f.input :user_type, :label => 'user type:', :collection => return_user_type, :include_blank => true %>
position:
<p><%= link_to_add_fields "Choose position", f, :user_levels %></p>
<p><%= f.button :submit, 'Save' %></p>
<% end %>
Here is the method to add position field:
#add user position in system user creation
def link_to_add_fields(name, f, association)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render :partial => association.to_s, :locals => {:f => builder, :i_id => 0}
end
link_to_function(name, "add_fields(this, \"#{association}\", \"#{j fields}\")")
end
JS file:
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).parent().before(content.replace(regexp, new_id));
}
I think you need to remove the :reject_if and change validates_associated :user_levels to validates_presence_of :user_levels.
I need some help with handling validations with Twitter Bootstrap properly. The validations are working properly, the issue is Twitter Bootstrap Flash screen. This is what I mean:
No fields filled out and submitted returns: http://i.stack.imgur.com/8pvUc.png
The 2 of the required 4 fields submitted returns: http://i.stack.imgur.com/J6lCi.png
(notice that it doesn't flash the errors)
I have a basketball app where a Player can be on many Rosters(for player roster archiving purposes) and a Roster can have many Players.
Roster.rb
class Roster < ActiveRecord::Base
belongs_to :team
has_many :rosterizes
has_many :players, :through => :rosterizes
accepts_nested_attributes_for :players
validates_presence_of :jersey_number, :class_year
attr_accessible :jersey_number, :class_year, :players, :team_id, :players_attributes
end
Rosterizes.rb(poorly named I know...)
class Rosterize < ActiveRecord::Base
belongs_to :player
belongs_to :roster
attr_accessible :player_id, :roster_id
end
Player.rb
class Player < ActiveRecord::Base
has_many :rosterizes
has_many :rosters, :through => :rosterizes
validates_presence_of :first_name, :last_name
attr_accessible :first_name, :last_name, :active
end
_add_player_form.html.erb
(nested form)
<%= simple_nested_form_for #roster, :url =>player_added_team_path, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.simple_fields_for :players, #roster.players.build do |x| %>
<%= x.input :first_name %>
<%= x.input :last_name %>
<%= x.input :active, :as => :hidden, :input_html => {:value => true} %>
<%end%>
<%=f.input :class_year %>
<%=f.input :jersey_number %>
<%=f.input :team_id, :as => :hidden, :input_html => {:value => params[:id]}%>
<div class="well">
<%= f.button :submit, :class => 'btn-primary icon-plus-sign btn-success', :value => "Add To Team" %>
</div>
<%end%>
Thanks for the help in advance!
SOLUTION
My problem is that every time the view was loaded, it was building a new form, thus never getting back the errors on the rollback
I made a change to my controller that builds for the nested form
Controller
def add_player
...
#new_player = #roster.players.build
end
And made the change accordingly to the view
_add_player_form.html.erb
<%= f.simple_fields_for :players, #new_player do |x| %>
...
<%end%>
This did the trick, thanks Mober!
the reason why only the first level validation is shown an the associated not is fairly simple... You do a <%= f.simple_fields_for :players, #roster.players.build do |x| %> which buildes the association ALWAYS new when the sites's rendered. What you want to is building the association only if it does not exists yet...
<% #roster.players.build if !#roster.players %>
<%= f.simple_fields_for :player do |player_form| %>
...
<% end %>
Twitter Bootstrap doesn't actually validate anything, it just provides styling for validation classes (error, success, etc).
Now, I'm not a Ruby expert by any means but it looks like you are ending your form early:
<%= f.simple_fields_for :players, #roster.players.build do |x| %>
<%= x.input :first_name %>
<%= x.input :last_name %>
<%= x.input :active, :as => :hidden, :input_html => {:value => true} %>
<%end%> <---- here
<%=f.input :class_year %>
<%=f.input :jersey_number %>
<%=f.input :team_id, :as => :hidden, :input_html => {:value => params[:id]}%>
Should be this?
<%= f.simple_fields_for :players, #roster.players.build do |x| %>
<%= x.input :first_name %>
<%= x.input :last_name %>
<%= x.input :active, :as => :hidden, :input_html => {:value => true} %>
<%= f.input :class_year %>
<%= f.input :jersey_number %>
<%= f.input :team_id, :as => :hidden, :input_html => {:value => params[:id]}%>
<% end %>
I want to make chain selects part inside my Formtastic form. But is it possible to set custom ids for multiple selects for future AJAX replacement?
This doesn't work:
<%= semantic_form_for [:admin, #production_year] do |f| %>
<%= f.inputs do %>
<%= f.input :car_model, :label => "CarModel", :as => :select, :collection => Brand.find(:all, :order => "name ASC"), :id => "brand_id" %>
<% end %>
<% end %>
Options should be passed to the input_html hash, like so:
<%= f.input :car_model, :input_html => { :id => "brand_id" } %>
I am trying to create a nested form using formtastic. I've included my code below but am running into some problems that I've also listed below. Any suggestions? Thanks.
# Home model
class Home < ActiveRecord::Base
has_many :home_members
accepts_nested_attributes_for :home_members, :reject_if => :all_blank, :update_only => true, :allow_destroy => true
end
# Form builder in members/new.html.erb
<%= semantic_form_for #home, :url => home_members_path(#home), :html => { :method => :post }, :remote => true do |f| %>
<%= f.inputs do %>
<%= f.semantic_fields_for :home_members do |h| %>
<%= h.input :name %>
<%= h.input :email %>
<%= h.input :birthday, :as => :string %>
<% end %>
<% end %>
# members_controller's new method; #home is set in a before filter
def new
2.times{ #home.home_members.build }
end
A default user is created when a Home is saved. How do I have the form display only the newly created records and not the existing one?
If #1 isn't possible, how do I make the existing record update? I have update_only set on the accepts_nested_attributes_for, but a new record is still created.
I am doing 2.times{ #home.home_members.build } in the controller action. When I print the size of #home.home_members I get 3 (one already exists) as expected. Why is the form only displaying 2 sets of inputs, one being populated with the existing home_member data?
well to answer question 1) show only the newly created objects
# Form builder in members/new.html.erb
<%= semantic_form_for #home, :url => home_members_path(#home), :html => { :method => :post }, :remote => true do |f| %>
<%= f.inputs do %>
<%= f.semantic_fields_for :home_members do |h| %>
<% if h.object.new_record? %>
<%= h.input :name %>
<%= h.input :email %>
<%= h.input :birthday, :as => :string %>
<% end %>
<% end %>
<% end %>
I've used cocoon with success in the past. https://github.com/nathanvda/formtastic-cocoon
I have a form I'm trying to set up ...
Users can have many posts, and each post can have many people watching it.
The Watch model is set up polymorphically as 'watchable' so it can apply to different types of models. It has a user_id, watchable_id, watchable_type and timestamps as attributes/fields.
This is soley so that when people comment on a post, users watching the post can get an email about it.
What I'm trying to do is show the user a list of users that they can tag on each post, which is not problem. This is what I'm using right now
http://pastie.org/940421
<% semantic_form_for #update do |f| %>
<%= f.input :subject, :input_html => { :class => 'short' } %>
<%= f.input :site, :include_blank => false, :input_html => { :class => 'short' } %>
<label>Tag Users (they will get notified of this update)</label>
<%= f.input :user, :as => :check_boxes, :label => ' ', :wrapper_html => { :class => "radiolist clearfix" }, :for => :watch, :name => "Watch" %>
<%= f.input :note, :label => 'Update'%>
<% f.buttons do %>
<%= f.commit_button :button_html => { :class => 'submit' } %>
<% end %>
<% end %>
The problem with this, is that when you go to edit an update/post ... all the checkboxes are prechecked ... I want it to pre-check only users who are currently watching the post.
To further clarify ... this is the hacky way I'm getting it to do what I want right now
<ul class="radiolist clearfix">
<% #users.each do |user| %>
<li>
<%= check_box_tag 'user_ids[]', user.id, #watches.include?(user.id) ? true : false -%>
<%= h user.name -%>
</li>
<% end %>
</ul>
where #watches is just an array of user ids
#watches = #update.watches.map{|watcher| watcher.user_id}
For anyone else having the same issue:
<%= f.input :some_input, :as => :boolean, :input_html => { :checked => 'checked' } %>
For multiple check boxes, this way:
<%= f.input :tags, :as => :check_boxes, :collection => some_map.collect { |c| [c[:name], c[:id], {:checked=> tag_ids.include?(c[:id])}] } %>
If you need the state of the checkbox to reflect the value of :some_input
<%= form.input :some_input, :as => :boolean, :input_html => { :checked => :some_input? } %>
In your model..
def some_input?
self.some_input ? true : false
end
Set the boolean attribute's value to 'true' in the controller before your render the form. That should make Formtastic default the checkbox to 'checked'.