create record based on collection_select dropdown - ruby-on-rails

I am trying to create playlist records based on the dropdown selection. I'm going to put this in a bootstrap divided dropdown once functional. For now I have a dropdown and a link. The link does the thing, creates a new playlist obj with the values from the video it was clicked on, everything is a PORO until added as a playlist obj, where the video is persisted to the DB as a video obj. What I am wanting to do is, if you want to add a video to as a playlist obj, that you see a list of associated playlist names. When you click on the name, it does the same thing as the link_to but takes the name parameter along with it to create the new record. Thanks for any help.
PS. if you have tips on implementing the bootstrap that'd be wicked helpful too :D
<%= form_tag :playlists, {action: 'create'} do %>
<%= collection_select :playlist, :name, current_user.playlists, :id, :name, class: 'dropdown-item' %>
<%= link_to 'Create Playlist', new_playlist_path(etag: video.etag, video_id: video.video_id, user_id: current_user.id,
img_high: video.img_high, img_default: video.img_default,
title: video.title, description: video.description), class: 'dropdown-item' %>
<% end %>
Basically, what I'm trying to do is...be able to do what the link_to is doing but also take along the playlist name

Bind to the onchange event of the the select and trigger it's form to submit.
<%= collection_select :playlist, :name, current_user.playlists, :id, :name, class: 'dropdown-item', onchange: "this.form.submit()" %>
Here's an example:
<form action="https://google.com/">
<select name="q" onchange="this.form.submit()">
<option value="abc">Option 1</option>
<option value="123">Option 2</option>
</select>
</form>

Was finally able to get the passing the params, I still have to use a button as couldn't get the onchange: to work yet.
<%= form_tag :playlists, {action: 'create'} do %>
<%= hidden_field_tag :etag, video.etag %>
<%= hidden_field_tag :video_id, video.video_id %>
<%= hidden_field_tag :img_high, video.img_high%>
<%= hidden_field_tag :img_default, video.img_default %>
<%= hidden_field_tag :title, video.title %>
<%= hidden_field_tag :published_at, video.published_at %>
<%= hidden_field_tag :description, video.description %>
<%= hidden_field_tag :user_id, current_user.id %>
<%= collection_select :playlist, :name, current_user.playlists, :name, :name, {class: 'dropdown-item', onsubmit: 'this.form.submit()'} %>
<%= submit_tag 'Add', method: 'post' %>
Wasn't aware I could use the hidden_field_tag there like that :P

Related

Disable or hide a button when an object is empty Rails

