I am trying to get Jquery to work on a static portfolio website.
My code is
home.html.erb
<%= link_to navigation_main_path(format: :js), remote: true do %>
<h2> ENTER SITE </h2>
<% end %>
navigation_controller.rb
class NavigationController < ApplicationController
def home
respond_to do |format|
format.js
format.html
end
end
def main
end
end
format.js.erb (for testing) in app/views/navigation
alert('hi');
Error I believe is stopping anything from working
Uncaught SyntaxError: Unexpected token < at processResponse
(rails-ujs.self-661556f443fbae7f6cec8f2cd394aa5e8186cb3f96aded9628126d3484eaa71a.js?body=1:246)
at
rails-ujs.self-661556f443fbae7f6cec8f2cd394aa5e8186cb3f96aded9628126d3484eaa71a.js?body=1:173
at XMLHttpRequest.xhr.onreadystatechange
(rails-ujs.self-661556f443fbae7f6cec8f2cd394aa5e8186cb3f96aded9628126d3484eaa71a.js?body=1:230)
It is telling me there is an unexpected token on the firstline of my HTML with DOCTYPE and I have no clue why and my format.js.erb code does not run. Thank you for the help
Actually, format.js.erb is in the wrong place!
As per Rails naming convention, the resource names for controllers and views should be plural. Rails is expecting NavigationsController and views/navigations/format.js.erb
More info on naming convention here
Hope this helps!
Related
I am searching for the internet about this topic, but I don't get how AJAX works with rails, I already check the documentation and I just simply don't understand it.
What I know is that AJAX is asynchronous and it just only takes to put this code in the view for make the request: "remote:true", the big deal that I don't get it is about this code:
respond_to :js
Apparently, it tells the controller that it would respond to Javascript and you have to make a file for whatever you wanna do with JS, my structure of my project is this one:
View
New.html.erb:
<p>Imagen de portada</p>
<%= simple_form_for #entries, remote: true do |f| %>
<% f.file_field 'input-image' %>
<% end %>
<div id="image-entry"></div>
View route:
views
|
-->admins
|
-->entries
|-->new.html.erb
|-->new.js.erb
Controller
entries_controller.rb
module Admins
class EntriesController < ApplicationController
before_action :authenticate_admin!
def index
render 'index'
end
def new
#entries=''
render 'new'
respond_to :js
end
end
end
Controller route:
controllers
|
-->admins
|
-->entries_controller.erb
JS
new.js.erb
console.log('funciona');
$('#input-image').click(function(){
$('body').css('background-color', 'red');
});
JS route:
views
|
-->admins
|
-->entries
|-->new.html.erb
|-->new.js.erb
Error
My error in this code is the following:
ActionController::UnknownFormat
So, I have questions about this error and what is the correct name of the file in JS for get the respond_to work correctly.
Answer by Irfan Fadilah on Facebook:
Your request is not processed by "new" method in EntriesController. The default form method is POST, so Rails will looking for "create" method in you EntriesController.
You can read RESTful routing in Rails Guide for more details.
In order to make your AJAX request to works. Add "create" method in EntriesController and create.js.erb (just write alert("Hello"); or something to test it) in views/entries.
I have a working Ruby on Rails form that currently posts my results and redirects the user to another view and posts the results. The flow is:
views/tools/index.html.erb -> views/tools/ping.html.erb
Since I have it working now, I'd like to convert it to AJAX and keep the user on the views/tools/index.html.erb view, getting rid of the redirect to enhance the user experience. However, I'm unsure of how to proceed based on the way that my Tools controller is currently setup, and my incredibly lacking knowledge of AJAX.
So, here's what I currently have:
views/tools/index.html.erb (added 'remote: true' to form)
<h1> Tools </h1>
<h3> Ping </h3>
<%= form_tag ping_tool_path(1), method: "post", remote: true do %>
<%= text_field_tag :ip, params[:ip] %>
<%= submit_tag "Ping", name: nil %>
<% end %>
<!-- this is where I'd like to put the results via AJAX -->
<div id="output"></div>
controllers/tools_controller.rb
class ToolsController < ApplicationController
def index
end
def ping
ping_host(params[:ip])
save_host(params[:ip])
# Adds based on recommendations
respond_to do |format|
format.html { redirect_to tools_path }
format.js
end
end
protected
def ping_host(host)
f = IO.popen("ping -c 3 #{host}")
#output = f.readlines
tool_type = "ping"
tool = Tool.find_by(tool_type: tool_type)
tool.increment(:tool_hit_count, by = 1)
tool.save
#results = "<pre>#{#output.join}</pre>".html_safe
end
def save_host(host)
host = Host.find_or_create_by(host_ip: host)
host.increment(:host_hitcount, by = 1)
host.save
end
end
views/tools/ping.html.erb
<%= #results %>
views/tools/ping.js.erb (New file based on suggestion)
$("#output").html("<%= #results %>");
routes.rb
Rails.application.routes.draw do
root 'tools#index'
resources :tools do
member do
post 'ping'
end
end
end
This is what I see on the Network tab in Google Chrome after submitting the form:
So, what I know at this point is that I'll need to add remote: true to my form in views/tools/index.html.erb, and this is where I get lost.
It seems that I have an issue ATM with the fact that I've abstracted the form to use my ping method in the Tools controller, whereas all of the tutorials (and railscasts) I've gone through are doing AJAX on CRUD methods and a given model, not something like what I've build here so far. Please help me understand AJAX!
You're on the right track, now you need to modify the def ping action with a respond_to block.
def ping
ping_host(params[:ip])
save_host(params[:ip])
respond_to do |format|
format.html { redirect_to tools_path } ## if you still want to have html
format.js
end
end
and create a file called view/tools/ping.js.erb where you have javascript that will be run and returned asynchronously
$("#output").html("<%= j #results %>");
The <%= %> block will be evaluated first and replaced with the output of that ruby code. Then this will be inserted into the #output div.
I have created a new micropost controller action called more to receive ajax request.
def more
micropost=Micropost.find_by(params[:id])
#answers=micropost.answers
respond_to do |format|
format.html {redirect_to micropost}
format.js
end
end
and I have created jquery file- more.js.erb
$(".microposts").html("<%= escape_javascript(render('users/unfollow')) %>"); `
to replace the content with a partial
my route file is like
resources :microposts, only: [:edit,:create,:destroy,:update,:show,:more] do
member do
get :more
end
end
and i call the javascript file in the view with
<%= link_to "load more",more_micropost_path(micropost),remote: true %>
Its working with normal html request but not ajax.Nothing happens when I click on the link. I saw similar questions asked by some but the fixes are not working for me. Can someone help me with this. Thanks in advance..
The error in firebug console is
`500 internal server error.
NoMethodError in MicropostsController#more.
Undefined method id for nil:NilClass'
The firebug error console shows this jquery line on the right hand side. I am not sure if its an error.
lixhr.send( ( options.hasContent && options.data ) || null );
judging by the error you posted in the comments, this line may be a problem:
micropost = Micropost.find_by(params[:id])
find_by requires a hash, so either use find
micropost = Micropost.find(params[:id])
or
micropost = Micropost.find_by(id: params[:id])
Good evening SO,
I am having issues gaining access to javascript functions in manifest files when rendering a JS partial. Below are the files which make the current articles#index page work:
Manifested files:
assets/javascripts/option_set_interface.js.coffee.erb
on_load = ->
load_article_click_handlers $('ul.index li.article')
$(document).ready on_load //standard DOM refresh
document.addEventListener 'page:change', on_load //turbolinks
load_article_click_handlers = (jQuery_object) ->
.. Do some stuff...
load_article_click_handlers is the function I would like to gain access to in create.js.erb
assets/javascript/articles.js.coffee
//= require option_set_interface
articles_controller.rb:
class ArticlesController < ApplicationController
def create
#article = Article.new(article_params)
#article.save
respond_to do |format|
format.html { redirect_to articles_path }
format.js { render 'create' }
end
end
def index
#articles = Article.all
end
protected
def article_params
params.require(:article).permit(:title)
end
end
Views and partials: views/articles/
index.html.haml
- provide(:title, 'Article list')
%h1 Article list
.row
.aside.span3
.row
%ul.index
- #articles.each do |article|
= render article
= render 'new'
_article.html.haml
%li.article
%input{ type: 'hidden', value: article.id, name: 'article_id' }
= article.id
= article.title
_new.html.haml
= form_for Article.new, remote: true, html: { id: 'new_article_form' } do |f|
= f.label :title
= f.text_field :title
= f.submit 'Create', class: 'btn btn-large btn-primary'
create.js.erb (where the issue is)
new_list_item = $('<%= escape_javascript( render #article ) %>')
new_list_item.prependTo('ul.index').slideDown()
load_article_click_handlers(new_list_item) //this is the line that breaks the code
The code works well, until I try to call load_article_click_handlers in create.js.erb. I am not sure how to get debug information on it because it uses rails' magic ajax. I'm not very sure how to capture the response.
create.js has access to jquery, clearly. But it does not seem to accept my custom functions. Any help or advice is appreciated, particularly tips on how to debug rail's ajax rendered JS. Currently attemtping to access load_article_click_handlers causes teh script not to run at all.
Things I have tried:
Adding '//= require option_set_interface' to application.js
using javascript_inlude_tag 'option_set_interface' in create.js.erb
EDIT
Found 1 correction, did not eliminate problem.
Solved.
I was going down the wrong path. Issue was with coffeescript's anonymous function wrapper. The feature was built to avoid "polluting the global namespace", which was exactly what I wanted to do with an include file.
Solution is to add
window.load_article_click_handlers = load_article_click_handlers
after the definition of load_article_click_handlers.
Hope this helps someone else.
I have spent a couple of days (like 4) trying to solve this issue. I followed the Hartl Rails 3 tutorial and in chapter 12 tried to convert the site from prototype to jQuery. I am not able to get the "follow"/"unfollow" button to update however.
I am able to issue jQuery commands from within Safari's Inspect Element Console, but if I put even the simplest jQuery command into the destroy.js.erb or create.js.erb files, nothing happens. The log is indicating that the appropriate relationships/destry.js.erb (or create.js.erb) file is rendering.
Here is the code that I have in the controller:
class RelationshipsController < ApplicationController
before_filter :authenticate
def create
#user = User.find(params[:relationship][:followed_id])
current_user.follow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
end
The users/_follow.html.haml is
- relationship = current_user.relationships.build(:followed_id => #user.id)
= form_for(relationship, :remote => true) do |f|
= f.hidden_field :followed_id
.actions= f.submit "Follow"
The users/_unfollow.html.haml is
- relationship = current_user.relationships.find_by_followed_id(#user)
- delete = { :method => :delete }
= form_for(relationship, :html => delete, :remote => true) do |f|
.actions= f.submit "Unfollow"
The users/_follow_form.html.haml is
- unless current_user?(#user)
#follow_form
- if current_user.following?(#user)
= render 'unfollow'
- else
= render 'follow'
The relationships/create.js.erb is
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= "#{#user.followers.count} followers" %>')
The relationships/destroy.js.erb is
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= "#{#user.followers.count} followers" %>')
However, in trying to diagnose this, I tried a very basic
$("#title").html("Followed")
which also does not work.
Looks like an issue with how you're using jQuery.
jQuery uses CSS-style selectors, while Prototype doesn't. So, to make it work, just add a "#" symbol to the selectors.
Instead of
$("follow_form").html("something");
You should use
$("#follow_form").html("something");
// Note the # symbol in the selector.
// Also, remember to end your statements with a semicolon.
You can read about jQuery ID selectors here: http://api.jquery.com/id-selector/
Check your public folder for an Assets folder, with application.js in it. Not sure how I ended up with that, but that was causing ajax queries to be processed twice.
It looks like you might be using Rails 3.1. It's important to use the exact gem versions used in the tutorial (including Rails 3.0 instead of 3.1) if want the same results. See the debugging tips at the Rails Tutorial Help page for more suggestions.