Rails - How to access index value in partial - ruby-on-rails

I am trying to use the built-in rails ajax to append an item to a list after a user fills out a form - However, I cannot target the div tag to append the new entry to: ActionView::Template::Error (undefined local variable or method 'index'
Clients/Index:
<% #clients.each_with_index do |client, index| %>
<div id="communication_pane<%= index %>">
<%= render client.communications.order(created_at: :desc) %>
</div>
<%= form_for([#clientlist, client, client.communications.build], remote: true) do |f| %>
<%= f.text_area :content, class: "form-control", id: "communication_content#{index}" %>
<%= f.submit("New Communication") %>
<% end %>
Communications/create.js.erb:
$('#communication_pane<%= index %>').prepend('<%= escape_javascript(render #communications) %>');
How can you access the index value from Clients/Index?

In your create.js.erb, there is an undefined variable index at $('#communication_pane<%= index %>')
Because there is no way the server knows about where you clicked on the client so that you have to explicitly tell the server about it. Here is an idea:
<!-- app/views/clients/index.html.erb -->
<% #clients.each_with_index do |client, index| %>
<div id="communication_pane<%= index %>">
<%= render client.communications.order(created_at: :desc) %>
</div>
<%= form_for([#clientlist, client, client.communications.build], remote: true) do |f| %>
<%= f.text_area :content, class: "form-control", id: "communication_content#{index}" %>
<!-- Letting server know the index of current form by adding a param -->
<%= hidden_field_tag :client_index, index %>
<%= f.submit("New Communication") %>
<% end %>
<% end %>
Then at your js.erb file, use params[:client_index] instead of index
# app/views/communications/create.js.erb
$('#communication_pane<%= params[:client_index] %>')
.prepend('<%= escape_javascript(render #communications) %>');
Hope this help.

I think you will have to pass index variable to your controller action as hidden_field and then display it on create.js.erb
clients/index:
<% #clients.each_with_index do |client, index| %>
<div id="communication_pane<%= index %>">
<%= render client.communications.order(created_at: :desc) %>
</div>
<%= form_for([#clientlist, client, client.communications.build], remote: true) do |f| %>
<%= f.hidden_field :index, value: index %>
<%= f.text_area :content, class: "form-control", id: "communication_content#{index}" %>
<%= f.submit("New Communication") %>
<% end %>
communications_controller
def create
#index = params[:communication][:index]
...
end
Communications/create.js.erb
$('#communication_pane<%= #index %>').prepend('<%= escape_javascript(render #communications) %>');

Related

How to change the content of rendered layout in rails?

Have to render the form that already exist in the project inside the page, but with a different title
app/views/welcome
<div class="form-wrapper>
<%= render 'form/form_variants/register_1', register: #register %>
</div>
-----------
app/views/form/form_variants/register_1
<%= form_for register.user, as: :user, url: register_path(service: params[:service]), method: :post %>
<%= content_tag :div, class: html_class('simpleFormHeading') do %>
<%= content_tag :h1, t('signup.title_register') %> #title that should be changed
<%= content_tag :p, raw(t('login.account_login.text', login_link: login_link)) %>
<% end %>
#a lot of inputs
<% end%>
Thanks in advance for your reply!
I would pass it as another variable to the partial
<div class="form-wrapper>
<%= render 'form/form_variants/register_1', register: #register, signup_title = 'whatever' %>
</div>
# app/views/form/form_variants/register_1
# optional: init signup_title to a default value depending on your needs
<% signup_title ||= t('signup.title_register') %>
<%= content_tag :h1, signup_title %>

Rails 5: Nil error in the first argument of a form

I'm quite new with rails so excuse my ignorance.
I have an homepage with a view of astronomic observations and I want to put in the same page the view of the outings that the observatory organize.
Since I can't append two views in the same page I tryed to pass the second view as a partial but I get an error
First argument in form cannot contain nil or be empty
So I though it was a problem of variables and tryed to pass the local variable of the partial but nothing changed.
So how do I pass a variable of #outing to the partial outings/_index.html.erb which will be visualized in the view of observative_sessions
I defined #outing=Outing.new in outings_controller which is the controller for the view outings
In app > views > observative_sessions I have the index.html.erb with
<div class="panel panel-default" id = "observative_sessions">
...
</div>
<%= render 'outings/index', :outings => #outing %>
In app > views > outings I put an _index.html.erb
<%= render 'outings/new_modal' %>
<div class="panel panel-default">
...
<tbody>
<% #outings.each do |outing| %>
...
<% end %>
</tbody>
The _new_modal.html.erb calls the _form.html.erb
<%= render 'outings/form' %>
And then the form
<%= bootstrap_form_for #outing do |f| %>
<%= f.date_field :day, label: 'Giorno:' %>
<%= f.text_field :location, label: 'Luogo:' %>
<%= f.time_field :time, label: 'Ora:' %>
<%= f.submit 'Aggiorna' %>
<% end %>
I get the error in the first line of the form with #outing.
If I put the view in a page alone everything work but not with the partial.
So what did I do wrong?
Thank you in advance for all the help.
In app > views > observative_sessions I have the index.html.erb with
<div class="panel panel-default" id = "observative_sessions">
...
</div>
<%= render partial: 'outings/index', locals: {outing: #outing} %>
In app > views > outings I put an _index.html.erb
<%= render partial: 'outings/new_modal',locals: {outing: outing} %>
<div class="panel panel-default">
...
<tbody>
<% #outings.each do |outing| %>
...
<% end %>
</tbody>
The _new_modal.html.erb calls the _form.html.erb
<%= render partial: 'outings/form', locals: {outing: outing} %>
Then in your form use the local outing variable:
<%= bootstrap_form_for outing do |f| %>
<%= f.date_field :day, label: 'Giorno:' %>
<%= f.text_field :location, label: 'Luogo:' %>
<%= f.time_field :time, label: 'Ora:' %>
<%= f.submit 'Aggiorna' %>
<% end %>
You need to pass #outing variable to all forms those are using #outing variable.
Change the line of rendering _new_modal.html.erb partial like this
<%= render 'outings/new_modal', outing: outings %>
Then change the line of rendering _form.html.erb like this
<%= render 'outings/form', outing: outing %>
And finally change the actual form like this
<%= bootstrap_form_for outing do |f| %>
<%= f.date_field :day, label: 'Giorno:' %>
<%= f.text_field :location, label: 'Luogo:' %>
<%= f.time_field :time, label: 'Ora:' %>
<%= f.submit 'Aggiorna' %>
<% end %>

rails content_for rendering content twice

I use fields_for as so:
<%= f.fields_for :task_comments, #task_category.task_comments do |task_comment_builder| %>
<%= render 'field', f: task_comment_builder %>
<% end %>
My fields partial contains the following:
<% content_for :dynamic_field do %>
<%= f.text_field :comment %>
<% end %>
<%= render 'shared/dynamic_field' %>
dynamic_field partial contains this:
<div class="field-border">
<%= yield :dynamic_field %>
</div>
What happens is if there are 3 task comments, instead of displaying the comment field once for each task_comment, it displays the comment field twice for each task_comment.
What might I be doing wrong?
Rather than using content_for, I decided to use render layout, which does the job:
<%= f.fields_for :task_comments, #task_category.task_comments do |task_comment_builder| %>
<%= dynamic_fields task_comment_builder do |f| %>
<%= render 'field', f:f %>
<% end %>
<% end %>
# application_helper.rb
def dynamic_fields(f, options = {}, &block)
options[:id] ||= "#{f.object.class.name.underscore}_#{f.object.object_id}"
render layout: "shared/dynamic_fields", locals: {f: f, options: options}, &block
end
# shared/_dynamic_fields.html.erb
<div class="field-border">
<%= link_to(raw('<i class="glyphicon glyphicon-remove"></i>'), '#', class: 'btn btn-danger remove-field', style: "float: right;") %>
<div style="clear: both; padding-top: 3px;">
<%= yield f %>
</div>
</div>

How to hide the form elements if the field is empty in ruby on rails?

I am using OpenStruct form for in my view like the following,
<%= form_for(OpenStruct.new(params[:f]), as: :f, url: product_types_path, method: :get, remote: true, html: {class: 'type'}) do |f| %>
<div class="field">
<%= f.label :product_type_id %>
<%= foreign_key(f, :product_type_id, Asset::Product::Type) %>
</div>
<% end %>
I want to hide the other form elements if product_type_id is nil or blank or empty?
I tried this,
<% unless product_type_id.blank? %>
<div class="field">
<%= render 'form' %>
</div>
<% else %>
<p>Select Product Type</p>
<% end %>
So if I got it right what you want to do is not to render the form if what you received with the param product_type_id is blank.
Is it possible for you to instatiate the variable in the controller instead of defining it directly in the form builder?
For instance in your controller:
def index
#product_type = OpenStruct.new(params[:f])
end
and in your view:
<% unless #product_type.product_type_id.blank? %>
<div class="field">
<%= render 'form', product_type: #product_type %>
</div>
<% else %>
<p>Select Product Type</p>
<% end %>
and finally your partial:
<%= form_for(product_type), as: :f, url: product_types_path, method: :get, remote: true, html: {class: 'type'}) do |f| %>
<div class="field">
<%= f.label :product_type_id %>
<%= foreign_key(f, :product_type_id, Asset::Product::Type) %>
</div>
<% end %>

AJAX updating todo list in Rails 3

I'm trying to convert my todo list app to use AJAX . Here is my update action of TasksController :
class TasksController < ApplicationController
def update
#list= List.find(params[:list_id])
#task=#list.tasks.find(params[:id])
#task.update_attributes(params[:task])
respond_to do |format|
format.html { redirect_to [current_user,#list], notice: 'Task completed' }
format.js
end
end
end
tasks/update.js.erb :
<% if #task.completed? %>
$('#edit_task_<%= #task.id %>').appendTo('#completed_tasks');
<% else %>
$('#edit_task_<%= #task.id %>').appendTo('#incomplete_tasks');
<% end %>
This is my lists/show.html.erb which lists out all tasks for a particular list :
<h3>Unfinished Tasks</h3>
<div class="tasks" id="incomplete_tasks">
<% #list.tasks.incomplete.each do |task| %>
<%= form_for [current_user,#list,task], remote:true do |f| %>
<%= f.check_box :completed %>
<%= f.submit %>
<%= f.label :completed, task.description %>
<% end %>
<% end %>
</div>
<h3>Finished Tasks</h3>
<div class="tasks" id="completed_tasks">
<% #list.tasks.completed.each do |task| %>
<%= form_for [current_user,#list,task], remote: true do |f| %>
<%= f.check_box :completed %>
<%= f.submit %>
<%= f.label :completed, task.description %>
<% end %>
<% end %>
<div class="tasks" id="completed_tasks">
<% #list.tasks.completed.each do |task| %>
<%= form_for [current_user,#list,task], remote: true do |f| %>
<%= f.check_box :completed %>
<%= f.submit %>
<%= f.label :completed, task.description %>
<% end %>
<% end %>
</div>
So, I don't quite understand the tasks/update.js.erb code.
$('#edit_task_').appendTo('#completed_tasks');
In the above code, from which html file are we taking the contents of this div :
Where does that div come from ? Please tell me if my question is unclear ,I'll try and rephrase it . Just to be clear , my code works , but I don't know why ?
Whenever you do a ajax request to your update method in the controller, the tasks get updated and it responds back with data in the format.js. After it responds, the update.js.erb gets called which updates the different elements in the page, from which you sent the ajax request, with the updated tasks.
In you update.js.erb,
<% if #task.completed? %>
$('#edit_task_<%= #task.id %>').appendTo('#completed_tasks');
<% else %>
$('#edit_task_<%= #task.id %>').appendTo('#incomplete_tasks');
<% end %>
there is a #task variable, which is the new task. If the task is completed, then it adds the task to the complete_tasks div - else it appends to the incomplete_tasks div.
Completed Tasks - <div class="tasks" id="completed_tasks">
Incomplete Tasks - <div class="tasks" id="incomplete_tasks">

Resources