i am making a calendar, and i make an ajax request on page load to get the some data from the rails db.
the ajax call successfully receives object on page load.
when i click on next or previous button to get the previous months data or next months data, even though the ajax call happens, no data object is receiving on success callback
i receive a set of objects which i access like the code below but only for the page load ajax call, the ajax call gets a status code 200 - OK each time but no json object is received on next requests.
In other words, console.log(data) only works on the page load event while console.log($month) works everytime
UPDATE: using the dev tools, i can see the response data, but they are not accessible from success in ajax...
UPDATE 2: when i uncomment error i get the message "The error code is: OK"
my ajax code looks like this
function retrieve($month) {
console.log($month);
var jsondata = {
events: {
month: $month,
}
}
$.ajax({
cache: false,
type: "POST",
url: "/events/find",
data: jsondata,
dataType: json,
statusCode: {
200: function() {
//alert("200");
},
202: function() {
//alert("202");
}
},
success: function(data) {
//alert("Data Send!");
//var data = JSON.stringify(data);
console.log(data);
for (var i = 0; i < data.length; i++) {
var day = data[i].date.substring(0, 2);
$("td[data-day='" + day + "']").addClass('added');
}
},
error: function(xhr) {
//alert("The error code is: " + xhr.statusText);
}
});
}
events_controller
def find
params = event_params
#events = Event.where('date LIKE ?',"%#{params[:month]}%")
respond_to do |format|
if #events
format.json {
render json: #events.to_json
}
else
render 'index'
end
end
end
private
def event_params
params.require(:events).permit(:date, :timerange,:month)
end
example response from rails log
Started POST "/events/find" for ::1 at 2015-08-16 16:09:59 +0300
Processing by EventsController#find as */*
Parameters: {"events"=>{"month"=>"September"}}
Event Load (0.1ms) SELECT "events".* FROM "events" WHERE (date LIKE '%September%')
Completed 200 OK in 2ms (Views: 0.1ms | ActiveRecord: 0.1ms)
Just for future reference for someone who might need this.
The problem was the dataType: json
it seems that when rails converted the results to json, they were invalid for jquery thus the error event was fired.
removing dataType.json from the ajax request fixed my problems.
Related
I am experiecing some issues with AJAX updating the page. The actual data in the database is updated but this is not always reflecting in real time on the web page.
For example, I have the following event:
$("#add_note").click(function(e) {
//e.preventDefault();
$("#add_note_form").validate({
rules: {
contact_note: {
required: true
}
},
submitHandler: function(form) {
contact.modal_update({
'obj' : $('#add_note_form'),
'uri' : '/contact/add_note/'
});
}
});
});
This function when a new note is created calls a callback to validate the form fields first and then if successful calls a callback inside a seperate class to conduct the update. See the modal_update class below:
// Update modal
this.modal_update = function(data)
{//
// Declare a few variables for the data object we've received
obj = data.obj // The form element to serialize
uri = data.uri;
// Get the form ID from the data-target attribute
id = obj.attr('data-target');
// URL to send to
url = this.site_url + uri + id;
// The form object
this.post_data(obj.serialize(),url);
// Hide Modal
obj.closest('.modal').modal('hide');
// Refresh
this.refresh();
}
This then figures out the correct route to ajax and calls a ajax call back inside the same class:
// AJAX post
this.post_data = function(obj,uri)
{
$.ajax({
data: obj,
dataType: 'json',
type: 'post',
url: uri,
headers: { "cache-control": "no-cache" },
cache: false,
success: function (response) {
if (response.success == true)
{
$("#alert_success .msg").html(response.message);
$("#alert_success").fadeIn(200).delay(2000).fadeOut(200);
}
else
{
$("#alert_error .msg").html(response.error);
$("#alert_error").fadeIn(200).delay(2000).fadeOut(200);
console.log(response.error);
}
}
});
}
I am then running another class callback to "refresh" the data in all the elements on the page:
this.refresh = function()
{
// Refresh the ajax requests
this.get_contact_data();
this.get_notes();
this.get_contact_log();
this.get_contact_tasks();
}
This class re loads the functions which run on page load to get the inial data into the tables/fields on the page. See "get_notes" below:
// Get notes
this.get_notes = function()
{
// Get all notes and populate table
var log_uri = this.site_url + "/contact/get_notes/" + this.contact_id;
this.get_data(log_uri,function(data) {
notes = $("#contact_notes ul");
notes.empty("");
// Populate the contact fields, assuming there is a result to play with
if (data != false) {
//alert(JSON.stringify(data));
$("#notes-tab .count").html("(" + data.length + ")");
$.each( data, function( key, value ) {
notes.append("<li class='list-group-item' modal-id='editNoteModal' data-target='" + value.ID + "'><div class='row'><div class='col-lg-3'><i class='fa fa-sticky-note mr-3'></i>" + value.timestamp + "</div><div class='col-lg-7'>" + value.note + "</div><div class='col-lg-2'><a href='#' class='edit mr-3'><i class='fa fa-edit mr-1'></i>Edit</a><a href='#' class='delete'><i class='fa fa-times mr-1'></i>Remove</a></div></div></li>");
});
console.log('Notes loaded');
} else {
notes.append("<li>There are currently no notes for this contact</li>");
}
});
}
Now the problem:
For some reason this does not update consistently in real time. The data is updated fine on the server side but on the client side the update/refresh does not always update. I might add a note and get a correct update response but the refresh method seems to be receiving the old data and always be one note behind. So the next time I add a note, the one I added before then appears and so forth.
Another problem I am experiencing is the methods seem to stack on each event so if I add one note (or one of the other methods) I will see the console say "notes loaded" but on the second note it says "notes loaded" twice, then on the 3rd note added 3 times and so forth.
I am sure there must be something fatal flaw in the design of my code here but I am not experienced enough with javascript/jquery to notice what direction I am going wrong so I can fix it.
I thought that this was an issue with ajax caching and not refreshing the result so I have adjusted the ajax request as cache none and also to send no cache headers. I am running in wamp.
In your case, your refresh code will always run before your data got updated. Because ajax is asynchronous so the code behind and below ajax will always execute nearly the time your ajax running.
At the time you run your post_data function to call the API, the refresh function got run too. So it's done before your data got updated.
You should run refresh function inside ajax callback. For example:
this.post_data = function(obj,uri, callback)
{
$.ajax({
data: obj,
dataType: 'json',
type: 'post',
url: uri,
headers: { "cache-control": "no-cache" },
cache: false,
success: function (response) {
if (response.success == true)
{
$("#alert_success .msg").html(response.message);
$("#alert_success").fadeIn(200).delay(2000).fadeOut(200);
}
else
{
$("#alert_error .msg").html(response.error);
$("#alert_error").fadeIn(200).delay(2000).fadeOut(200);
console.log(response.error);
}
callback();
}
});
}
And in modal_update, you pass refresh function to post_data as a callback:
this.modal_update = function(data)
{//
// Declare a few variables for the data object we've received
obj = data.obj // The form element to serialize
uri = data.uri;
// Get the form ID from the data-target attribute
id = obj.attr('data-target');
// URL to send to
url = this.site_url + uri + id;
// The form object
this.post_data(obj.serialize(),url, this.refresh);
// Hide Modal
obj.closest('.modal').modal('hide');
}
You should read more about asynchronous ajax. You can use other tricky solution is setTimeout to run this.refresh but I do not recommend that because you not sure when the update is done.
I'm a AJAX rookie, so bear with me. I'm trying to send data from a chat-message box to two places -- the actual chat box and to a rails method. That way I can display the meesage, and also store the message in my DB.
I have the following JS/HTML code
<button onclick="myFunction()" name="submitmsg" type="submit" id="submitmsg" value="Send">Try it</button>
<script>
function myFunction() {
var x = document.getElementById("frm1");
console.log(x);
var text = "";
var i;
for (i = 0; i < x.length ;i++) {
text += x.elements[i].value + "<br>";
}
document.getElementById("chatbox").innerHTML += text;
$.ajax({
url : "/messages/create",
type : "post",
data : { data_value: x }
dataType : "text" //this might be wrong?
});
}
</script>
I can successfully insert into the HTML DOM, but it isn't sending the data to the messages controller create action. My messages controllers is named messsages_controller.rb and the action is create.
I've added debugger in my create action in order to then view what params are, but it never even executes the code.
Some routes:
messages GET /messages(.:format) messages#index
POST /messages(.:format) messages#create
new_message GET /messages/new(.:format) messages#new
edit_message GET /messages/:id/edit(.:format) messages#edit
message GET /messages/:id(.:format) messages#show
PATCH /messages/:id(.:format) messages#update
PUT /messages/:id(.:format) messages#update
DELETE /messages/:id(.:format) messages#destroy
UPDATE
wait, something is wrong with my JS code. It was previously inserting HTML into the DOM, but somewhere along adjustments it stopped. Now the console is throwing the error new:110 Uncaught SyntaxError: Unexpected identifier line 110 is commented out.
When I the .ajax call out of the function, then it works fine. I have something syntactically wrong when I call the .ajax function inside myFunction()
$.ajax({
url : "/messages", //by rails convention doing a post simply to '/messages' should be handled by create action
method : "post",
data : { data_value: x },
dataType : "json", //this might be wrong?
success: function(response){
//do something,maybe notify user successfully posted their message
},
error: function(error){
console.log(error);
}
});
And in your create method you should handle json requests
def create
//save message
#message.save!
respond_to do |format|
format.json { json: #message.as_json }
end
end
This is how your code should look like. You can always do more creatively.
Please checkout this gist
I'm newbie with Rails
My purpose is insert song_id and title which received from Javascript via AJAX POST into Database (MySQL)
In my javascript file
var song_id = "23f4";
var title = "test";
$( document ).ready( function() {
jQuery.ajax({
url: 'create',
data: "song_id=" + song_id + "&title=" + title,
type: "POST",
success: function(data) {
alert("Successful");
},
failure: function() {
alert("Unsuccessful");
}
});
} );
In my editor_controller.rb
class EditorController < ApplicationController
def new
#song = Song.new
end
def create
logger.debug("#{params[:song_id]}")
logger.debug("#{params[:title]}")
#song = Song.new(song_params)
if #song.save
redirect_to root_path
else
flash[:notice_song_failed] = true
redirect_to root_path
end
end
private
def song_params
params.require(:song).permit(:song_id, :title)
end
The problem is when I running the Rails app with this code, the Console notices me that
ActionController::ParameterMissing at /editor/create
param is missing or the value is empty: song
I'm trying to use
private
def song_params
params.require(:song).permit(params[:song_id], params[:title])
end
but it doesn't work and notices me the same, moreover in the terminal log told me below
Started POST "/editor/create" for ::1 at 2015-04-01 01:07:23 +0700
Processing by EditorController#create as /
Parameters: {"song_id"=>"23f4", "title"=>"test"}
23f4
test
Completed 400 Bad Request in 1ms
Do I missed something in my code, Thanks for Advance.
You are not sending a song parameter at all. It looks like you need to update the data line in the jQuery.ajax call to include the song parameter like so:
data: {song: {song_id: song_id, title: title}}
This:
params.require(:song).permit(params[:song_id], params[:title])
is saying "require the 'song' parameter, and allow 'song_id' and 'title' through. If you don't pass a song parameter, you'll get a bad request.
You can either:
Change that line of code to remove the require on 'song'
or
Like #infused says, change your ajax call to send a song JSON object.
I am calling jQuery Ajax function, everything works fine.. except, it is not receving any response and appending it in.
When form is submitted.. beforeSend event is called and loading image successfully runs, and also there is an alert box with message 'Deleted', but the request and response from page is not appended.... in network tab of chrome, i can see message of selected post deleted... but its not appending in page.
$(document).ready(function() {
$("#post").submit(function() {
var post = $('#post').val();
var token = $('#token').val();
var str = 'token='+ token + '&post='+ post;
$.ajax({
type: "POST",
cache: false,
url: "http://localhost/delete.php",
data: str,
beforeSend: function(){
$("#post").html('<img src="http://localhost/loader.gif" align="absmiddle"> Deleting...');
},
success: function(msg) {
alert('Deleted');
$("#post").ajaxComplete(function(event, request, settings) {
$("#post").html(msg);
});
}
});
return false;
});
});
You're attaching a new event listener to #post after the AJAX query succeeds. Basically what you're saying is, "after this query succeeds, wait for another query to succeed and then change the HTML." Since the query has already succeeded, you need to remove ajaxComplete and simply use:
success: function() {
alert('Deleted');
$("#post").html(msg);
}
I am trying to store a token into a global var. When the alert is run it says null, but if I put 2 alerts one after the other the 1st shows null but the second shows the token.
Its like the token is not being set because the 1st alert is run before the ajax request has finished.
Does anyone have any ideas on what I am doing wrong?
var csrf_token = null;
$(document).ready(function(){
get_csrf_token();
alert('token 1 '+csrf_token);
alert('token 2 '+csrf_token);
});
function get_csrf_token()
{
$.ajax({
type: "GET",
url: "http://buscore/index.php/includes/csrf_token/",
dataType: "json",
success: function(resp, status) {
if (resp.status != 'success')
{
alert('Error - Update CSRF Token\n\n' + resp.status);
return;
}
csrf_token = resp.csrf_token;
}
});
}
Thanks
UPDATED
Ok thanks for your help everyone but still dont see how this would work. I use get_csrf_token() like jqgrid to send the token with the request like below. So how do I pass the token to and have it working?
beforeRequest: function (){
get_csrf_token()
//alert(csrf_token);
$("#customer_grid").setPostDataItem('<?php echo $csrf_token_name; ?>', csrf_token);
}
The success callback function runs when the HTTP response arrives.
In your test, the response is arriving between the time that the first alert is displayed and the time you click the button to let the script continue.
Do whatever you need to do with the data in the callback, not as the statement after the one where you initiate the Ajax request.
Example as requested by comment:
$(document).ready(function(){
get_csrf_token();
});
function get_csrf_token()
{
$.ajax({
type: "GET",
url: "http://buscore/index.php/includes/csrf_token/",
dataType: "json",
success: function(resp, status) {
if (resp.status != 'success')
{
alert('Error - Update CSRF Token\n\n' + resp.status);
return;
}
alert('token 1 '+csrf_token);
alert('token 2 '+csrf_token);
}
});
}
The A in AJAX stands for 'asynchronous'. While you are busy clicking on the first alert, the AJAX request is going through and the value is filled. You will need to place all code that needs the variable csrf_token into your callback function. Alternatively, you can look into using jQuery 1.5 or above (if you aren't already). It has so-called Deferred Objects
This API allows you to work with return values that may not be immediately present (such as the return result from an asynchronous Ajax request).
You can also set the async value on your post request tofalse, like this:
$.ajax({
type: "GET",
async: false,
url: "http://buscore/index.php/includes/csrf_token/",
dataType: "json",
success: function(resp, status) {
if (resp.status != 'success')
{
alert('Error - Update CSRF Token\n\n' + resp.status);
return;
}
csrf_token = resp.csrf_token;
}
});
This will make the browser wait for the response before proceeding with the rest of your code. I wouldn't necessarily recommend it, but it should work.
The AJAX request is async. That means the script doesn't wait for it to finish. When the first alert fires the token is not set. But until you hit OK it has time to load and the token will be set.
Here's the order of the operations:
call get_csrf_token
make token request
show alert 1
finish request and set csrf_token
client hits OK on the first alert
show alert 2 (the token variable was set at 4.)