Rendering form in slim unexpectedly submits data - ruby-on-rails

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

Related

RAILS : Read_only field using rendered form

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
....

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.

Rails Cocoon read only fields

I am using Cocoon for nested forms. For task records that are already created, I want description to be read_only.
projects/_form::
= simple_form_for #project do |f|
= f.input :name
= f.input :description
%h3 Tasks
#tasks
= f.simple_fields_for :tasks do |task|
= render 'task_fields', f: task
.links
= link_to_add_association 'add task', f, :tasks
= f.submit
And _task_fields :
.nested-fields
- if #task.description?
= f.text_field :description, disabled: true
- else
= f.input :description
= f.input :done, as: :boolean
= link_to_remove_association "remove task", f
Currently the validation in _task_fields is not working: undefined method <description> for nil:NilClass in the line with if statement. How can I write the IF statement correctly?
For task records that are already created, I want description to be
read_only.
You are doing it wrong. You should be able do the check by using new_record? like so
.nested-fields
- unless f.object.new_record?
= f.text_field :description, disabled: true
- else
= f.input :description
= f.input :done, as: :boolean
= link_to_remove_association "remove task", f
Also, by using disabled: true, the value of description won't be submitted and cannot be passed through params. If you want to have the description value in the params, use readonly: true instead.
.nested-fields
- unless f.object.new_record?
= f.text_field :description, readonly: true
- else
= f.input :description
= f.input :done, as: :boolean
= link_to_remove_association "remove task", f

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