Rails jQuery is rendering text instead of collection - javascript

I created a file inside my javascript folder "load-contacts.js" in hopes of trying to load the collections as well as the pagination via jquery.
$(document).on('turbolinks:load', function() {
$('#contacts').html("<%= j render(#contacts) %>");
$('#paginator').html("<%= j paginate #contacts, remote: true %>");
});
When I run this code it actually works and change the part where it intended to change. However, it is only rendering it as text as it instead of the collection and the pagination (kaminari gem).
Here's how it looks like:
Any idea what am i missing here?
UPDATES:
Here's my contacts controller
class ContactsController < ApplicationController
before_action :find_params, only: [:edit, :update, :destroy]
def index
# catch the group id from params in session
session[:selected_group_id] = params[:group_id]
#contacts = Contact.by_group(params[:group_id]).search(params[:term]).order(created_at: :desc).page params[:page]
end
def autocomplete
#contacts = Contact.search(params[:term]).order(created_at: :desc).page(params[:page])
render json: #contacts.map { |contact| { id: contact.id, value: contact.name } }
end
def new
#contact = Contact.new
end
def create
#contact = Contact.new(contact_params)
if #contact.save
flash[:success] = "Contact was successfully created."
redirect_to(previous_query_string)
else
render 'new'
end
end
def edit
end
def update
if #contact.update(contact_params)
flash[:success] = "Contact successfully updated."
redirect_to(previous_query_string)
else
render 'edit'
end
end
def destroy
#contact.destroy
flash[:success] = "Contact successfuly deleted."
redirect_to contacts_path
end
private
def contact_params
params.require(:contact).permit(:name, :email, :phone, :mobile, :company, :address, :city, :state, :country, :zip, :group_id, :avatar)
end
def find_params
#contact = Contact.find(params[:id])
end
def previous_query_string
session[:selected_group_id] ? { group_id: session[:selected_group_id] } : {}
end
end
Here's the part for the kaminari gem pagination:
<div class="card-footer">
<div class="pagination justify-content-center" id="paginator">
<%= paginate #contacts, remote: true %>
</div>
</div>
And here's where I am suppose to be rendering the contacts inside the views/contacts/index.html.erb:
<table class="table" id="contacts">
<%= render partial: "contact", object: #contacts, remote: true %>
</table>

you can't use j render outside .erb. Because j render is method of rails, your js just know it is string
what you need are use script tag inside your html.erb, or use rails ajax. It is working as expected
reference: How to render partial on the same page after clicking on link_to with AJAX

have you tried escape_javascript before calling render.
something like:
<%= escape_javascript render(my_partial) %>

Related

AJAX button processes, doesn't change

