Extend forms without page reload, rails - ruby-on-rails

I'm searching for a solution to extend my form without page reload.
First I tried to render a partial with coffee or javascript, but escape_javascript didnt work.
Here's the view
<%= form_for #recipe = current_user.recipes.build do |f| %>
<%= f.label :name, "Recipe Name" %>
<%= f.text_field :name %>
<%= button_to "Add Ingredient", '#', class: "btn btn-lg btn-primary", id: "add" %>
<p></p>
<%= f.submit class: "btn" %>
<% end %>
The form above should be extented with following partial by every click on the button
<div id="recipe-ingredients">Quantity
<%= f.fields_for :quantities, #recipe.quantities.build do |quantity| %>
<%= render 'quantity_fields', f: quantity %>
<% end %>
</div>
_quantity_fields
<%= f.label :amount, "Amount:" %>
<%= f.text_field :amount %>
<%= f.collection_select(:ingredient_id, Ingredient.all, :id, :name) %>
This approach did not work (recipes.js.erb)
$(document).ready(function() {
$("#add").click(function() {
$("p").append("<%= escape_javascript
render(:partial => 'quantities') %>");
});
});
There's a workaround (see below) but I'm searching for a better solution.
$(document).ready(function() {
$("#workout-week").append(<%= escape_javascript(
Haml::Engine.new(File.read(File.join(Rails.root,'app/views',
'_show_period.html.haml'))).render(Object.new, period: #period)) %>);
});
A second approach is to write following lines in Coffee or JavaScript:
<%= f.fields_for :quantities, #recipe.quantities.build do |quantity| %>
<%= f.label :amount, "Amount:" %>
<%= f.text_field :amount %>
<%= f.collection_select(:ingredient_id, Ingredient.all, :id, :name) %>
<% end %>

I'm a newbie so take this with a grain of salt, but have you tried using render :foo instead of redirect_to :foo in the appropriate controller function?

I solved it with cocoon
<%= form_for #recipe do |f| %>
<div class="field">
<%= f.label :name %>
<br/>
<%= f.text_field :name %>
<%= f.fields_for :quantities do |quantity| %>
<%= render 'quantity_fields', :f => quantity %>
<% end %>
<div class="links">
<%= link_to_add_association 'add', f, :quantities %>
</div>
</div>
<%= f.submit %>
<% end %>

Related

How to insert new line breaks using form_for with collection_check_boxes

I use the following form_for at one point in my code to display a series of topics for users to select from.
<%= form_for #user do |f| %>
<%= f.collection_check_boxes(:topic_ids, Topic.all.sample(50).each, :id, :topic_name) %>
<%= f.submit %>
<% end %>
When it renders on the page, the boxes are all one-after-the-other. How can I separate them so that there is one check box per line?
from reference here
It is possibly to customize the way the elements will be shown by giving a block to the method as sample below from your code above
<%= form_for #user do |f| %>
<%= f.collection_check_boxes :topic_ids, Topic.all.sample(50).each, :id, :topic_name do |b| %>
<%= b.label(class: "check_box") do %>
<%= b.check_box(class: "check_box") %>
<%= b.object.topic_name %></br>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
You may of course render HTML inside the block:
<%= form_for #user do |f| %>
<%= f.collection_check_boxes :topic_ids, Topic.all.sample(50).each, :id, : topic_name do |b| %>
<div class="my-checkbox-wrapper">
<%= b.label(class: "foo") do %>
<%= b.object.topic_name %>
<%= b.check_box(class: "bar") ></br>
<%end%>
<%= f.submit %>
<%end%>
You can have a look at this example
It is very broad question. In short, using CSS.
For example using Bootstrap 4:
<%= form_for #user do |f| %>
<div class="form-check">
<%= f.collection_check_boxes :topic_ids, Topic.all.sample(50).each, :id, :topic_name, class: 'form-check-input' %>
</div>
<%= f.submit %>
<% end %>

Gem dragonfly. How to make the list of current files on edit view?

I have model Project and in model have field documents(files). I am using gem dragonfly. When editing a project, how to make the list of current files? At this time on the edit page the list of files fields show: "The file is not selected". I do next: ​
projects_controller:
def edit
end
def update
if #project.update(project_params)
redirect_to #project
else
render :edit
end
end
private
def set_project
#project = Project.find(params[:id])
end
def set_payment_types
#payment_types = PaymentOption.all
end
def project_params
params.require(:project).permit(:title, :description, :price, :location,
:anonymity, :price_category, :category_id, :skill_list, documents_attributes: [:attachment], payment_option_ids: [])
end
edit.html.erb:
<%= form_for #project do |f| %>
<p>
<%= f.label 'Name' %>
<%= f.text_field :title %>
</p>
<P>
<%= f.label 'Budget' %>
<%= f.text_field :price %>
für
<%= f.select :price_category, Project::PRICE_CATEGORIES %>
</P>
<p>
<%= f.label 'Description' %>
<%= f.text_area :description %>
</p>
<p>
<%= f.label 'Category' %>
<%= f.collection_select :category_id, Category.all, :id, :name %>
</p>
<p>
<%= f.label 'Skills Freelancer (15 pieces) *' %>
<%= f.text_field :skill_list %>
</p>
<p>
<%= f.label 'Location' %>
<%= f.text_field :location %>
</p>
<ul>
<% #payment_types.each do |type| %>
<li><%= check_box_tag 'project[payment_option_ids][]', type.id %>
<%= type.name %>
</li>
<% end %>
</ul>
<p>
<b>Anonymity order</b>
</p>
Setup allows for players to remain anonymous. Note that this may reduce the number of responses.
<p>
<%= f.label 'Place Order anonymously' %>
<%= f.check_box :anonymity %>
</p>
<p>
<%= f.fields_for :documents do |d| %>
<%= render 'document_fields', f: d %>
<% end %>
<div class="links">
<%= link_to_add_association 'add file', f, :documents %>
</div>
</p>
<P>
<%= f.submit 'Edit' %>
</P>
<% end %>
​_document_fields.html.erb:
<div class="nested-fields">
<%= f.label :attachment %>
<%= f.file_field :attachment %>
<%= link_to_remove_association "remove file", f %>
</div>
document.rb
class Document < ApplicationRecord
belongs_to :project
dragonfly_accessor :attachment
end
On the edit page the list of files fields show: "The file is not selected", but must be specified ​current files.
file_field is for uploading new files only, not for displaying what is already in the database. For displaying a list of uploaded files, you should just display the name of the file and/or an image tag with the thumbnail and provide a destroy link.
You can also provide a link to create a new attachment.
edit.html.erb
<div>
<ul>
<%= #project.documents.each do |document| %>
<li>
<%= document.attachment.name %>
<%= link_to "Delete", document_path(document), method: :delete, data: { confirm: 'Are you sure you want to delete this?' } %>
</li>
<% end %>
</ul>
<div class="links">
<%= link_to_add_association 'add file', f, :documents %>
</div>
</div>

Render partial after change select

I have the following view
<%= form_for #survey do |f| %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %> <br><br>
<%= f.label :description %><br>
<%= f.text_field :description %><br><br>
</div>
<%= f.fields_for :survey_sections do |builder| %>
<%= builder.text_field :title, :placeholder => "Abschnittsbeschreibung" %><br>
<%= builder.fields_for :questions do |quest| %>
<%= quest.text_field :text, :placeholder => "Frage" %> <br>
<%= quest.fields_for :answers do |ans| %>
<%= ans.text_field :text, :placeholder => "Antwort" %> <br>
<%end%>
<%end%>
<%= select_tag("question_type",options_for_select([["Radio", "radio"],["Checkbox", "check"]])) %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I want to render a partial in this view after selecting one of the options.
How can i do this?
Easiest way is render the partial with display:none
<div id='foo' style='display:none'>
<%= render :foobar %>
</div>
And when a user select something, show it by JS(jQuery).
$('[name=question_type]').change(function() {
$('#foo').show();
});
If you are using jQuery, then try this:
VIEW
<%= select_tag("qustion_type",options_for_select([["Radio", "radio", {:onclick => "someFunction(#{controller_path})"}],["Checkbox", "check", {:onclick => "someFunction(#{controller_path})"}]])) %>
JAVASCRIPT
function someFunction(url) {
jQuery.ajax({
url: url,
data: {some_data: "data_value"},
success: function(data) {
//data has the html code that you render in controller
}
});
}
EDIT (See Comments)
As you asked that you need to render a partial on each option select. So, for each option select you need to hit a controller method. In my example url is that controller end point(eg:- render_radio_some_controller_path).
def render_radio
render :partial => "radio"
end
After this, it will go to the success block of Ajax call and data will have the html defined in radio.html.erb. Now, you just have to use jQuery to update the desired div html with data(Eg:- jQuery("#some_div").html(data);)

Rails 4 - Rendering partial with access to class

I have two classes Bid (has_many :mozs) and Moz (belongs_to :bid). I am trying to render a partial for creating Moz objects.
<%= f.fields_for :mozs do |builder| %>
<%= render "moz_fields", :f => builder %>
<% end %>
in my partial:
<div class="field fields">
<%= f.label :url, "Comparative URL" %><br>
<%= f.text_field :url %>
<%= f.hidden_field :destroy %>
<%= link_to_function "remove", "remove_fields(this)"%>
</div>
When the contents of the partial are in the fields_for tag:
<%= f.fields_for :mozs do |builder| %>
<div class="field fields">
<%= builder.label :url, "Comparative URL" %><br>
<%= builder.text_field :url %>
<%= builder.hidden_field :destroy %>
<%= link_to_function "remove", "remove_fields(this)"%>
</div>
<% end %>
then everything works fine. But I need it in a partial to dynamically add the fields. When I keep it in a partial I get this error: undefined method `url' for NilClass:Class.
I don't understand why the class would be nil just because I put it in a partial.
I think the problem will likely be with your rendering of a partial inside the fields_for tag && you're not using the locals argument:
<%= render partial: "moz_fields", locals: { f: builder } %>
#moz_fields
<%= f.fields_for :mozs do |b| %>
<div class="field fields">
<%= b.label :url, "Comparative URL" %><br>
<%= b.text_field :url %>
<%= b.hidden_field :destroy %>
<%= link_to_function "remove", "remove_fields(this)"%>
</div>
<% end %>

Increment a title in a rails form

I am trying to make the title increment by number in the form below as the user adds a level (a new form). For example when the user clicks add level it should say "Level 2" and if they add another one it says "Level 3"
Here is the second partial in which the title I would like to increment
<fieldset class="levelCreator">
<%= f.label :title, "Level"%> <br /><%# This is what I would like to increment %>
<%= f.text_field :title %><br />
<%= f.hidden_field :_destroy %>
<%= link_to "remove", '#', class: "btn btn-danger btn-mini remove_fields" %>
<%= f.fields_for :steps do |builder| %>
<%= render 'step_fields', f: builder %>
<% end %>
<%= link_to_add_fields "add step", f, :steps %>
here is the first partial in which the add level button exists
<%= form_for(#course) do |f| %>
<%= render 'shared/error_messages_courses' %>
<div class="courseCreator">
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :description %>
<%= f.text_field :description %>
<%= f.label :typeof %>
<%= f.text_field :typeof %>
</div>
<%= f.fields_for :levels do |builder| %>
<%= render 'level_fields', f: builder %>
<% end %>
<%= link_to_add_fields "add level", f, :levels %>
<%= f.submit "Save", class: "btn btn-large btn-primary save" %>
<% end %>
</div>
</div>
It may not be very elegant, but a counter in the parent view should do it:
view:
<% index = 1 %>
<%= f.fields_for :levels do |builder| %>
<%= render 'level_fields', {f: builder, index: index} %>
<% index = index + 1 %>
<% end %>
partial:
<%= f.label :title, "Level #{index}"%>

Resources