Rails4: How to apply Bootstrap to simple_nested_form_for - ruby-on-rails

I'd like to apply bootstrap to the input fields as following.
<div class="input-group">
<span class="input-group-addon">Title</span>
<input type="text" class="form-control">
</div>
My current code is as following.
_form.html.erb
<%= simple_nested_form_for #event do |f| %>
<%= f.input :title %>
<%= f.input :description, input_html: { rows: 5, cols: 30 } %>
<%= f.input :charge_person %>
.
.
.
<% end %>
It would be appreciated if you could give me the best way in Rails.

This should do the trick:
<%= simple_nested_form_for #event do |f| %>
<div class="input-group">
<span class="input-group-addon">Title</span>
<%= f.input :title, class: 'form-control' %>
</div>
<div class="input-group">
<span class="input-group-addon">Description</span>
<%= f.input :description, class: 'form-control' %>
</div>
<div class="input-group">
<span class="input-group-addon">Charge Person</span>
<%= f.input :charge_person, class: 'form-control' %>
</div>
...
<% end %>

You shouldl read more detail SIMPLE FORM DOCS
<%= simple_nested_form_for #event, , wrapper_html: { class: 'input-group' } do |f| %>
<%= f.label :title, wrapper_html: { class: 'input-group-addon' } %>
<%= f.input_field :title, wrapper_html: { class: 'form-control' } %>
.
.
.
<% end %>

Related

file upload progress bar

