I got a problem with nested fields_for in rails, I have a list of products and each product can have multiple images, so I use Angular.js to complete this task, I followed this tutorial https://tatey.com/2013/01/13/adding-and-removing-children-with-rails-nested-forms-and-angularjs/ , but the names of the inputs doesn't have the right name because the index doesn't increment at the first param only on the second, like this:
First product has two images so this are the names assigned to each input
catalog[products_attributes][0][images_products_attributes][0][url_image]
catalog[products_attributes][0][images_products_attributes][1][url_image]
The second product has one image and this are the names of the attributes
catalog[products_attributes][0][images_products_attributes][0][url_image]
As you can see the second product has the index 0 on the products_attributes but it should be 1
This is my code
<div ng-repeat="product in products">
<div class="product">
<%= f.fields_for :products, Product.new do |product|%>
<div class="field">
Producto {{$index}}
<%= product.text_field :name, placeholder: "Nombre"%>
</div>
<div class="field">
<%= product.text_field :description, placeholder: "Descripción" %>
</div>
<div class="field">
<%= product.number_field :price, placeholder: "Precio" %>
</div>
<div class="field">
<%= product.check_box :available %>
</div>
<input type="button" name="name" value="+" ng-click="addImageToProduct($index)">
<div class="images">
<div class="image" ng-repeat="image in product.images">
<%= product.fields_for :images_products, ImagesProduct.new, child_index: "{{$index}}" do |image|%>
<div class="field">
{{$index}}<%= image.file_field :url_image%>
</div>
<%end%>
<input type="button" name="name" value="-" ng-click="removeImageToProduct($parent.$index, $index)">
</div>
</div>
<%end%>
</div>
<input class="step-button remove" type="button" name="name" value="Quitar" ng-click="removeProduct($index)">
</div>
Remove the child_index from your forms
child_index: "{{$index}}"
And puts the code already generated in the view with:
catalog[products_attributes][{{$parent.$index}}][images_products_attributes][$index][url_image]
Related
I've created a form so the user can add a new picture to the website catalog, but for some reasons it doesn't work. Once the form is filled out, I click on the 'Submit' button but nothing happens, I just stay on the same page (and I don't have any error message...).
I don't think the error comes from my Controller since nothing happens when I add the raise keyword in my Controller's 'create' method.
I'm sure this is an amateur mistake... but I can't see what it is. Thanks for your help!
picture.rb /
Picture model:
class Picture < ApplicationRecord
validates :name, presence: true
has_many_attached :photo
end
new.html.erb /
Here is my form :
<%= form_for(#picture) do |f| %>
<div class="form-group">
<%= f.label :name, "Please indicate the name" %>
<%= f.text_field :name, class:"form-control", placeholder:"(mandatory field)" %>
</div>
<div class="form-group">
<%= f.label :description, "Add a description" %>
<%= f.text_area :description, class:"form-control" %>
</div>
<div class="form-group">
<div class="row">
<div class="col">
<%= f.label :category, "Add a category" %>
<%= f.text_field :category, class:"form-control" %>
</div>
<div class="col">
<%= f.label :price, "Indicate the price (when applicable)" %>
<%= f.number_field :price, class:"form-control", placeholder:"0,00$ CAD" %>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col">
<p>Where do you want to add this item?</p>
<div>
<%= f.check_box :is_home_item %>
<%= f.label :is_home_item, "Homepage" %>
</div>
<div>
<%= f.check_box :is_portfolio_item %>
<%= f.label :is_portfolio_item, "Work" %>
</div>
<div>
<%= f.check_box :is_sketchbook_item %>
<%= f.label :is_sketchbook_item, "Sketchbook" %>
</div>
<div>
<%= f.check_box :is_shopping_item %>
<%= f.label :is_shopping_item, "Shopping" %>
</div>
</div>
<div class="col">
<div class="form-group">
<%= f.label :photo, "Select your picture" %>
<%= f.file_field :photo, class:"form-control-file" %>
</div>
</div>
</div>
</div>
<div class="form-group">
<%= f.submit class:"btn btn-lg btn-primary" %>
</div>
<% end %>
pictures_controller.rb /
class PicturesController < ApplicationController
def new
#picture = Picture.new
end
def create
#picture = Picture.new(picture_params)
if #picture.save
redirect_to root_path(#picture), notice: "Picture was successfully created"
else
render :new
end
end
private
def picture_params
params.require(:picture).permit(:name, :description, :category, :price, :is_home_item, :is_portfolio_item, :is_sketchbook_item, :is_shopping_item, :photo)
end
end
And here is the text I got on my local server console
Here is the HTML output of my form :
<form>
<input type="hidden" name="authenticity_token" value="7MxWbzbltjXcAx2dvgRwIu07WMpyjPQji6LI6ELifMZODLJyMBucNApnPRk8vsjshSEjyMMenDUfvDw6pN+/4Q==">
<div class="form-group">
<label for="picture_name">Indicate the name</label>
<input class="form-control" placeholder="(mandatory field)" type="text" name="picture[name]" id="picture_name">
</div>
<div class="form-group">
<label for="picture_description">Add a description</label>
<textarea class="form-control" name="picture[description]" id="picture_description"></textarea>
</div>
<div class="form-group">
<div class="row">
<div class="col">
<label for="picture_category">Add a category</label>
<input class="form-control" type="text" name="picture[category]" id="picture_category">
</div>
<div class="col">
<label for="picture_price">Indicate the price (when applicable)</label>
<input class="form-control" placeholder="0,00$ CAD" type="number" name="picture[price]" id="picture_price">
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col">
<p>Where do you want to add your picture?</p>
<div>
<input name="picture[is_home_item]" type="hidden" value="0"><input type="checkbox" value="1" name="picture[is_home_item]" id="picture_is_home_item">
<label for="picture_is_home_item">Homepage</label>
</div>
<div>
<input name="picture[is_portfolio_item]" type="hidden" value="0"><input type="checkbox" value="1" name="picture[is_portfolio_item]" id="picture_is_portfolio_item">
<label for="picture_is_portfolio_item">Work</label>
</div>
<div>
<input name="picture[is_sketchbook_item]" type="hidden" value="0"><input type="checkbox" value="1" name="picture[is_sketchbook_item]" id="picture_is_sketchbook_item">
<label for="picture_is_sketchbook_item">Sketchbook</label>
</div>
<div>
<input name="picture[is_shopping_item]" type="hidden" value="0"><input type="checkbox" value="1" name="picture[is_shopping_item]" id="picture_is_shopping_item">
<label for="picture_is_shopping_item">Shopping</label>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="picture_photo">Select your picture</label>
<input class="form-control-file" type="file" name="picture[photo]" id="picture_photo">
</div>
</div>
</div>
</div>
<div class="form-group">
<input type="submit" name="commit" value="Create Picture" class="btn btn-lg btn-primary" data-disable-with="Create Picture">
</div>
My routes :
Rails.application.routes.draw do
devise_for :users
# Pages routes
root to: 'pages#home'
get 'about', to: 'pages#about'
get 'portfolio', to: 'pages#portfolio'
get 'sketchbook', to: 'pages#sketchbook'
get 'shopping', to: 'pages#shopping'
# Pictures routes
resources :pictures
end
And these are my routes in the Terminal
Not quite sure why this is happening, but form_for is deprecated, so you should replace it with form_with.
You can use a model, such as your #picture with form_with as described in the docs.
<%= form_with(model: #picture) do |form| %>
# fields
<% end %>
This should create a form DOM object that looks like this:
<form action="/pictures" method="post" accept-charset="UTF-8" >
<input name="authenticity_token" type="hidden" value="..." />
...
</form>
If for some reason it doesn't, you can always pass a method: :post in the form_with (ie. <%= form_with(model: #picture, method: :post) do |form| %>).
Currently, you have got has_many_attached with a singular photo. That does not seem to be the right syntax. Have you tried changing to has_many_attached :photos and modifying the picture_params to have photos passed as an array photos: []?
Or if you wanted to attach one photo, then you should try changing to has_one_attached :photo in the Picture model.
Here's the relevant code. This all works on my development server with a direct code copy to the production server. Development works fine. I don't do much with html or css so it could be there. Anyone see something obvious? I've checked suggestions from other similar questions in the forums but I'm not seeing it.
Code from exams controller:
def new
#exam = Exam.new
#exam.questions.build if #exam.questions.blank?
end
# GET /exams/1/edit
def edit
end
# POST /exams
# POST /exams.json
def create
#exam = Exam.new(exam_params)
respond_to do |format|
if #exam.save
format.html { redirect_to #exam, notice: 'Exam was successfully created.' }
format.json { render :show, status: :created, location: #exam }
else
format.html { render :new }
format.json { render json: #exam.errors, status: :unprocessable_entity }
end
end
end
_form
<%= form_for(#exam) do |f| %>
<% if #exam.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(exam.errors.count, "error") %> prohibited this exam from being saved:</h2>
<ul>
<% #exam.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %>:
<%= f.text_field :title,:size =>"50" %>
</div>
<div class="field">
<%= f.check_box :pcredit %>
<%= f.label :pcredit, "Give partial credit when a question has multiple correct answers." %>
</div>
<div class="field">
<%= f.check_box :available %>
<%= f.label :available, "Available to take" %>
</div>
<% exam.user_id = current_user.id %>
<div class="field">
<%= f.hidden_field :user_id, value: current_user.id %>
</div>
<div class="field">
<%= f.hidden_field :department_id, value: current_user.department_id %>
</div>
<div class="field">
<%= f.hidden_field :creator_id, value: current_user.id %>
</div>
<div class="field">
<%= f.check_box :retake %>
<%= f.label :retake, "Retakes allowed" %>
</div>
<div class="field">
<%= f.check_box :results %>
<%= f.label :results, "Show results" %>
</div>
<hr>
<div id="questions">
<%= f.fields_for :questions do |question| %>
<%= render 'question_fields', f: question %>
<hr>
<% end %>
<%= link_to_add_association 'add_question', f, :questions, partial: 'question_fields' %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Questions Partial
<strong>Question:</strong>
<div class='nested-fields'>
<div class="field">
<%= f.label :name, "Question:" %>
<%= f.text_area :name,:size =>"50" %>
</div>
<div class="field">
<%= f.label :value, "Point Value:" %>
<%= f.number_field :value %>
</div>
<div class="field">
<%= f.label :available %>
<%= f.check_box :available %>
</div>
<%= link_to_remove_association "remove question", f %>
<div>
<p><strong>Answers:</strong></p>
<div id="answers">
<%= f.fields_for :answers do |answer| %>
<%= render 'answer_fields', f: answer %>
<% end %>
</div>
<%= link_to_add_association 'add_answer', f, :answers, partial: 'answer_fields' %>
<hr>
</div>
</div>
Answers Partial
<div class="field">
<%= f.label :name, "Answer:" %>
<%= f.text_area :name,:size =>"50" %>
</div>
<div class="field">
<%= f.label :correct %>
<%= f.check_box :correct %>
</div>
<div class="field">
<%= f.hidden_field :creator_id, value: current_user.id %>
</div>
<div class="field">
<%= f.hidden_field :department_id, value: current_user.department_id %>
</div>
<div class="field">
<%= f.label :locked %>
<%= f.check_box :locked %><br>
<%= link_to_remove_association "remove answer", f %>
</div>
Page Source:
<!DOCTYPE html>
<html>
<head>
<title>Online Placements</title>
<link rel="stylesheet" media="all" href="/assets/exams-72737ac2bb269793edd945e3daa76d03d1bc74588f32b4acceb48ba3328ddc14.css" />
<script src="/assets/application-3199215ebdb5afca46347c9bb159d59b78620065cea4336725d6fdeebc9e0e12.js"></script>
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="+r+/jvc85b8QgSkJrpoT/idGMB3vYnkfLePBCjnWdsGBP1xhb/L86UA80toVa+/SXxGzb1KhDR0mm8hLkGt+Fw==" />
</head>
<body id="exams">
<div id="banner">
<img src=/assets/KHSlogo-3f9139495681edc2572d84a2d1157e33990d56e4536f98c1addaf5e9c092b2fc.gif width="160" height="77" alt="*****" />
<title1>**************</title1>
<p id="notice"></p>
</div>
<div id="columns">
<div id="side">
<font color="#ff0000">Home</font><br>
Placements
<br>
<hr>
<font color="#ff0000">Admins Only</font><br>
Users
<br>
<hr>
<font color="#ff0000">Documentation</font>
<br><a target="_blank" href="https://docs.google.com/document/d/11_WLL7wZIkzssubus4XAQcouKkpRdrG6Lu-dWGn7gJY/edit#bookmark=id.8glqcm3gxwmz">User Document</a>
<br><a target="_blank" href="https://docs.google.com/document/d/11_WLL7wZIkzssubus4XAQcouKkpRdrG6Lu-dWGn7gJY/edit#bookmark=id.o7htlx2i1tyx">Placement Help</a>
</div>
<div id="main">
<li>
Logged in as <b>****- </b>
<a rel="nofollow" data-method="delete" href="/users/sign_out">Logout</a>
</li>
<h1>Editing Exam: Placement Test</h1>
<form class="edit_exam" id="edit_exam_1" action="/exams/1" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="_method" value="patch" /><input type="hidden" name="authenticity_token" value="K98vKBkYaUZL5WOt5xjlopkOVk7pvhc3HgBp5M0zmsQu3Hy2oBN5AzZjI3gTYcghP9qhXrpqAQenrZnYcVNw5Q==" />
<div class="field">
<label for="exam_title">Title</label>:
<input size="50" type="text" value="Placement Test" name="exam[title]" id="exam_title" />
</div>
<div class="field">
<input name="exam[pcredit]" type="hidden" value="0" /><input type="checkbox" value="1" checked="checked" name="exam[pcredit]" id="exam_pcredit" />
<label for="exam_pcredit">Give partial credit when a question has multiple correct answers.</label>
</div>
<div class="field">
<input name="exam[available]" type="hidden" value="0" /><input type="checkbox" value="1" checked="checked" name="exam[available]" id="exam_available" />
<label for="exam_available">Available to take</label>
</div>
<div class="field">
<input value="1" type="hidden" name="exam[user_id]" id="exam_user_id" />
</div>
<div class="field">
<input value="1" type="hidden" name="exam[department_id]" id="exam_department_id" />
</div>
<div class="field">
<input value="1" type="hidden" name="exam[creator_id]" id="exam_creator_id" />
</div>
<div class="field">
<input name="exam[retake]" type="hidden" value="0" /><input type="checkbox" value="1" checked="checked" name="exam[retake]" id="exam_retake" />
<label for="exam_retake">Retakes allowed</label>
</div>
<div class="field">
<input name="exam[results]" type="hidden" value="0" /><input type="checkbox" value="1" checked="checked" name="exam[results]" id="exam_results" />
<label for="exam_results">Show results</label>
</div>
<hr>
<div id="questions">
<a class="add_fields" data-association="question" data-associations="questions" data-association-insertion-template="<strong>Question:</strong>
<div class='nested-fields'>
<div class="field">
<label for="exam_questions_attributes_new_questions_name">Question:</label>
<textarea name="exam[questions_attributes][new_questions][name]" id="exam_questions_attributes_new_questions_name" cols="50">
</textarea>
</div>
<div class="field">
<label for="exam_questions_attributes_new_questions_value">Point Value:</label>
<input type="number" name="exam[questions_attributes][new_questions][value]" id="exam_questions_attributes_new_questions_value" />
</div>
<div class="field">
<label for="exam_questions_attributes_new_questions_available">Available</label>
<input name="exam[questions_attributes][new_questions][available]" type="hidden" value="0" /><input type="checkbox" value="1" name="exam[questions_attributes][new_questions][available]" id="exam_questions_attributes_new_questions_available" />
</div>
<input type="hidden" name="exam[questions_attributes][new_questions][_destroy]" id="exam_questions_attributes_new_questions__destroy" value="false" /><a class="remove_fields dynamic" href="#">remove question</a>
<div>
<p><strong>Answers:</strong></p>
<div id="answers">
</div>
<a class="add_fields" data-association="answer" data-associations="answers" data-association-insertion-template=" <div class="field">
<label for="exam_questions_attributes_new_questions_answers_attributes_new_answers_name">Answer:</label>
<textarea name="exam[questions_attributes][new_questions][answers_attributes][new_answers][name]" id="exam_questions_attributes_new_questions_answers_attributes_new_answers_name" cols="50">
</textarea>
</div>
<div class="field">
<label for="exam_questions_attributes_new_questions_answers_attributes_new_answers_correct">Correct</label>
<input name="exam[questions_attributes][new_questions][answers_attributes][new_answers][correct]" type="hidden" value="0" /><input type="checkbox" value="1" name="exam[questions_attributes][new_questions][answers_attributes][new_answers][correct]" id="exam_questions_attributes_new_questions_answers_attributes_new_answers_correct" />
</div>
<div class="field">
<input value="1" type="hidden" name="exam[questions_attributes][new_questions][answers_attributes][new_answers][creator_id]" id="exam_questions_attributes_new_questions_answers_attributes_new_answers_creator_id" />
</div>
<div class="field">
<input value="1" type="hidden" name="exam[questions_attributes][new_questions][answers_attributes][new_answers][department_id]" id="exam_questions_attributes_new_questions_answers_attributes_new_answers_department_id" />
</div>
<div class="field">
<label for="exam_questions_attributes_new_questions_answers_attributes_new_answers_locked">Locked</label>
<input name="exam[questions_attributes][new_questions][answers_attributes][new_answers][locked]" type="hidden" value="0" /><input type="checkbox" value="1" name="exam[questions_attributes][new_questions][answers_attributes][new_answers][locked]" id="exam_questions_attributes_new_questions_answers_attributes_new_answers_locked" /><br>
<input type="hidden" name="exam[questions_attributes][new_questions][answers_attributes][new_answers][_destroy]" id="exam_questions_attributes_new_questions_answers_attributes_new_answers__destroy" value="false" /><a class="remove_fields dynamic" href="#">remove answer</a>
</div>
" href="#">add_answer</a>
<hr>
</div>
</div>
" href="#">add_question</a>
</div>
<div class="actions">
<input type="submit" name="commit" value="Update Exam" data-disable-with="Update Exam" />
</div>
</form>
Show |
Back
<br><br><br>
</div>
</div>
</body>
</html>
It would be great to see controller part for it where #exam is defined
I assume that in your prod case (where form doesn't show) association questions is empty.
So there are several variants:
1.In controller always build a question if the association is empty
#exam.questions.build if #exam.questions.blank?
2.You can add entity in the view
f.fields_for :questions, #exam.questions.presence || [#exam.questions.build] do |question|
3.Take into account such case in view and show proper message
<% if #exam.questions.present? %>
<%= render 'questions_part' %>
<% else %>
<%= render 'no_questions_partial' %>
<% end %>
I think 1 variant is better.
OK I finally figured it out. I had to precompile assets. Working now.
Thanks to those who offered suggestions. I really appreciate your time.
I've got a nice bootstrap navigation menu with a search box in it.
I've got it in a partial file...
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
I like the layout of this search box. Unfortunately, I can't figure out how to get my rails search box to look the same...
<%= search_form_for #search do |f| %>
<div class="field">
<%= f.label :title_or_template_cont, "Search" %>
<%= f.text_field :title_or_template_cont %>
</div>
<div class="actions">
<%= f.submit "Search" %>
What changes do I need to make in my rails form to look like the bootstrap search box?
I tried a few classes within the rails search box, but wasn't close to the way it looked.
Any suggestions?
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
Checkout the gem "Simpleform" so you can style forms with css easily in rails using their helpers. Then:
<%= simple_form_for #search, html: {class: "navbar-form navbar-left"} do |f| %>
<div class="form-group">
<%= f.input_tag :title_or_template_cont, label: false, input_html: {class: 'form-control'}, placeholder: 'search' %>
</div>
<div class="actions">
<%= f.submit "Search", class: "btn btn-default" %>
My page contains 3 buttons New, Login, SignUp, and when I click New, I am getting form with two tabs, for New, Login and SignUp Buttons. But, I want, Login tab alone with page when I click the Login Button. And, SignUp tab alone with page, when I click on SignUp button.
Hope, some wil sureply help me... I am completely new to this .....
Here is my code...
Thanks in advance
Here is my code...
New Page code:
Login
SignUp
Login
SignUp
<%= f.label :content %><br />
<%= f.text_field :content %>
<%= f.label :user_id %><br />
<%= f.number_field :user_id %>
<%= f.submit %>
-->
<div class="modal-footer">
<button type="submit" class="btn btn-primary" >Save changes</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
</div>
Index code:
New Micropost
Login
SignUp
As far I got you, I think you need to do as below:
# index.html
<%= form_for(MicroPost.new) do |f| %>
<ul class="nav nav-tabs">
<li>Login</li>
<li>SignUp</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="new">Login</div>
<div class="tab-pane " id="new1">SignUp</div>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<div class="field">
<%= f.label :user_id %><br />
<%= f.number_field :user_id %>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" >Save changes</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
</div>
</div>
<% end %>
This is working for me.
Hope this would help.
Right now when I create a form using a form_for Ruby on Rails creates an extra <br> tag after the form. Is there an option to not have RoR create this for me? Here is the code for creating the form:
<%= form_for(:user, :url => create_user_path) do |f| %>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %>
<%= f.password_field :password %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
Output:
<form method="post" action="http://localhost:3000/users" accept-charset="UTF-8"><div style="margin:0;padding:0;display:inline"><input type="hidden" value="✓" name="utf8"><input type="hidden" value="fsdfsdf+rgJKoc5sdQvsqvT2s=" name="authenticity_token"></div>
<div class="field">
<input type="text" size="30" name="user[password_clear]" id="user_password_clear" class="text_box">
</div>
<div class="field">
<input type="text" size="30" name="user[password]" id="user_password" class="text_box">
</div>
<div class="actions">
<input type="submit" value="Sign Up" name="commit" class="button button_medium button_green">
</div>
</form>
<br>
Thank you!
As long as you don't plan on creating a new form you could refrain from closing the form until you want a to appear, just don't add the <% end %> tag until you want a br and keep the following code inside the current form.
It's not very ellegant but it will probably work the way you want it to.