I've found a lot of people with the same problem I have, but none of the solutions apply to my situation. I am following Michael Hartl's tutorial here. I have a follow system set up in accordance with chapter 14 (I'm using the latest edition of the book, as I am on Rails 5.1). The follow/unfollow button processes in the database, but I have to manually refresh the page to see the button and follow count change.
I get this in the browser console log:
POST 500 (Internal Server Error)
jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js:10255
send # jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js:10255
ajax # jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js:9739
ajax # jquery_ujs.self-784a997f6726036b1993eb2217c9cb558e1cbb801c6da88105588c56f13b466a.js:94
handleRemote # jquery_ujs.self-784a997f6726036b1993eb2217c9cb558e1cbb801c6da88105588c56f13b466a.js:179
(anonymous) # jquery_ujs.self-784a997f6726036b1993eb2217c9cb558e1cbb801c6da88105588c56f13b466a.js:512
dispatch # jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js:5227
elemData.handle # jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js:4879
relationships_controller.rb:
class RelationshipsController < ApplicationController
before_action :authenticate_user!
def create
user = User.find(params[:followed_id])
current_user.follow(user)
respond_to do |format|
format.html { redirect_to(:back) }
format.js
end
end
def destroy
user = Relationship.find(params[:id]).followed
current_user.unfollow(user)
respond_to do |format|
format.html { redirect_to(:back) }
format.js
end
end
end
views/users/_follow.html.erb:
<%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
<div><%= hidden_field_tag :followed_id, #user.id %></div>
<%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>
views/users/_unfollow.html.erb
<%= form_for(current_user.active_relationships.find_by(followed_id: #user.id),
html: { method: :delete }, remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn" %>
<% end %>
views/users/_follow_form.html.erb
<% if current_user != #user %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
relationships/create.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>");
$("#followers").html('<%= #user.followers.count %>');
relationships/destroy.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>");
$("#followers").html('<%= #user.followers.count %>');
users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user!, only: [:index, :edit, :update, :destroy,
:following, :followers]
def index
#page_title = "Forge Users"
#users = User.all
end
def show
#user = User.find(params[:id])
#posts = Post.all
end
def following
#title = "Following"
#user = User.find(params[:id])
#users = #user.following
render 'show_follow'
end
def followers
#title = "Followers"
#user = User.find(params[:id])
#users = #user.followers
render 'show_follow'
end
end
What am I doing wrong?
You set local variable user
def create
user = User.find(params[:followed_id])
but reference class instance variable #user in your .js.erb template.
$("#followers").html('<%= #user.followers.count %>');
Instead, set #user = User.find(params[:followed_id]) so it is available to the views. Actually, I think you are trying to set #user = current_user. That might make more sense.
You need to rename your Javascript files to have .erb ending.
relationships/create.js.erb and relationships/destroy.js.erb. It's because you have Ruby in the file so it has to process the Ruby before it gets interpreted as Javascript and sent back.
http://guides.rubyonrails.org/working_with_javascript_in_rails.html#a-simple-example

rails 5 undefine template error

i am creating rails 5 and adding comment to a show action which is displayed in modal
in my show action for comment i have it like this
#selfie = Selfy.find(params[:id])
respond_to do |format|
format.js
end
with this i cant get the show through modal like this
<%= link_to fetch_selfy_path(selfie.id), class: "show_lightbox", data: { featherlight: "mylightbox" }, remote: true do %>
<img class="card-main-image" src="<%= selfie.photo.url if selfie.photo.url %>" alt="Image Alt text">
<% end %>
<div class="lightbox" id="lightbox">
<%=render partial: "selfies/show", locals: { selfie: selfie } %>
</div>
after clicking on the button we show action together with a comment
<% selfie.comments.each do |comment| %>
<%= render partial: "selfies/comments/comment", locals: { comment: comment } %>
<% end %>
where the partial looks like
<p> <b><%= comment.user.username %>: </b><%= comment.body %></p>
all this works fine until i try to inject the new commect through ajax
addCommentToSelfie("<%= j render "selfies/comments/comment", locals: { comment: #comment } %>");
this returns and error of
ActionView::Template::Error (undefined local variable or method `comment' for #<#<Class:0x007f207400c648>:0x00557937265830>):
1:
2: <p> <b><%= comment.user.username %>: </b><%= comment.body %></p>
app/views/selfies/comments/_comment.html.erb:2:in `_app_views_selfies_comments__comment_html_erb__4557429192479440105_46989553619000'
i tried different methond but still getting same error
You're mixing up different syntaxes with some mixing up of quotes too. If you use locals: ... you must also use partial:, or omit both in this case...
addCommentToSelfie("<%= j render 'selfies/comments/comment', comment: #comment %>");
based on the answers provide above, i was able to solve my issue
first i clean my creat.js.erb to
$("#comments").append("<%= j render partial: 'selfies/comments/comment', locals: { comment: #comment } %>");
secondy was getting error nil class because i wasnt using instant variable in my comments controller
from:
def create
comment = #selfie.comments.new(comment_params)
comment.user = current_user
comment.save
end
TO:
def create
#comment = #selfie.comments.new(comment_params)
#comment.user = current_user
#comment.save
respond_to do |format|
format.js
end
from there everything works smoothly
Could you show us the action create in the comment controller ? Usually, I do something like that.
def create
#comment = #selfie.comments.new(comment_params)
#comment.user = current_user
respond_to do |format|
if #comment.save
format.html { redirect_to #comment }
format.js
else
render :new
end
end
end
Then in your view, you should have the file comments/create.js.erb that contains your js :
addCommentToSelfie("<%= j render 'selfies/comments/comment', comment: #comment %>");
And now #comment should exist.

rails create pages by hash with nested resources

image
as image, i'd like to make page with nested resources.
my plan is
register user
create tour(request input informations by params)
if #tour.tour_days(params) value is over 1
create day pages as much as the number of user put into tour_day params
so i want to create page like(if 1user create first tour and put 3 into tour_day)
localhost:3000/tours/1/days/1
localhost:3000/tours/1/days/2
localhost:3000/tours/1/days/3
(if 1user create second tour and put 2 into tour_day)
localhost:3000/tours/2/days/1
localhost:3000/tours/2/days/2
i'd like to create these pages by automatically when user put number into tour_day and click submit button from tour_view
i've done create nested resources and throw data but i can't make clearly.. ;(
the reason i nest resources and create additional controller(day_controller) is afterwords i'd like to add recommendation function(recommendation for whom couldn't make schedule)...
actually i'd like to make page like airbnb(creating room process)
(Am i doing right process??)
tour_controller
class ToursController < ApplicationController
before_action :set_tour, only:[:show, :edit, :update]
before_action :authenticate_user!, except:[:show]
def index
#tours = current_user.tours
end
def show
end
def new
#tour = current_user.tours.build
end
def create
#tour = current_user.tours.build(tour_params)
i = 0
if #tour.save
redirect_to new_tour_day_path(#tour.id, #day), notice: "Saved Your Tour Courses"
else
render :new
end
end
def edit
end
def update
if #tour.update(tour_params)
redirect_to edit_tour_day_path(#tour.id, #day), notice: "Updated Your Tour Courses"
else
render :edit
end
end
private
def set_tour
#tour = Tour.find(params[:id])
end
def tour_params
params.require(:tour).permit(:tour_title, :tour_theme, :tour_summary, :tour_language, :tour_day, :tour_member, :tour_car, :tour_camera, :price)
end
end
day_controller
class DaysController < ApplicationController
before_action :set_tour
before_action :set_day, only: [:show, :edit, :update]
before_action :authenticate_user!, except:[:show]
def index
end
def show
end
def new
#tour = current_user.tours.find(params[:tour_id])
#day = #tour.days.build
end
def create
#tour = current_user.tours.find(params[:tour_id])
#day = #tour.days.build(day_params)
if #day.save
redirect_to edit_tour_day_path(#tour.id, #day), notice: "Saved Your Tour Courses"
else
render :new, notice: "Errors"
end
end
def edit
end
def update
if #day.update(day_params)
redirect_to edit_tour_day_path(#day), notice: "Updated Your Tour Courses"
else
redner :edit
end
end
private
def set_tour
#tour = Tour.find(params[:tour_id])
end
def set_day
#day = Day.find(params[:id])
end
def day_params
params.require(:day).permit(:day_number)
end
end
tour_view(test page)
<div class="container">
<%= form_for #tour, :html => { multipart: true } do |f| %>
<div class="col-md-3 select">
<div class="form-group">
<label>Maximum Tour Day</label>
<%= f.select :tour_day, [["1",1], ["2",2], ["3",3], ["4",4]], prompt: "Select...", class: "form-control" %>
</div>
</div>
<div class="actions">
<%= f.submit "save", class: "btn btn-primary" %>
</div>
<% end %>
</div>
day_view(test page)
<div class="container">
<%= form_for [:tour, #day] do |f| %>
<label>day_number</label>
<%= f.text_field :schedule_, class: "form-control" %>
<div class="actions">
<%= f.submit "Save", class: "btn btn-primary"%>
</div>
<% end %>
</div>
** additionally
Inside of Day view
i'd like to create schedule like
image
when i click an icon, the form appear and make detail tour schedule with ajax.
how can i approach to create this function??
----
this is my first project of web programming, im so confusing
plz... give me some(lots of) help...
----
im using rails 5.0.0.1 and rails 2.3.1

Why does my Rails AJAX delete method only work if I refresh?

I just incorporated the DESTROY method for items in my school project. It worked fine, but now I must use AJAX to complete the action. After implementing this code, it only displays on the browser when I refresh the page, and not instantly when I delete an item. If I did not include enough information please let me know.
_item.html.erb
<% item.each do |i| %>
<p><%= i.name %> | <%= link_to "Complete", i, method: :delete, remote: true, class: 'glyphicon glyphicon-ok' %></p>
<% end %>
destroy.js.erb
<% if #item.destroyed? %>
$('#item-' +<%= #item.id %>).hide();
<% else %>
$('#item-' +<%= #item.id %>).prepend("<%= flash[:error] %>");
<% end %>
items_controller.rb
class ItemsController < ApplicationController
def index
#items = Item.all
end
def show
#item = Item.find(params[:id])
end
def new
#item = Item.new
end
def edit
#item = Item.find(params[:id])
end
def create
#item = Item.new(params.require(:item).permit(:name))
if #item.save
flash[:notice] = "The item was added to your list."
redirect_to current_user
else
flash[:error] = "There was a problem creating your item."
redirect_to current_user
end
end
def destroy
#item = Item.find(params[:id])
if #item.destroy
flash[:notice] = "\"#{#item.name}\" was completed and destroyed."
else
flash[:error] = "There was an error completing the item."
end
respond_to do |format|
format.html
format.js
end
end
end
Flash sets the message for the next request, this is why it works correctly in your create action (because you are redirecting). In your destroy action, you are rendering (which is not good, since it means delete request gets resent on page refresh, you should be redirecting here too) and setting flash, so it shows up on next request (refresh). If you want to send message for the response to the current request, you have to use flash.now :
flash.now[:notice] = "\"#{#item.name}\" was ..."
Again, you should use flash and redirect on success and use flash.now and render on request failure.
EDIT:
The above paragraphs only apply to html requests. I initially missed the point of the question! Thanks BroiSatse
Looking at your display code, you dont seem to be setting the "#item-#item.id", so your return js does nothing. Add it like this:
<p id="item-<%= i.id %>"><%= i.name %> | ...

Rails: Can I send a GET request to a create path?

I'm trying to append new comments to a list of existing comments using javascript and ajax. I set up my Comments#create to create a new comment and then render its text. But how can I access this text with ajax?
controllers/comments_controller.rb
def new
#comment = Comment.new
#comments = Comment.all
end
def create
#thing = Thing.find(params[:thing_id])
#comment = #thing.comments.create(comment_params)
render text: #comment.text.to_s + "".html_safe
end
My form for a new comment and ajax/javascript attempt:
<%= form_for([#thing, #comment], remote: true) do |f| %>
<%= f.text_area :text, :placeholder => "Explain your rating..." %>
<div id="btn"><%= f.submit "Post", class: "btn", id: "postacomment" %></div>
<script type="text/javascript">
$("#postacomment").click(function() {
$.get( "<%= new_thing_comment_path(:id => #comment.id) %>", function( data ) {
$('#comments_h2').prepend( data );
});
});
</script>
<% end %>
First of all, don't try to bend HTTP methods to fill your needs, follow them instead.
If you want to respond to javascript with rails, that is fairly easy. On your comments controller:
def new
#comment = Comment.new
#comments = Comment.all
end
def create
#thing = Thing.find(params[:thing_id])
#comment = #thing.comments.create(comment_params)
respond_to do |format|
format.html { redirect_to new_comments_path } #this is just a redirection in case JS is disabled
format.js
end
end
As you can see we are now responding to two types of formats, in this case html and js, this forces you to have those corresponding views, or at least for the js version which may look like this:
app/views/comments/create.js.erb:
$('#comments_h2').prepend("<%= j #comment %>");
In the example above I'm assuming you have a partial for rendering a comment, it should look something like:
app/views/comments/_comment.html.erb:
<h2><%= comment.content %></h2>
Obviously you have to update that file to meet your needs.
Hope it helps!

Categories

Resources