How can I disable a button once the user was able to send a request. I used the logic of checking if an object in empty or has value in the controller and if the object is empty the user can submit a request otherwise the button will be hidden or disabled.
Object in the Controller
#c_req = Notification.where("message LIKE ?", "%{friend}%")
View
<%= form_for :friend, url: friends_path, method: :post do |f| %>
<%= f.hidden_field :message, :value => "Accepted your friend request" %>
<%= f.hidden_field :date, :value => #date %>
<%= f.submit 'Submit', :disabled => #c_req.present? %>
<% end %>
I used :disabled => #c_req.present? to check if it has a value.
If disabled attribute is added in any input field then it will be disabled either it is disabled = false.
You want to enable button if object is empty.
<%= form_for :friend, url: friends_path, method: :post do |f| %>
<%= f.hidden_field :message, value: "Accepted your friend request" %>
<%= f.hidden_field :date, value: #date %>
<%= f.submit 'Submit',class: "submit_btn" %>
<% end %>
<script type="text/javascript">
$(document).ready(function(){
<% unless #c_req.empty? %>
$(".submit_btn").attr('disabled', true)
<% end %>
})
</script>
Above js code runs when page is loading, if the #c_req is empty then your submit button is enable else disable
Try to replace <%= f.submit 'Submit', :disabled => #c_req.present? %> with <%= f.submit 'Submit', :disabled => !#c_req.present? %>
You have twisted the logic. You want to disable the button if it does NOT exist.
I'd try changing to .any? or .empty?
And be nice you your future self and name the variable better.
#present? is used to check if the item is there. Disabling has to happen if the item is not there. For that we have #empty?
Please don't use things like c_req, be a little descriptive in variable names. Also follow a code style, some thing like this...
Update to your code...
<%= form_for :friend, url: friends_path, method: :post do |f| %>
<%= f.hidden_field :message, value: "Accepted your friend request" %>
<%= f.hidden_field :date, value: #date %>
<%= f.submit 'Submit', disabled: #c_req.empty? %>
<% end %>
If you are hiding it... Use a similar query to decide not to show the button or hide the button from css.
Ex:
<%= f.submit 'Submit', class: ('hidden' if #c_req.empty?) %>
I guess you get the idea!

Rails 5 tags array turning into string

BLUF: My tags array for posts works fine to create and read the tags, but when I edit the post, the form field strips the tags array of their commas; the users has to manually re-enter the commas into the tags field, even if they aren't updating it, or else the tags get joined to together in one long string.
Details: using rails 5 and the acts_as_taggable_on gem.
My Post model
class Post < ApplicationRecord
acts_as_taggable
in my Controller:
private
def post_params
params.require(:post).permit(:post_type, :title, :content, :picture, :body_parts,
:duration, :equipment, :calories, :protein,
:fat, :carbs, :ingredients, tag_list:[] )
end
in my form view:
<%= form_for(#post, html: { multipart: true }) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<span class="glyphicon glyphicon-tags"></span>
<%= f.text_field :tag_list, multiple: true, class: 'form-control' %>
<%= f.submit "Save changes", class: "btn btn-primary" %>
<%= link_to "Cancel", post_path(#post), class: "btn btn-default" %>
<% end %>
in the post show view:
<%= raw post.tag_list.map { |t| link_to t, tag_path(t) }.join(', ') %>
I don't' know what else is relevant, but like I said, everything works fine until i try and edit the post, and then the text_field strips out the commas
Thanks in advance for any advice,
Add tags to text_field through value argument and convert them to comma delimiter string.
<%= f.text_field :tag_list, value: f.object.tag_list.to_s, multiple: true, class: 'form-control' %>

Formtastic f.input automatically adds parent name appear next to it

In my application, lists has_many books and books belong_to a list. I have this form for creating a new book in my rails application:
<div class="formtastic-control">
<%= semantic_form_for(#book) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.input :list, :as => :select, :include_blank => false %>
<%= f.text_field :title, class: 'form-control', placeholder: "Title" %>
<%= f.text_field :author, class: 'form-control', placeholder: "Author (optional)" %>
<%= f.submit "Add to library", class: "btn btn-default" %>
<% end %>
</div>
So the user can select which list they want to add the book to. I'm using formtastic to do that. The whole thing works fine, but I want to get rid of the word "list" which appears next to the select tag:
How can I do that? I know it's trivial, but it pushes the select tag to the right and I don't want it to do that.
I added :label => false and it worked, thanks.

Nested Form in rails 4

I have two Model Product and Supplier.
Product has_one supplier.
how to Build a Seach form inside a form.
,I want to Search Supplier and Put that id into My Product form.
Currently my code look like this.
<%= f.text_field :product_code, class: 'form-control'%>
<%= f.text_field :product_name, class: 'form-control'%>
<%= f.text_field :supplier_id, class: 'form-control'%>
<%= render :partial => 'supplier_search' %>
<%= f.submit 'Save', :class=>'button add'%>
Render suplier_search partial after submit button of product form.
<%= f.text_field :code, class: 'form-control'%>
<%= f.text_field :supplier_id, class: 'form-control'%>
<%= f.submit 'Save', :class=>'button add'%>
<%= render :partial => 'supplier_search' %>
Or
Don't have form in suplier_search partial. Just put input field or whatever you want, there and submit those fields via Ajax and get your required results in product form.
if its not partialing for <%= render :partial => 'supplier_search' %>
then use
"your views folder name/supplier_search" %>

Multiple values for collection_select

I am trying to have the following HTML code in my form:
<select name="user[language_ids][]">
<option value="">Please select</option>
<option value="1" selected="selected">English</option>
<option value="2">Spanish</option>
</select>
<select name="user[language_ids][]">
<option value="">Please select</option>
<option value="1" selected="selected">English</option>
<option value="2">Spanish</option>
</select>
To allow the User to select two languages when he signs up.
I have tried with this:
<%= f.label :languages %>
<%= f.collection_select(:language_ids, Language.all, :id, :name) %>
<%= f.collection_select(:language_ids, Language.all, :id, :name) %>
And also with this:
<%= f.label :languages %>
<%= f.collection_select(:language_ids[], Language.all, :id, :name) %>
<%= f.collection_select(:language_ids[], Language.all, :id, :name) %>
After revieweing the answers, I have tried with this:
<%= collection_select(:user, :language_ids, Language.all, :id, :name, {}, {:name => 'user[language_ids][]' }) %>
<%= collection_select(:user, :language_ids, Language.all, :id, :name, {}, {:name => 'user[language_ids][]' }) %>
But the problem here is that both of the selects have the same ID and also, they are not associated with the form builder f
Any thoughts on the best way to do so?
Try,
<%= f.collection_select(:language_ids, Language.all, :id, :name,{}, {:multiple => true}) %>
You can create a collection of fields by using
fields_for.
The two select will have the same id but
collection_select
takes an optional hash containings html options where you can set a custom id.
<%= f.fields_for :language_ids do |language| %>
<%= language.collection_select(nil, Language.all, :id, :name,
{include_blank: "Please select", selected: 1},
{id: :user_language_id_1}) %>
<%= language.collection_select(nil, Language.all, :id, :name,
{include_blank: "Please select", selected: 1},
{id: :user_language_id_2}) %>
<% end %>
generates the following output:
<select id="user_language_id_1" name="user[language_ids][]">
<option value="">Please select</option>
<option value="1" selected="selected">English</option>
<option value="2">Spanish</option>
</select>
<select id="user_language_id_2" name="user[language_ids][]">
<option value="">Please select</option>
<option value="1" selected="selected">English</option>
<option value="2">Spanish</option>
</select>
Since you wrote "user[language_ids][]" in the name attribute of your select, I'm forced to assume you want a multiple select box. You should do this:
f.collection_select (:language_ids, Language.all, :id, :name,
{:prompt => true}, {:multiple => true})
Not a very well documented feature, for sure.
EDIT: Looking further on your example and some of the answers, I would like to point out a few things:
Your example has the prompt "Please select" as first option of the select box, but then you want english to be "selected in both of your examples. If you want an option to be pre-selected which it as well the first option of the select box, then why do you have the prompt option? One uses it to force the user to choose something.
You wrote in one answer that you want multiple selects instead of a multiple select, reason why you don't want the :multiple => true solution. I'd still recommend you to use it, but maybe you really have a necessary use case. Therefore, I would recommend you to use the select_tag helper directly (I don't think you'll achieve that with form tag helpers):
select_tag "user[language_ids][]",
options_from_collection_for_select(Language.all, "id", "name"),
:prompt => true, :id => "user_language_ids"
key here is, the mutiple selects have to have different ids, which you will have to pass explicitly, so it'll be on your hands.
You should be able to do something like this:
<%= f.label :languages %>
<%= f.collection_select(:language_ids, Language.all, :id, :name, {}, {id => "language_1", :name => "user[language_ids][]"}) %>
<%= f.collection_select(:language_ids, Language.all, :id, :name, {}, {id => "language_2", :name => "user[language_ids][]"}) %>
Basically sending 2 (or more) fields with the same attribute doesn't work, because params will be turned into a hash : {language_ids: [1], language_ids: [2]} and since you have the same key the last one will override the previous one(s).
{a: 1, a: 2}[:a] #=> 2
To circumvent this problem you need to to create different attributes and then concatenate them in one. For this you'll need facade attributes in your model :
class Language
attr_writer :language_one_id, :language_two_id
before_save :gather_languages
def gather_languages
self.language_ids= [language_one_id, language_two_id]
end
# for the form to display chosen lang (idem with two)
def language_id
language_ids.first
end
end
# view/_form
=f.select :language_one_id, Language.all.map {|l| [l.name, l.id]}
=f.select :language_two_id, Language.all.map {|l| [l.name, l.id]}
But frankly I think you're making your life harder by going against conventions here (I'd use checkboxes instead).
You could add a "second_language" column to your table and then make it have the same content as the first language column.
You could use fields_for like this:
<%= form_for #user do |f| %>
...
<h2>Languages</h2>
<%= fields_for :languages do |lang_form| %>
<%= lang_form.collection_select :language_id, Language.all, :id, :name %>
<% end %>
..
<% end %>
On your controller, in your new or edit method, you can do this to accept 2 languages
2.times { #user.languages.build }
First of all you have to edit your user model:
user.rb
has_many :languages
accepts_nested_attributes_for :languages
Next generate model:
$> rails g model language user_id:integer name
language.rb
belongs_to :user
users_controller.rb (probably in 'new' action)
2.times do
language = #user.language.build
end
_form.html.erb
<%= form_for #user do |f| %>
<%= f.fields_for :languages do |lang| %>
<%= lang.label :name, "Name" %><br />
<%= lang.select :name, Language.all.collect {|l| [l.name, l.id]}, prompt: 'Please select' %><br />
<%= end %>
<p><%= f.submit "Submit" %></p>
<% end %>
Try This:
<%=select_tag "language_ids[]" options_for_select([['Please select','']]+Language.all.map{|ln|[ln.name,ln.id]})%>
uses the gem, gem "cocoon"
in the form of the model you want to add the field
<div class="form-group">
<%= f.fields_for :photoproducts do |forms_fields| %>
<% render partial: "shared/photoproducts_fields", locals: {f: forms_fields} %>
<% end %>
<%= link_to_add_association('+ Foto', f, :photoproducts, type: "button", class: "btn btn-primary btn-sm") %>
</div>
(In this example, I have a product template, which I'm adding photos to)
and then create a partial in a shared folder at the root of the project.
-
project / shared / _fotoproduto_fields.html.erb
<div class="nested-fields">
<%= link_to_remove_association('remove photo', f, type: "button", class: "btn btn-danger btn-sm") %>
<div class="photoproducts">
<div class="form-group">
<label class="control-label"><%= f.label :name %></label>
<%= f.text_field :name, class: "form-control", type: "text" %>
</div>
<div class="form-group">
<label class="control-label"> photo</label>
<%= f.file_field :files, class: "form-control" %><br/><br/>
</div>
</div>
</div>
this way you get a more dynamic form
remember to put parameters in the controllers for nested attributes, and put in the create method, a build of the model.
ex: #products.photoproducts.build

Resources