RAILS : Read_only field using rendered form - ruby-on-rails

I have a form view with an email text field and some other type of field in a view named _form.html.haml, as follows :
....
= easy_form_for #form, label_col: 'col-md-2', control_col: 'col-md-10' do |f|
= f.text_field :name, required: true
= f.text_field :email, required: true
= f.text_area :description, rows: 5
....
And an edit.html.haml view that inherits from this form as follows:
...
%h2.page-header= page_title
= render 'form'
...
I would like to make a Patch on this form in the edit.html.haml view just gray the email field and leave the other fields of the form as they are

You could send a parameter to the form partial and handle the readonly part there.
= render partial: 'form', locals: { disable_email: true }
If the form partial does not receive any disable_email it will default to false.
....
- disable_email = local_assigns.has_key?(:disable_email) ? disable_email : false
= easy_form_for #form, label_col: 'col-md-2', control_col: 'col-md-10' do |f|
= f.text_field :name, required: true
= f.text_field :email, required: true, readonly: disable_email
= f.text_area :description, rows: 5
....

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.

Create action not being called in form

I've just started a new app where I want to take a postcode in a form and save it to the database. My problem is that the create action doesn't seem to be being called no matter what I try.
Routes:
root 'postcodes#new'
resources :postcodes, only: [:new ,:create]
Controller: postcodes_controller.rb
class PostcodesController < ApplicationController
def new
#postcode = Postcode.new
end
def create
#postcode = Postcode.new(postcode_params)
if #postcode.save
flash[:success] = 'Success'
else
flash[:error] = 'Error'
end
end
private
def postcode_params
params.require(:postcode).permit(:code)
end
end
Model: postcode.rb
class Postcode < ApplicationRecord
validates :code, presence: true, uniqueness: true
end
View: postcodes/new.haml
.container
%form
%fieldset.form-group
= form_for #postcode do |f|
= f.label :postcode
= f.text_field :code, placeholder: 'Example Postcode', class: 'form-control'
= f.submit 'Submit', class: 'btn btn-primary'
I've attempted to pass more options in the form_for such as the method and action and now I have a feeling it's a routing error.
Any help will be appreciated.
Thanks.
I believe the problem you are experiencing is a result of your HAML.
You do not need to use, nor should you use, a form HTML element outside the form_for method call.
The form_for method will handle generating this HTML element/tag for you.
You have:
.container
%form
%fieldset.form-group
= form_for #postcode do |f|
= f.label :postcode
= f.text_field :code, placeholder: 'Example Postcode', class: 'form-control'
= f.submit 'Submit', class: 'btn ban-primary'
Which outputs an empty <form> element.
You should have:
.container
= form_for #postcode do |f|
%fieldset.form-group
= f.label :postcode
= f.text_field :code, placeholder: 'Example Postcode', class: 'form-control'
= f.submit 'Submit', class: 'btn ban-primary'
That should generate a proper <form> tag with the required action and method attributes populated with the right URL and 'post' so that your create action is called.

Rendering form in slim unexpectedly submits data

I'm trying to render multiple forms in users/new.html.slim. I'm having trouble with my "next" button in the form1, which automatically submits the form to db when I click it. But, it supposed to just render next form.
= simple_form_for #user, html: { class: "profile_form"} do |f|
= f.fields_for :profile, #user.profile || Profile.new do |p|
= render 'users/form1', f: f, p: p
= f.submit
and this is form1
.form-1
.form-1-detail
= f.input :name
= f.input :email
= f.input :password, required: true
= f.input :password_confirmation, required: true
button.next next
Does anyone know why it's happening? I'm suspecting the indentation is causing it to act weirdly.
Your problem is with the default type of a button, which is "submit", so any button inside a form will trigger a form submission, unless you specifically change the button type.
You can do so by explicitly adding type="button":
.form-1
.form-1-detail
= f.input :name
= f.input :email
= f.input :password, required: true
= f.input :password_confirmation, required: true
button.next type="button" next

Rails simple_form error: false

in my app I have form that looks like this
= simple_form_for #user do |f|
= f.input :name, error: false
= f.input :surname, error: false
Is there any way to avoid this repetitions (error: false)?
If they're all of the same type, something like this should work:
= simple_form_for #user do |f|
- [ :name , :surname ].each do |field|
= f.input field, error: false
If not, you could use a hash or something, instead of an array, and specify the type, as well.
It appears that simple form has the following option:
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 %>
From https://github.com/plataformatec/simple_form
So, in your case:
= simple_form_for #user , defaults: { error: false } do |f|
= f.input :name
= f.input :surname
You could loop through an array of symbols
simple_form_for #user do |f|
[:name, :surname].each do |element|
f.input element, error: false
end
end

Rails 4 yield additional form fields

I'm trying to DRY up one of my forms that sometimes has additional fields (for nested models) when making a new entry, but wouldn't need those fields when performing an update. As such, I was trying to pass the additional fields in via a block, but the form object isn't being passed properly.
Is there a way to pass a form object (or really any variable) into a yield?
Example code for reference:
_form.slim
= nested_form_for #model do |f|
.row
= f.label :name
= f.text_field :name, autofocus: true
...
= yield
...
= f.submit 'Save'
new.html.slim
== render layout: 'model/form' do
h3 Additional Fields
= f.fields_for :nested do |h|
= a.label :name, 'Nested Name'
= a.text_field :name
= a.link_to_remove do
= fa_icon 'times-circle-o'
= f.link_to_add "Add another nested model", :nested
edit.html.slim
== render layout: 'model/form'
To elaborate on my comment, this is how I'd do it using partials:
_form.slim
= nested_form_for #model do |f|
.row
= f.label :name
= f.text_field :name, autofocus: true
...
- if defined?(additional_fields)
h3 Additional Fields
= f.fields_for :nested do |h|
= a.label :name, 'Nested Name'
= a.text_field :name
= a.link_to_remove do
= fa_icon 'times-circle-o'
= f.link_to_add "Add another nested model", :nested
...
= f.submit 'Save'
new.html.slim
== render 'model/form', :additional_fields => true
edit.html.slim
== render 'model/form'
I might be missing something, but I'm not sure why this wouldn't work.

Resources