In a rails application i am working on, i would like to refresh/reload the index method of my controller without refreshing the view. For instance lets say i have this as my index:
def index
#title =params[:title]
end
And html.erb:
<script>
function changeField() {
var newTitle = "Alerts"
$.ajax({
url: 'index?title=' + newTitle,
type: 'POST',
contentType: 'application/json',
data: '',
dataType: 'script',
headers: {
'X-CSRF-Token': '<%= form_authenticity_token.to_s %>'
},
complete: function () {
alert('<%=#title%>');
}
});
}
</script>
<button type="button" onclick="changeField()"></button>
The problem i am having is that it does not reload the #title variable on the view so i get the original title and not the new title.
When page was loading alert('<%=#title%>') equals alert('first value') and after set a new value javascript code can't be reloaded. If you look html code you can see first value but not second
I think you can add this code to you controller
respond_to do |format|
format.html # index.html.erb
format.js { render :json { :title => params['title'] || #title }.to_json }
end
and add to js code success: function(data) { alert(data['title']) }
Related
I'm trying to create a jackpot betting site (just as a challenge). I have a method in my controller to update the pot when a user adds money to the pot. I display the pot total on the homepage and would like to update it with Ajax as soon as someone adds money to the pot. I'm using the gon gem to pass variables such as the pot total from my controller to my javascript. It works when the page is reloaded but not when the update method is called with ajax.
Heres my PagesController:
def home
#jackpot = Jackpot.last
gon.pot = #jackpot.pot
end
JackpotsController:
def update
#jackpot = Jackpot.find(params[:id])
if params.has_key?(:amount)
#jackpot.update(pot: #jackpot.pot + params[:amount].to_f)
gon.pot = #jackpot.pot
end
respond_to do |format|
format.js
end
end
Javascript: (In the url the :id is hardcoded for now)
$("#bet-btn").click(function() {
$.ajax({
type: "POST",
url: "/jackpot/update/21",
datatype: "json",
success: function() {
console.log("Pot size: " + gon.pot);
updatePot();
},
error: function() {
console.log("error")
}
});
});
This updates the donut progress bar for the pot
function updatePot() {
updateDonutChart('#jackpot-donut', gon.pot , true);
}
Button to place bet: (amount also hardcoded)
<%= link_to "Place Bet", update_pot_path(#jackpot, :amount =>
0.1), method: :post,:remote => true, id: "bet-btn", class: "btn btn-info btn-lg" %>
I'm pretty new to rails and especially javascript/ajax so any help would be appreciated. Thanks!
In the controller, simply respond to JSON:
respond_to do |format|
format.json { render json: { pot: #jackpot.pot } }
end
Specify the dataType when posting with $.ajax. Notice that the new data is bieng passed to the success function, so it's not gon.pot, but data.pot.
$.ajax({
dataType: "json",
url: url,
data: data,
success: function(data) {
console.log('pot', data.pot);
}
});
I have action in controller
def login
#message = params[:mess]
#user = 1
render :rend_log_form
end
the view - rend_log_form.js.erb
l = $("#log_form");
console.log(<%= #message %>);
l.html("<%= j(render(partial: 'login/log_form', locals: {user: #user})) %>");
and some javascript code
$.ajax({
type: "POST",
url: "/login",
data: {mess:"eee"},
success:function(data) {
console.log("SUCCESS POST");
console.log(data);
},
error:function(data) {
console.log("ERROR POST:");
console.log(data);
}
});
action and controller works ok if use link_to with remote: true, but with my javascript code I have in browser console:
ERROR POST:
Object
the Object.responseText - the code of rend_log_form.js.erb
How to render the form with javascript?
Thanks to Hary Bomrah, adding dataType:"html" to ajax call in js code has helped.
I have a checkbox on my trailers index page that, when checked, should filter the results.
trailers_controller:
class TrailersController < ApplicationController
respond_to :html, :js
def index
trailers = Trailer.last(40).sort_by(&:published_at).reverse
trailers = trailers.select { |t| t.budget == "blockbuster" } if params[:show_indie] && params[:show_indie] == "false"
#trailers = Kaminari.paginate_array(trailers).page(params[:page]).per(6)
end
end
And my view:
<div class="trailers">
<%= render #trailers %>
</div>
And my js:
<script>
$(function(){
$('.checkbox-inline').on('change', function() {
var show_indie = $(this).find('input').prop('checked')
$.ajax({
url: '/trailers/filter',
type: "post",
async:true,
dataType: "html",
data: {show_indie},
success: function() {
console.log ("filtered")
},
error: function(){
console.log ("error with ajax")
}
});
})
});
</script>
routes:
post 'trailers/filter' => 'trailers#index'
And my index.js.erb:
console.log('index js loaded')
$('.trailers').html("<%= escape_javascript render(#trailers) %>");
Everything seems to work, the AJAX is posting okay. But the index.js.erb is not rendering. I have a feeling it's because my dataType is "html" instead of JSON or something.. But not really sure how that works, or how to fix it.
What am I doing wrong?
Is this the best way to handle this kind of filtering?
You need to specify dataType as "script"
$.ajax({
method: "GET",
url: "test.js",
dataType: "script"
});
To add to the answer, you need to remember not to store your javascript in your views directly. To make your application run efficiently & properly, you need to use the unobtrusive javascript pattern:
#app/assets/javascripts/application.js
$(document).on('change', '.checkbox-inline', function() {
var show_indie = $(this).find('input').prop('checked')
$.ajax({
url: '/trailers/filter',
type: "post",
dataType: "script",
data: {show_indie},
success: function() {
console.log ("filtered")
},
error: function(){
console.log ("error with ajax")
}
});
});
This will not only free up your views, but also allow you to factor the JS into your asset pipeline, making it more efficient.
I've been all over the place plugging different things into this process and I still get no results.
Sometimes I get the infamous extra "<" error, sometimes absolutely nothing happens, and I'm not sure if this is the problem but I think Google developer is showing that the current page is being sent as the json file I'm asking for and not the json I'm sending (see later). This is what I see in google developer:
Which is definitly NOT my json file:
In any case, this is my javascript:
$('#q_name_cont').autocomplete({
url: "autocomplete/items",
dataType: 'json'
});
This is my route:
get 'autocomplete/items' => 'home#autocomplete_items', :defaults=>{:format=>'json'}
Controller Action (commented out part is another method I was trying for a while):
def autocomplete_items
# respond_to do |format|
# format.js {render 'autocomplete_items'}
#products = Item.all.order(:name)
respond_to do |format|
format.html
format.json {
render json: #products.map {|item| item.name}
}
end
end
Before I was using mapping, I was using this view for the render:
{
"items": [
<%Item.all.each do |i|%>
{ "<%=i.name%>","<%=i.name%>" },
<%#end%>
{ "value": "", "data": "" }
]
}
I've really been all over the place, trying for a very long time to get this to work. What am I missing?
IIRC, Your url and dataType options just do not exist in autocomplete's documentation. You could try source option instead:
$('#q_name_cont').autocomplete({
source: function (request, response) {
$.ajax({
url: "/autocomplete/items", // should be with '/'
dataType: 'json',
data: { query: request.term },
success: function(data) {
// call response to return the result to autocomplete box
response(data);
}
});
}
});
Of course, this is just for showing up all items, if you want to filter like real autocomplete box, you should modify controller to filter the result base on query:
def autocomplete_items
#products = Item.all.order(:name)
respond_to do |format|
format.html
format.json {
render json: #products
.where('name ILIKE ?', "%#{params[:query]}%")
.pluck(:name)
}
end
end
I send data in json format for counting visits. Problem is when i use back arrow in browser - results are send second, third ... and more times and there is one em tag for every click in back arrow on browser. What i can do to overwrite results but not sending second in new place.
My controller:
visits_count = current_user.visits.where(:read => false).count.to_i
respond_to do |format|
format.json { render :json => visits_count }
And my js:
function unread(){
$('#visits p').each( function() {
$.ajax({
url: '/visits/unread_count',
dataType: 'json',
success: function(data) {
if (data > 0) {
$('#visits p').append('<em>' + data +'</em>');
}
}
});
});
};
and my view:
<%= link_to 'visits', visits_path, :id => "visits" %><p></p></li>