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">
Related
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) %>');
I'm making a bloglike application. I want to make it so that blog posts are editable if clicked.
This is my partial that displays all the posts of a user and makes them clickable
<% if #feed_items.any? %>
<% #feed_items.in_groups_of(3, false).each do |feeds| %>
<div class="row">
<% feeds.each do |feed| %>
<div class="col-md-4">
<ol class="posts">
<%= link_to edit_post_path(feed) do %>
<%= render feed %>
<% end %>
</ol>
</div>
<% end %>
</div>
<% end %>
<% end %>
This is the Edit view that it redirects to when a post is clicked:
<% if logged_in? %>
<div class="row">
<%= render 'shared/post_form' %>
</div>
<% end %>
And this is the '_post_form' partial which is the layout for an editable post:
<%= form_for(#post) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new post..." %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
When I click a post to edit it it does redirect however it gives me the error: "First argument in form cannot contain nil or be empty"
Any suggestions on how to resolve this?
In your controller's edit method you have to set #post like,
def edit
#post = Post.find(params[:id])
end
Edited
I'm working on an app that is intended to be a rough clone of survey monkey.
Survey's act as the 'template' and submissions are responses to that survey template.
I have a show page that leads to a form for a new submission. I have the correct survey template and the associated models/attributes I require (confirmed in pry), however I can't get any of the associated questions and answers to render as form input fields.
controllers/surveys_controller.rb
before_action :set_survey, except: [:index, :new, :create, :home, :mysurveys]
def show
#survey.submissions.build
end
private
def survey_params
params[:survey].permit(:user_id, :title, questions_attributes: [:id, :prompt, :_destroy, answers_attributes: [:id, :content, :_destroy]])
end
def set_survey
#survey = Survey.find(params[:id])
end
views/surveys/show.html.erb
<h1>This is the show page for surveys.</h1>
<h3><%= #survey.title %></h3>
<% if current_user == #survey.user_id %>
<%= render "mysurvey" %>
<% else %>
<%= render 'survey_form' %>
<% end %>
views/surveys/_survey_form.html.erb
<%= form_for #survey do |f| %>
<% #survey.questions.each do |q| %>
<%= q.prompt %>
<%= f.text_field %>
<% q.answers.each do |a| %>
<%= a.content %>
<%= f.text_field %>
<% end %>
<% end %>
<% end %>
I've tried f.text_field :q, :questions, :prompt q.prompt. Rails just returns undefined method.
Your show.html.erb
<h1>This is the show page for surveys.</h1>
<h3><%= #survey.title %></h3>
<% if current_user == #survey.user_id %>
<% render "mysurvey" %>
<% else %>
<% render 'survey_form' %>
<% end %>
Which should be like
<h1>This is the show page for surveys.</h1>
<h3><%= #survey.title %></h3>
<% if current_user == #survey.user_id %>
<%= render "mysurvey" %>
<% else %>
<%= render 'survey_form' %>
<% end %>
This is really simple, but i'm going slightly mad and probably missing something that's staring me in the face. Can anyone help?
Basically, I have a simple each loop that's returning an extra rogue line. Even when there's nothing in the db, I get one line returned!
My show view including the loop is:
<p id="notice"><%= notice %></p>
<p>
<b>Header:</b>
<%= #mailer.header %>
</p>
<p>
<b>Subtext:</b>
<%= #mailer.subtext %>
</p>
<div id="" class="" padding-left: 30px;>
<h3>Mailer Products </h3>
<ol id="mailer-Product-list">
<% #mailer.mailer_products.sort_by { |mailer_products| mailer_products.position }.each do |mailer_product| %>
<%= content_tag_for :li, mailer_product do %>
<%= mailer_product.product.cat_no %>
<% end %>
<% end %>
</ol>
<%#= link_to 'Done', #product, :class => "standard-button" %>
</div>
<%= form_for([#mailer,#mailer.mailer_products.build]) do |f| %>
<div class="field">
<%= f.label :product_id %><br />
<%= f.text_field :product_id %>
</div>
<div class="field">
<%= f.hidden_field :mailer_id, :value => #mailer.id %>
</div>
<div class="actions">
<%= f.submit "Add Product" %>
</div>
<% end %>
<%= link_to 'Edit', edit_mailer_path(#mailer) %> |
<%= link_to 'Back', mailers_path %>
The controller code is:
class MailersController < ApplicationController
def show
#mailer = Mailer.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #mailer }
end
end
class MailerProductsController < ApplicationController
def index
#mailer_products = MailerProduct.find(:all)
respond_to do |format|
format.html # index.html.erb
format.json { render :json => #mailer_products }
end
end
end
end
Your call to form_for looks like this
form_for([#mailer,#mailer.mailer_products.build]) do |f|
You get an extra blank item because that's what calling .build on mailer_products does: it appends a new instance to the array
When the form is after the loop this doesn't matter, but when things are the other way around the loop will be on the modified array
My usual mistake is adding a <%= instead of a <% on the loop...
<%= #foo.each do |itme| %>
# do stuff
<% end %>
which should be
<% #foo.each do |itme| %>
# do stuff
<% end %>
Double check your tags...
I have a parent class Car and the /cars/show page lists all of the reviews associated with it. The reviews can be voted on. I am having some difficulty getting the :votes_count to update by JavaScript.
/votes/create.js.erb
$("#votes").html("<%= review.votes_count %>") // this does not work
/cars/show
<% #car.reviews.each do |review| %>
<p id='votes'><%= pluralize(review.votes_count, 'vote') %></p>
<% if current_user %>
<%= form_for(#vote, :remote => true) do |f| %>
<%= f.hidden_field "review_id", :value => review.id %>
<%= f.hidden_field "user_id", :value => current_user.id %>
<%= f.submit "vote" %>
<% end %>
<% end %>
<br />
<%= review.content %>
<% end %>
create.js.erb
<% #car.reviews.each do |review| %>
$("#review_<%= review.id %>").html("<%= pluralize(review.votes_count, 'vote') %>");
<% end %>