Simple Form For that adapts based on checkbox input - ruby-on-rails

I am working on a personal project where I want users to be able to create profiles (I am using Devise to handle users). These can either be public or private, whereby public profiles require more input fields than private profiles. Is there any way I can cause these additional form fields to only appear if the user chooses his profile to be public?
I tried looking on StackOverflow and previous threads on here but couldn't find anything. I saw a few suggestions for the Cocoon gem but couldn't get that to work.
<%= simple_form_for(#User, url: registration_path(#User)) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :first_name, required: true, autofocus: true %>
<%= f.input :email,
required: true,
input_html: { autocomplete: "email" }%>
<%= f.input :public, required: false, label: "Enable public profile?" %>
## Ideally the following two-fields would only show if public is clicked
## Best case they would be required fields if this happens and not required if
it does not
<%= f.input :linkedin_link, required: false, label: "Linked-In Profile Link" %>
<%= f.input :photo, as: :file, label: "Profile Picture", accept: "image/*", hint: "Why not use your Linked-In profile picture? (png and jpg only)" %>
<%= f.input :password, required: true, hint: ("#{#minimum_password_length} characters minimum" if #minimum_password_length), input_html: { autocomplete: "new-password" } %>
<%= f.input :password_confirmation, required: true, input_html: { autocomplete: "new-password" } %>
<%= f.button :submit, "Sign up", class: "btn-success btn-full-width" %>
</div>
<% end %>
Looking forward to learning something new :) Thanks a lot for your help!

Managed to solve it with this.
JS:
$(function () {
$('div[name="showthis"]').hide();
//show it when the checkbox is clicked
$('input[type="checkbox"]').on('change', function () {
if ($(this).prop('checked')) {
$('div[name="showthis"]').fadeIn();
} else {
$('div[name="showthis"]').hide();
}
});
});
HTML:
<div class="form-inputs">
<%= f.input :first_name, required: true, autofocus: true %>
<%= f.input :email, required: true, input_html: { autocomplete: "email" }%>
<%= f.input :public, required: false, label: "Enable public profile?" %>
<div name="showthis">
<%= f.input :linkedin_link, required: false, label: "Linked-In Profile Link" %>
<%= f.input :photo, as: :file, label: "Profile Picture", accept: "image/*", hint: "Why not use your Linked-In profile picture? (png and jpg only)" %>
</div>
<%= f.input :password, required: true, hint: ("#{#minimum_password_length} characters minimum" if #minimum_password_length), input_html: { autocomplete: "new-password" } %>
<%= f.input :password_confirmation, required: true, input_html: { autocomplete: "new-password" } %>
<%= f.button :submit, "Sign up", class: "btn-success btn-full-width" %>
</div>

Related

Specify visible input fields from simple_form layout

I'm loading two views that render a simple_form form layout, new and edit.
I need to show all input fields when the user profile is initially being created (new), and specify fields that will not show when it is being used for edit. I've seen a lot of info around persisted but can't figure it out.
My _form.html.slim file.
= simple_form_for([:admin, User.new]) do |f|
= f.error_notification
.form-inputs
= f.input :name, required: true, label: 'Name'
= f.input :email, required: true
= f.input :password, required: true, placeholder: ("#{#minimum_password_length} characters minimum" if #minimum_password_length)
= f.input :password_confirmation, required: true
.form-actions
= f.button :submit, "Create User", class: 'btn btn-primary btn-block btn-lg'
I'm using Rails and Slim - Any help appreciated.
You can indeed use persisted? to conditionally render the fields in form.
= simple_form_for([:admin, User.new]) do |f|
= f.error_notification
.form-inputs
= f.input :name, required: true, label: 'Name'
= f.input :email, required: true
-# Say you don't want user to edit his password after creation
- unless f.object.persisted?
= f.input :password, required: true, placeholder: ("#{#minimum_password_length} characters minimum" if #minimum_password_length)
= f.input :password_confirmation, required: true
.form-actions
= f.button :submit, "Create User", class: 'btn btn-primary btn-block btn-lg'
Here f.object will be the User instance for which the form will be rendered.

How to add class to form components with simple_form

Does anyone know how to add a class to a ruby on rails simple form, and how to add a class to an individual component so that I can style them later in CSS. Thank you
Straight from the simpleform docs:
It is also possible to pass any html attribute straight to the input, by using the :input_html option, for instance:
<%= simple_form_for #user do |f| %>
<%= f.input :username, input_html: { class: 'special' } %>
<%= f.input :password, input_html: { maxlength: 20 } %>
<%= f.input :remember_me, input_html: { value: '1' } %>
<%= f.button :submit %>
<% end %>
If you want to pass the same options to all inputs in the form (for example, a default class), you can use the :defaults option in simple_form_for. Specific options in input call will overwrite the defaults:
<%= simple_form_for #user, defaults: { input_html: { class: 'default_class' } } do |f| %>
<%= f.input :username, input_html: { class: 'special' } %>
<%= f.input :password, input_html: { maxlength: 20 } %>
<%= f.input :remember_me, input_html: { value: '1' } %>
<%= f.button :submit %>
<% end %>
Just adding a point to #bmac151's answer above.
For styling or dynamic scripting (e.g. javascript) purposes, you can also provide an ID to distinguish the elements from other elements of the same class by providing the id option, like so:
<%= simple_form_for #user, html: { id: 'simple-form' } do |f| %>
<%= f.input :username, input_html: { class: 'special', id: 'username' } %>
<%= f.input :password, input_html: { maxlength: 20, id: 'password' } %>
<%= f.input :remember_me, input_html: { value: '1', id: 'remember_me' } %>
<%= f.button :submit, id: 'submit-button' %>
<% end %>
This will give you unique IDs for all of the elements in the form, as well as the form itself.
From CSS, you can refer to these for styling, like this:
#simple-form {
font-size: 125%;
}
#submit-button {
text-transform: uppercase;
}
From Javascript, you can refer to elements by their element ID, as well. With this, you can apply dynamic behaviors to individual elements, rather than whole classes at a time. Here's a Javascript example:
var submit_button = document.getElementById("submit-button");
submit_button.addEventListener("click", function () {
alert('Yeeehaaah!');
submit_button.submit();
});
For fine-grained control, you'll want to use the id attribute rather than the class attribute; however, for theme-like control of elements, the class attribute is more useful.
<%= f.button :submit, "Sign in", class: "submit-button" %>

Rails 4.1 Carrierwave not uploading images

I am using the carrierwave gem to upload images of movie listings. I have created a migration creating a image column to my listings database.
updated the Listing model.rb file
class Listing < ActiveRecord::Base
mount_uploader :image, ImageUploader
belongs_to :user
end
added the :html = > { multipart: true } command to my simple form
<div class="wizard-container">
<%= simple_form_for(#listing, url: new_user_registration_path, method: :get, :html => { multipart: true } ) do |f| %>
<div class="card wizard-card ct-wizard-orange" id="wizard">
<!-- You can switch "ct-wizard-orange" with one of the next bright colors: "ct-wizard-blue", "ct-wizard-green", "ct-wizard-orange", "ct-wizard-red" -->
<div class="wizard-header">
<h3>
<b>LIST</b> YOUR MOVIE <br>
<small>This information will let us know more about your movie</small>
</h3>
</div>
And the image field to my listing.html.erb file
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<%= f.file_field :image %><br>
</div>
</div>
but when i create a listing the folloeing information , appears in console
Started GET "/users/sign_up?utf8=%E2%9C%93&listing%5Btitle%5D=Top+Gun&listing%5Btime%5D=14.35&listing%5Bdate%5D=24%2F03%2F2016&listing%5Bseats%5D=5&listing%5Bvenue_name%5D=Preston+Library&listing%5Bimage%5D=IMG_0892.JPG&listing%5Bprice%5D=2.3&listing%5Blocation%5D=Preston+Town+Hall&listing%5Bother_info%5D=This+is+a+great+venue&listing%5Bprojector%5D=0&listing%5Bcables%5D=0&listing%5Blaptops%5D=0&listing%5Bseating%5D=0&listing%5Bblinds%5D=0&listing%5Binternet%5D=0&listing%5Blighting%5D=0&listing%5Bcamcorder%5D=0&listing%5Bcatering%5D=0&listing%5Btoilets%5D=0&listing%5Bfire%5D=0&listing%5Bfire%5D=1&commit=Create+Listing" for 127.0.0.1 at 2015-03-24 14:36:31 +0000
Processing by Devise::RegistrationsController#new as HTML
Parameters: {"utf8"=>"✓", "listing"=>{"title"=>"Top Gun", "time"=>"14.35", "date"=>"24/03/2016", "seats"=>"5", "venue_name"=>"Preston Library", **"image"=>"IMG_0892.JPG",** "price"=>"2.3", "location"=>"Preston Town Hall", "other_info"=>"This is a great venue", "projector"=>"0", "cables"=>"0", "laptops"=>"0", "seating"=>"0", "blinds"=>"0", "internet"=>"0", "lighting"=>"0", "camcorder"=>"0", "catering"=>"0", "toilets"=>"0", "fire"=>"1"}, "commit"=>"Create Listing"}
So it captures the image but does mot display the image?
this app is slightly different to what i normally do , I make the user sign in first and then create details ,this app you create listings and then create an account
new.html.erb
<%= render 'layouts/header' %>
<h2 class="text-center">Sign up</h2>
<%
if !user_signed_in?
resource.listings.build
resource.listings[0].title = params[:listing][:title]
resource.listings[0].time = params[:listing][:time]
resource.listings[0].date = params[:listing][:date]
resource.listings[0].seats = params[:listing][:seats]
resource.listings[0].venue_name = params[:listing][:venue_name]
resource.listings[0].location = params[:listing][:location]
resource.listings[0].other_info = params[:listing][:other_info]
resource.listings[0].price = params[:listing][:price]
resource.listings[0].projector = params[:listing][:projector]
resource.listings[0].cables = params[:listing][:cables]
resource.listings[0].laptops = params[:listing][:laptops]
resource.listings[0].seating = params[:listing][:seating]
resource.listings[0].blinds = params[:listing][:blinds]
resource.listings[0].lighting = params[:listing][:lighting]
resource.listings[0].camcorder = params[:listing][:camcorder]
resource.listings[0].catering = params[:listing][:catering]
resource.listings[0].toilets = params[:listing][:toilets]
resource.listings[0].fire = params[:listing][:fire]
resource.listings[0].internet = params[:listing][:internet]
end
%>
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: {class: "form-signin"}) do |f| %>
<%= f.error_notification %>
<%= f.input :name, required: true, autofocus: true, label: false, placeholder: "Name", input_html: {class: "form-control"} %>
<%= f.input :email, required: true, label: false, placeholder: "Email", input_html: {class: "form-control"} %>
<%= f.input :password, required: true, label: false, placeholder: "Password", input_html: {class: "form-control"} %>
<%= f.input :password_confirmation, required: true, label: false, placeholder: "Password Confirmation", input_html: {class: "form-control"} %>
<div style="display:none">
<%= f.fields_for :listings do |listing_form| %>
<%= listing_form.input :title, label: false, placeholder: "Movie Title", input_html: {class: "form-control"} %>
<%= listing_form.input :time, label: false, placeholder: "What time does your movie start?", input_html: {class: "form-control"} %>
<%= listing_form.input :date, label: false, placeholder: "What date", input_html: {class: "form-control"} %>
<%= listing_form.input :seats, label: false, placeholder: "Number of seats", input_html: {class: "form-control"} %>
<%= listing_form.input :venue_name, label: false, placeholder: "Name of venue", input_html: {class: "form-control"} %>
<%= listing_form.input :location, label: false, placeholder: "Address", input_html: {class: "form-control", rows: 5 } %>
<%= listing_form.input :other_info, label: false, placeholder: "Other information", input_html: {class: "form-control", rows: 5} %>
<%= listing_form.input :price, label: false, placeholder: "Ticket Price (£)", input_html: {class: "form-control"} %>
<p> Projector </p>
<%= listing_form.input :projector, required: false, label: false %>
<p> Cable </p>
<%= listing_form.input :cables, required: false, label: false %>
<p> Laptop </p>
<%= listing_form.input :laptops, required: false, label: false %>
<p> Seating </p>
<%= listing_form.input :seating, required: false, label: false %>
<p> Blinds </p>
<%= listing_form.input :blinds, required: false, label: false %>
<p> Lighting </p>
<%= listing_form.input :lighting, required: false, label: false %>
<p> Camcorder </p>
<%= listing_form.input :camcorder, required: false, label: false %>
<p> Catering </p>
<%= listing_form.input :catering, required: false, label: false %>
<p> Toilets </p>
<%= listing_form.input :toilets, required: false, label: false %>
<p> Fire alarm </p>
<%= listing_form.input :fire, required: false, label: false %>
<p> Wifi/internet </p>
<%= listing_form.input :internet, required: false, label: false %>
<% end %>
</div>
<%= f.button :submit, "Sign up", class: "btn btn-primary btn-block" %>
<%= render "devise/shared/links" %>
<% end %>
application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(
:name,
:email, :password, :confirmation_password,
listings_attributes: [
:title, :time, :date, :seats,
:venue_name, :location, :other_info,
:price, :projector, :cables,
:laptops, :seating, :blinds,
:lighting, :camcorder, :catering,
:toilets, :fire, :internet, :image
]
)
end
devise_parameter_sanitizer.for(:account_update) << :name
end
end
any thoughts
Neil
rake routes
Rails.application.routes.draw do
resources :listings
devise_for :users
root 'pages#home'
get 'about' => 'pages#about'
get 'pages/contact'
get 'dashboard' => 'pages#dashboard'
get 'start' => 'listings#listing'

Rails 4.1: NameError in Jobs#new

Want to show different job categories for my jobs board , using the simple form gem I have added the following to my jobs form.
_form.html.erb
<%= simple_form_for(#job, html: { class: 'form-horizontal' }) do |f| %>
<%= f.collection_select :category_id, Category.all, :id, :name, {prompt: "Choose a category" }, input_html: { class: "dropdown-toggle" } %>
<%= f.input :title, label: "Job Title", input_html: { class: "form-control" } %>
<%= f.input :description, label: "Job Description", input_html: { class: "form-control" } %>
<%= f.input :company, label: "Your Company", input_html: {class: "form-control" } %>
<%= f.input :url, label: "Link to Job", input_html: { class: "form-control" } %>
<br/>
<div class="form-group">
<%= f.submit class: "btn btn-primary" %>
</div>
<% end %>
but when i go to jobs.new.html it generates the following error
NameError in Jobs#new
Showing /Users/neilpatel/Desktop/Rails/jobs_board/app/views/jobs/_form.html.erb where line #3 raised:
uninitialized constant ActionView::CompiledTemplates::Category
<%= simple_form_for(#job, html: { class: 'form-horizontal' }) do |f| %>
**<%= f.collection_select :category_id, Category.all, :id, :name, {prompt: "Choose a category" }, input_html: { class: "dropdown-toggle" } %>** -<error
<%= f.input :title, label: "Job Title", input_html: { class: "form-control" } %>
Error specifies you don't have Category Model in your application. That's why rails considering Category as constant and throwing this error uninitialized constant. Try add Category Model in you app/models directory.
<%= f.collection_select :category_id, Category.all, :id, :name, {prompt: "Choose a category" }, input_html: { class: "dropdown-toggle" } %>
Category.all Should be Modelname.all

Rails - simple form

I use simple_form gem in my Rails app. When I use code like this
= f.input_field :name, label: false, placeholder: 'Name'
= f.input_field :price, label: false, placeholder: 'Price'
= f.input_field :description, label: false, placeholder: 'Description'
= f.input_field :image, label: false, placeholder: 'Image'
I get HTML for input:
<input class="string required textform" id="item_name" label="false" maxlength="255" name="item[name]" placeholder="Имя" size="255" type="text">
As you can see size of input is 255 now. Actually it's much more than enough. How can specify the size of inputs?
Following is from simple_form documentation here
It is also possible to pass any html attribute straight to the input,
by using the :input_html option, for instance:
<%= simple_form_for #user do |f| %>
<%= f.input :username, input_html: { class: 'special' } %>
<%= f.input :password, input_html: { maxlength: 20 } %>
<%= f.input :remember_me, input_html: { value: '1' } %>
<%= f.button :submit %>
<% end %>
To set size of 100 for name input:
= f.input :name, label: false, placeholder: 'Name', input_html: { size: 100 }

Resources