i need to create a progress bar for my form ,
i want when the user click on submit button a progress bar appear and start uploading the mp3
i m using ruby on rails and paperclip gem
here is my code
<% provide(:title, "Upload") %>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#song, url: upload_path ) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :title, t('song.title') %>
<%= f.text_field :title, class: 'form-control', required: true %>
<%= f.label :artist, t('song.artist') %>
<%= f.collection_select :artist_id, #artists, :id, :name, {prompt: "Select a Artist"}, {class: "form-control selectpicker", "data-live-search" => "true", "required" => "true" } %>
<%= f.label :mp3, t('song.mp3') %>
<%= f.file_field :mp3 %>
</br>
<%= f.submit t('song.submit'), class: "btn btn-primary", data: { disable_with: 'Uploading'} %>
<% end %>
</div>
</div>
thanks
Edit 1 :
<% provide(:title, "Upload") %>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#song, url: upload_path ) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :title, t('song.title') %>
<%= f.text_field :title, class: 'form-control', required: true %>
<%= f.label :artist, t('song.artist') %>
<%= f.collection_select :artist_id, #artists, :id, :name, {prompt: "Select a Artist"}, {class: "form-control selectpicker", "data-live-search" => "true", "required" => "true" } %>
<%= f.label :mp3, t('song.mp3') %>
<%= f.file_field :mp3, required: true, multiple: true, name: 'song' %>
<div class="progress-wrapper">
<p>Bitrate: <span class="bitrate"></span></p>
<div class="progress">
<div class="progress-bar" role="progressbar">
0%
</div>
</div>
</div>
</br>
<%= f.submit t('song.submit'), class: "btn btn-primary", data: { disable_with: 'Uploading'} %>
<% end %>
</div>
</div>
<script>
$(document).ready(function() {
var upload = $('#new_song');
var wrapper = upload.find('.progress-wrapper');
var progress_bar = wrapper.find('.progress-bar');
var bitrate = wrapper.find('.bitrate');
upload.fileupload({
dataType: 'script',
add: function (e, data) {
types = /(\.|\/)(mp3)$/i;
file = data.files[0];
if (types.test(file.type) || types.test(file.name)) {
data.submit();
}
else { alert(file.name + " must be mp3 file"); }
}
});
upload.on('fileuploadstart', function() {
wrapper.show();
});
upload.on('fileuploaddone', function() {
wrapper.hide();
progress_bar.width(0); // Revert progress bar's width back to 0 for future uploads
});
upload.on('fileuploadprogressall', function (e, data) {
bitrate.text((data.bitrate / 1024).toFixed(2) + 'Kb/s');
var progress = parseInt(data.loaded / data.total * 100, 10);
progress_bar.css('width', progress + '%').text(progress + '%');
});
});
</script>
this is my try but not working
it give me error :
undefined method `permit' for # Did you mean? print
and the Bitrat not showing
http://img3.stooorage.com/images/669/20501499_screenshot-14--2016-west-08-02-14.png

Rails save not working on gem cocoon with different edit form

Friends , I have a model order that has many details. I am using the cocoon gem to generate forms . They render ok but are not saving . I click the button to save and nothing happens , and rails console shows nothing. The default edit form, called detail_fields saves with no problem. But i had to create this one called detail_fields_dev, and this one is not working. Can someone help?
routes.rb
resources :details
resources :orders
get '/orders/:id/devolucao' => 'orders#devolucao' , as: 'devolucao_order'
put '/orders/:id' => 'orders#update'
patch '/orders/:id' => 'orders#update'
orders_controller, is ok, using the default rails code. I created this action to call the detail_fields_dev form:
def devolucao
# #order = Order.find(params[:id])
end
The details params are ok too:
def order_params
params.require(:order).permit(:customer_id, :valor_total, :valor_total_dev, :item_total, :item_total_dev,:tipo,:descontado,:order_num, details_attributes: [:id,:order_id, :cod_produto, :desc_produto, :cod_cor, :desc_cor, :desc_tamanho,:preco,:quantidade,:quantidade_dev,:total, :total_dev,:barcode, :_destroy])
end
Order view:
_form_devolucao.html.erb
<%= simple_form_for(#order) do |f| %>
<%= f.error_notification %>
<div class="form-inputs form_fixed">
<%= f.input :customer, :as => :hidden %>
<%= f.input :tipo, :as => :hidden %>
<%= f.input :descontado, :as => :hidden %>
<%= f.input :valor_total, :as => :hidden %>
<%= f.input :item_total, :as => :hidden %>
<%= f.input :order_num, :as => :hidden %>
<div class="row">
<form action="#" method="post">
<div class="small-6 medium-3 columns leitor_dev">
Código de barras
(Leitor):
<input class = "cod_barras_dev" type="text" name="cod_barras_dev" value="" />
</div>
</form>
<div class="small-5 columns end not_found">
<span class="not_found">Produto não existe neste pedido!</span>
</div>
</div>
</div>
<div class="row">
<div class="small-12 columns">
<hr/>
<div id="details">
<%= f.simple_fields_for :details do |detail| %>
<%= render partial: "orders/detail_fields_dev", locals: {f: detail} %>
<% end %>
</div>
<hr/>
</div>
</div>
<div class="row">
<div class="small-12 columns">
<div class="form-actions container">
<%= link_to_add_association '+ ítens', f, :details, data: {"association-insertion-method" => :before, "association-insertion-node" => ".container " },:class => "button tiny radius add" %>
<br />
<br />
<br />
</div>
</div>
</div>
<div class="row">
<div class="small-6 medium-2 columns">
<%= f.button :submit, "Salvar" %>
</div>
<div class="small-6 medium-2 columns end">
<%= link_to 'Cancelar', orders_path, :class => "button alert"%>
</div>
</div>
<% end %>
And the partial orders/detail_fields_dev.html.erb
<div class="nested-fields">
<div class="row listCod" data-cod="<%= f.object.barcode %>">
<div class="small-6 columns show-for-small-only">
<%= f.input :barcode, label: "Cod Barras", input_html: { class: 'barcode_ror_dev' } %>
</div>
<%= f.input :order_id, :as => :hidden, input_html: { class: 'order_id_ror_dev' } %>
<div class="show-for-medium-up small-2 columns">
<%= f.input :cod_produto, label: "Produto", input_html: { class: 'cod_produto_ror_dev' } %>
</div>
<%= f.input :desc_produto,:as => :hidden, input_html: { class: 'desc_produto_ror_dev' } %>
<%= f.input :cod_cor,:as => :hidden, input_html: { class: 'cod_cor_ror_dev' } %>
<div class="small-2 show-for-medium-up columns">
<%= f.input :desc_cor,label: "Cor", input_html: { class: 'desc_cor_ror_dev' } %>
</div>
<div class="small-2 show-for-medium-up columns">
<%= f.input :desc_tamanho,label: "Tam", input_html: { class: 'desc_tamanho_ror_dev' } %>
</div>
<div class="small-2 show-for-medium-up columns">
<%= f.input :preco,label: "Preço",input_html: { class: 'preco_ror_dev' } %>
</div>
<div class="small-6 medium-2 columns">
<%= f.input :quantidade_dev,label: "Qtd Dev", input_html: { class: 'quantidade_ror_dev' } %>
</div>
<div class="show-for-medium-up medium-2 columns end">
<%= f.input :total_dev,label: "Total Dev",input_html: { class: 'total_ror_dev' } %>
</div>
<div class="small-1 columns end">
<%= link_to_remove_association "-", f, :class => "button tiny alert remove"%>
</div>
</div>
</div>
Output:
!(http://imgur.com/kVPpwY6)

Turbolinks and rails

I can't submit my post without refreshing edit page, I am using turbolinks gem and simple_form here is the source code:
<div class = "row">
<div class = "col-lg-9 col-md-8">
<%= simple_form_for #post do |f| %>
<div class = "form-group">
<%= f.input :title, :label => false %>
<%= f.input :content, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'MyToolbar', :height => 465} } %>
<%= f.input :cat_list, :label => "Type your tags here" %>
</div>
<%= link_to 'Show', #post %> |
<%= link_to 'Back', posts_path %>
</div>
<div class = "col-lg-3 col-md-4 ">
<div class = "form-group" data-no-turbolink >
<p>
<%= image_tag(#post.thumbnail.url(:original), :class => "img-thumbnail") %>
</p>
<p>
<%= f.file_field :thumbnail %>
</p>
<p>
<%= f.select :tag_list, Post::Months, { }, { :multiple => true, :size => 10, :class => "form-control" } %>
</p>
<p>
<%= f.button :submit, class: "btn btn-primary" %>
</p>
</div>
</div>
</div>
<% end %>
How can I solve this issue?
Please correct me if I have misunderstood your problem.
By default, Turbolinks works only for GET requests.
So, in your case, you are not using turbolinks to submit the page.
Notice the data-no-turbolink attribute added to <div class = "form-group">
<div class = "form-group" data-no-turbolink >
<p>
<%= image_tag(#post.thumbnail.url(:original), :class => "img-thumbnail") %>
</p>
<p>
<%= f.file_field :thumbnail %>
</p>
<p>
<%= f.select :tag_list, Post::Months, { }, { :multiple => true, :size => 10, :class => "form-control" } %>
</p>
<p>
<%= f.button :submit, class: "btn btn-primary" %>
</p>
</div>
Whenever turbolinks finds a data-no-turbolink attribute, it ensures that all anchor tags within it fallback to the default behavior i.e. ignore turbolinks
The 'edit' page however may have been rendered using turbolinks.

How do I fix this form the Rails way?

I want to have all the errors appear on top of their respective areas.
I ran an if statement with any? on the first one but I know I am repeating myself and have to do it the Rails way.
Any help?
<%= form_for #movie, :html => {:class => "form-horizontal"} do |f| %>
<div class="control-group">
<% if #movie.errors[:title].any? %>
<div class="alert alert-error"><%= #movie.errors[:title].to_sentence %></div>
<% end %>
<%= f.label :title, :class => "control-label" %>
<div class="controls">
<%= f.text_field :title %>
</div>
</div>
<div class="control-group">
<div class="alert alert-error"><%= #movie.errors[:description].to_sentence %></div>
<%= f.label :description,:class => "control-label" %>
<div class="controls">
<%= f.text_area :description, :class => "span8", :rows => "10" %>
</div>
</div>
<div class="control-group">
<div class="alert alert-error"><%= #movie.errors[:rating].to_sentence %></div>
<%= f.label :rating, :class => "control-label" %>
<div class="controls">
<%= f.select :rating, Movie::RATINGS, prompt: "Pick one" %>
</div>
</div>
<div class="control-group">
<div class="alert alert-error"><%= #movie.errors[:total_gross].to_sentence %></div>
<%= f.label :total_gross, :class => "control-label" %>
<div class="controls">
<%= f.number_field :total_gross %>
</div>
</div>
<div class="control-group">
<div class="alert alert-error"><%= #movie.errors[:released_on].to_sentence %></div>
<%= f.label :released_on, :class => "control-label" %>
<div class="controls">
<%= f.date_select :released_on, :order => [:month, :day, :year], :prompt => { :month => 'Select month',:day => 'Select day', :year => 'Select year' }, :start_year => 1950 %>
</div>
</div>
<div class="control-group" >
<%= f.label :image_file_name, :class => "control-label" %>
<div class="controls">
<%= f.text_field :image_file_name %>
</div>
</div>
<div class="form-actions">
<%= f.submit :class => "btn btn-success btn-large" %> <%= link_to "Cancel", root_path, class: "btn btn-danger btn-large" %>
</div>
<% end %>
Here's a solution that will be more DRY and won't necessitate gems like simple_form.
Create a partial for your control group and replace the field name and form field helper with variables:
# File: _control_group.html.erb
<% show_errors = true if show_errors.nil? %>
<div class="control-group">
<% if #movie.errors[field_name].present? && show_errors %>
<div class="alert alert-error">
<%= #movie.errors[field_name].to_sentence %>
</div>
<% end %>
<%= label_tag field_name, :class => "control-label" %>
<div class="controls">
field_helper
</div>
</div>
Then replace these items in your form with a partial render and pass the appropriate code in through the parameters:
<%= form_for #movie, :html => {:class => "form-horizontal"} do |f| %>
<%= render "control_group", field_name: :title, field_helper: f.text_field(:title) %>
<%= render "control_group", field_name: :description, field_helper: f.text_area(:description, :class => "span8", :rows => "10") %>
<%= render "control_group", field_name: :rating, field_helper: f.select(:rating, Movie::RATINGS, prompt: "Pick one") %>
<%= render "control_group", field_name: :total_gross, field_helper: f.number_field(:total_gross) %>
<%= render "control_group", field_name: :released_on, field_helper: f.date_select(:released_on, :order => [:month, :day, :year], :prompt => { :month => 'Select month',:day => 'Select day', :year => 'Select year' }, :start_year => 1950) %>
<%= render "control_group", field_name: :image_file_name, field_helper: f.text_field(:image_file_name), show_errors: false %>
<div class="form-actions">
<%= f.submit :class => "btn btn-success btn-large" %> <%= link_to "Cancel", root_path, class: "btn btn-danger btn-large" %>
</div>
<% end %>
Ran into a similar problem.
Using simple_form worked for me. See an example here

show rest of a form if a checkbox is ckecked in ruby on rails

I need to ask to my user if will pay a service with credit card...if it checked the option pay_with_card? it must show the rest of the form, that ask for other data like card number, mail, etc. if the user don't checked it, it must show a message, the question is...how can I do this? thanks in advance
<%= form_for(#product) do |f| %>
<%= f.label :pay_with_card? %>
<%= f.check_box :pay_with_card,{}, "Yes", "No"%>
<div>
<%= f.label :card_number %> <%= f.text_field :card_number %>
</div>
<div>
<%= f.label :mail %> <%= f.text_field :mail %>
</div>
<% end %>
Make the card number/mail details div style="display:none;", then add some javascript to the checkbox to change it to display:block;
Something like this:
<%= form_for(#product) do |f| %>
<%= f.label :pay_with_card? %>
<%= f.check_box :pay_with_card,{}, "Yes", "No"%>
<div id="card_details" style="display:none;">
<%= f.label :card_number %> <%= f.text_field :card_number %>
<%= f.label :mail %> <%= f.text_field :mail %>
</div>
<% end %>
<script type="text/javascript">
var checkbox = document.getElementById('product_pay_with_card');
var details_div = document.getElementById('card_details');
checkbox.onchange = function() {
if(this.checked) {
details_div.style['display'] = 'block';
} else {
details_div.style['display'] = 'none';
}
};
</script>
How about using jQuery?
First, wrap your credit card fields in a div with class credit_card_fields and than add this JS code to your page:
$("input[type='checkbox']#pay_with_card").on('change', function(){
$('.credit_card_fields').toggle();
});
You can use JS for it or move pay_with_card out of form like:
<%= link_to 'pay with card', your_current_path(:pay_with_card => 1) %>
<%= form_for(...) do |f| %>
<% if params[:pay_with_card] %>
<%= # fields for card %>
<% end %>
<% end %>
You can do it through jQuery, for example:
$ ->
$('select#pay_with_card').change ->
if $(this).val() == 'yes'
$('.card_block').slideDown('fast')
else
$('.card_block').slideUp('fast')
assumed that part of the form with payment card is included in the div with .card_block class
Ok my solution is this: all the code in the view, if a user check pay_with_card...(mi code is in spanish) it shows the complete form...if is not checked don´t show nothing, just the same checkbox asking for payment... thanks guys.
function mostrar (){
var checkbox = document.getElementById('chk_tarjeta');
if (checkbox.checked)
document.getElementById("card_details").style.display = "block";
else
document.getElementById("card_details").style.display = "none";
</script>
<h1>Forma de Pago</h1>
<%= form_for(#product) do |f| %>
<div id="product_pay_with_card">
<div >
<%= f.label :paga_con_tarjeta? %></br>
<%= f.check_box :paga_con_tarjeta, :id => "chk_tarjeta", :onclick => "mostrar();" %>
<div>
</div>
</div>
<div id="card_details" >
<div>
<%= f.label :numero_de_tarjeta %></br>
<%= f.text_field :numerotarjeta %>
</div>
<div>
<%= f.label :codigo_de_seguridad %></br>
<%= f.text_field :codigoseguridad %>
</div>
This worked for me with a form_with model and bootstrap
Change my_hidden_form with an id that makes sense for your form.
Original code is haml
= form_with scope: :model, url: models_path, local: true do |form|
.row
.col-6
.form-group
%h5.mb0 THE CASE TO TICK
= form.check_box :form_value, {:data => {:aria => {controls: :my_hidden_form, expanded: false}, :toggle => "collapse", :type => "checkbox", :target => "#my_hidden_form" }}
.row
.col-6
.form-group.collapse#my_hidden_form
%h5.mb0 THE FORM TO SHOW WHEN CASE IS TICKED
= form.text_field :name, placeholder: "A name"
.row
.col-md-12.text-right
= form.submit 'Submit', class: "btn btn-primary"
Converted to erb/html with https://haml2erb.org/
<%= form_with scope: :model, url: models_path, local: true do |form| %>
<div class="row">
<div class="col-6">
<div class="form-group">
<h5 class="mb0">THE CASE TO TICK
<%= form.check_box :form_value, {:data => {:aria => {controls: :my_hidden_form, expanded: false}, :toggle => "collapse", :type => "checkbox", :target => "#my_hidden_form" }} %>
</h5>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="form-group collapse" id="my_hidden_form">
<h5 class="mb0">THE FORM TO SHOW WHEN CASE IS TICKED
<%= form.text_field :name, placeholder: "A name" %>
</h5>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 text-right">
<%= form.submit 'Submit', class: "btn btn-primary" %>
</div>
</div>
<% end %>
Since the approach suggested by #Unixmonkey didn't work for me, here's a slight variation I put together using an event listener.
<script type="text/javascript">
const checkbox = document.getElementById('product_pay_with_card');
const details_div = document.getElementById('card_details');
checkbox.addEventListener("change", (event) => {
if (event.currentTarget.checked) {
details_div.style['display'] = 'block';
}
else {
details_div.style['display'] = 'none';
}
});
</script>

Resources