Ajax request does not update database until page refresh - javascript

I'm making a ToDo list for a dashboard system I'm creating.
So the idea is that a user can add new ToDo items, delete ToDo items and finish/unfinish ToDo items. I'm working in this project with codeIgniter.
The problem is when I'm adding a task it is added to the database but when I delete it after that or finish it, it has not been updated in the database. Only when I refresh the page and delete the task or finish the task after that it is updated in the database. I have checked the data and that has been succesfuly sended to the controller and from the controller to the model. It just does not get updated in the Database for some reason.
I'm sending all data using AJAX post requests to the codeigniter controller.
$(document).ready(function () {
runBind();
function runBind() {
/**
* Deletes a task in the To Do list
*/
$('.destroy').on('click', function (e) {
var $currentListItem = $(this).closest('li');
var $currentListItemLabel = $currentListItem.find('label');
$('#main-content').trigger('heightChange');
$.ajax({
url: 'dashboard/deleteToDo',
type: 'post',
data: 'message=' + $currentListItemLabel.text()
}).success(function (data) {
$currentListItem.remove();
}).error(function () {
alert("Error deleting this item. This item was not deleted, please try again.");
})
});
/**
* Finish the to do task or unfinish it depending on the data attribute.
*/
$('.toggle').on('ifClicked', function (e) {
console.log("hallo");
var $currentListItemLabel = $(this).closest('li').find('label');
/*
* Do this or add css and remove JS dynamic css.
*/
if ($currentListItemLabel.attr('data') == 'done') {
$.ajax({
url: 'dashboard/finishToDo',
type: 'post',
data: 'message=' + $currentListItemLabel.text() + '&finish=' + false
}).success(function (data) {
console.log(data);
$currentListItemLabel.attr('data', '');
$currentListItemLabel.css('text-decoration', 'none');
}).error(function () {
alert("Error updating this item. This item was not updated, please try again.");
})
}
else {
$.ajax({
url: 'dashboard/finishToDo',
type: 'post',
data: 'message=' + $currentListItemLabel.text() + '&finish=' + true
}).success(function (data) {
console.log(data);
$currentListItemLabel.attr('data', 'done');
$currentListItemLabel.css('text-decoration', 'line-through');
}).error(function () {
alert("Error updating this item. This item was not updated, please try again.");
})
}
});
}
$todoList = $('#todo-list');
/**
* Add a new To Do task.
*/
$("#frm_toDo").submit(function (e) {
e.preventDefault();
var url = $(this).attr('action');
var method = $(this).attr('method');
var data = $(this).serialize();
$.ajax({
url: url,
type: method,
data: data
}).success(function (data) {
addItemToHTMLList();
$('#new-todo').val('');
}).error(function () {
alert("Error saving this task. This task has not been saved, please try again.");
});
});
/**
* Adds the task that has been created directly to the HTML page
*/
var addItemToHTMLList = function () {
$('.destroy').off('click');
$('.toggle').off('click');
var todos = "";
todos +=
"<li>" +
"<div class='view'>" +
"<div class='row'>" +
"<div class='col-xs-1'>" +
"<input class='toggle' type='checkbox'>" +
"</div>" +
"<div class='col-xs-10'>" +
"<label id='item'>" + " " + $('#new-todo').val() + "</label>" +
"</div>" +
"<div class='col-xs-1'>" +
"<a class='destroy'></a>" +
"</div>" +
"</div>" +
"</div>" +
"</li>" + $todoList.html();
$todoList.html(todos);
$todoList.find('input').iCheck({checkboxClass: 'icheckbox_flat-grey', radioClass: 'iradio_flat-grey'});
runBind();
$('#main').show();
}
});
It would be great if you can help me out because I have no clue. I have checked all the data but it just does not get updated in the database before the page refresh.

Have you compared the XHR requests using browser dev tools to ensure they are 100% equivalent (for a delete on an existing todo versus a delete on a newly added todo)?
Also, the typical pattern is to use some sort of id instead of using the whole message as the matcher -- have you considered having finish/delete operate on the id of the todo instead of sending the text of the todo? You can make a unique id if you do not want to expose your database ids.

The problem is that you are creating objects after the page has finished initializing and the events have already been attached. You need to instead assign the events to a parent element, so that this element delegates the event to any new items in the to-do. See the "Delegated Events" section in the jQuery docs: http://api.jquery.com/on/

Related

Async tooltip using JSON and kendo.template

I am struggeling with the KendoUI tooltip helper. Currently I am doing the following to get some tooltip information on a grid row:
$("#grid").kendoTooltip({
filter: 'td:nth-child(10)',
content: function (e) {
var template = kendo.template($("#myToolTipTemplate").html());
var dataItem = $("#grid").data("kendoGrid").dataItem(e.target.closest("tr"));
var tooltipHtml;
$.ajax({
url: DetailsURL + "/" + dataItem.Id,
async: false
}).done(function (data) { // data.Result is a JSON object from the server with details for the row
if (data.Success) {
data.Result = data.Result.replace(/null/g, "\"N/A\"");
tooltipHtml = template($.parseJSON(data.Result));
} else {
tooltipHtml = "Ooops!<br>Something went wrong (" + data.Result + ")";
}
});
return tooltipHtml;
}
});
I would like to get rid of the synchronous ajax call and make it asynchronous. I saw some asynchronous examples where the server delivers the full html, but nothing that works with JSON data from the server, that is then "compiled" via a kendo.template() to html on the client. Any suggestions how to do this?
Set the content of the tooltip to be a placeholder value (e.g.
"Loading..")
Listen for the "Show" event of the tooltip.
When the show event is triggered, start the request for JSON from the server
In the 'done' callback, execute the template, and replace the content of the tooltip with the new html in the 'done' callback
$("#ID").data("kendoTooltip").popup.wrapper.find(".k-tooltip-content").html("........");
Telerik helped me here. And, as often, it's easier than guessed..
$("#grid").kendoTooltip({
filter: 'td:nth-child(10)',
content: function (e) {
var template = kendo.template($("#myToolTipTemplate").html());
var dataItem = $("#grid").data("kendoGrid").dataItem(e.target.closest("tr"));
var tooltipHtml;
$.ajax({
url: DetailsURL + "/" + dataItem.Id,
async: false
}).done(function (data) { // data.Result is a JSON object from the server with details for the row
if (data.Success) {
data.Result = data.Result.replace(/null/g, "\"N/A\"");
tooltipHtml = template($.parseJSON(data.Result));
} else {
tooltipHtml = "Ooops!<br>Something went wrong (" + data.Result + ")";
}
// set tooltip content here (done callback of the ajax req)
e.sender.content.html(tooltipHtml);
});
}
});

Append the last message once

Hello guys i am trying to build a chat with Jquery , php , ajax and mysql
the problem that i am facing since few days is that when i get the value of the last message its keep getting append to the div what i want is to append the last message only once , and append again if there is a new message here is my ajax call
var chat = "";
$.ajax({
url: "php/gt_user.php",
type: "get",
success: function (result) {
var gtUser = $.parseJSON(result);
$.each(gtUser, function (idx, obj) {
var usrApp = "<span><i class='fa fa-user-circle-o' aria-hidden='true'></i>";
usrApp += "<p class='usr-name'>" + obj.Tables_in_chat + "</p></span>";
$('.userarea').append(usrApp);
}); // here i get all the username who sent a message and print them on a div
$('.userarea span').on('click', function () {
$('.msgarea').html("");
var usrName = $(this).text();
$('#usrname').text(usrName);
setInterval(function () {
$.ajax({
url: "php/admin_msg.php",
type: "post",
data: {
name: usrName
},
success: function (result) {
var lastmsg = result;
function appedn() {
var usrMsg = "<div class='usr-msg'><i class='fa fa-user-circle-o' aria-hidden='true'></i>";
usrMsg += "<span><p>" + lastmsg + "</p></span></div>";
$('.msgarea').append(usrMsg);
}
if (chat !== result) {
appedn();
} else {
chat = result;
}
}
});
}, 2000);
});
}
});
the respanse from php/admin_msg.php is working and i got the last message sucessfully the problem is that this script keep adding the same message to the message area , and what i want is to added the message only once if there is a new one
You need to somehow identify last message that is already appended to your html the best would be some id sent from server. So your message div should containt some data-id attribute, and then when you ask for next message get last children of $('.msgarea') element, read it data-id and compare with current one.
Another thing I would recommend to moving to some view library or framework, react, angular, vue or whatever. It gets complicated when you want to manage such features with pure jQuery.
i was finally able to fix the problem after 1 day of struggle so will post the answear here just in case it will help some one else facing the same issue
the part where i had to get all the username table from database i move it to my HTML and used a few line of php to echo the result like this(each user name has his own table)
// show all the user name that sent a message
$result = $con->query("show tables from chat");
while($row = mysqli_fetch_assoc($result)){
echo "<span><i class='fa fa-user-circle-o' aria-hidden='true'></i><p class='usr-name'>".$row['Tables_in_chat']."</p></span>";
}
then on my jquery script i moved the function that check for the last message every 2sec outside the click event so my Jquery script look more cleaner now
/* get the user name and added it to the header of the message box */
$('.userarea span').on('click', function () {
$('.msgarea').html("");
var usrName = $(this).text();
$('#usrname').text(usrName);
});
var chatdata = "";
/* check for new message and append the message area if there is a new one */
setInterval(function () {
var usrName = $('#usrname').text();
$.ajax({
url: "php/admin_msg.php",
type: "post",
data: {
name: usrName
},
success: function (result) {
function appedn() {
var usrMsg = "<div class='usr-msg'><i class='fa fa-user-circle-o' aria-hidden='true'></i>";
usrMsg += "<span><p>" + result + "</p></span></div>";
$('.msgarea').append(usrMsg);
}
if (chatdata !== result) {
appedn();
chatdata = result;
}
}
});
}, 2000);

How to have a same duplicated div structure but parsing a different xml data in each div

I am making some application that it loads data from an xml file. it works file if there is one corresponding div structure and one xml path. But I want to have multiple copies of my div structure, but each one will load different xml content.
I tired to do it by loop but it does copy each data in both content.
JSFIDDLE: https://goo.gl/8XwMYz
HTML:
<div class="data" data-xml="https://dl.dropboxusercontent.com/u/33538012/file1.xml">
</div>
<div class="data" data-xml="https://dl.dropboxusercontent.com/u/33538012/file2.xml">
</div>
jQuery:
$(".data").each(function() {
var path = $(this).attr("data-xml");
$.ajax({
url: path,
dataType: "xml",
success: parse,
error: function() {
alert("Error: Something went wrong with loading the playlist!");
}
});
});
function parse(document) {
$(document).find("person").each(function() {
$(".data").append(
"<div class='name'>Name: " +
$(document).find("name").text() +
"</div><div class='title'>Title: " +
$(document).find("title").text() + "</div>")
//$(document).find("name").text();
});
}
As you can see in the HTML I have exactly the same structure but each one are linked to a different xml file paths., an in my code I want to load the corresponding data based on the xml file they are linked to.
UPDATE:
Based on the answer #charlietfl has provided, the code seems better now, but still does not provide the intended result. I have been testing on the below code, and realised that it does not pass the xml instance to the parse function.
$(".data").each(function() {
// store element instance
var elem = $(this);
var path = $(this).attr("data-xml");
//console.log($el);
$.ajax({
url: path,
dataType: "xml",
success: function(xml){
parse(document, elem);
},
error: function() {
alert("Error: Something went wrong with loading the playlist!");
}
});
});
function parse(document, elem) {
console.log($(document).find("name").text());
$(document).find("person").each(function() {
//alert($el);
var $person = $(this);
elem.append(
"<div class='name'>Name: " +
$person.find("name").text() +
"</div><div class='title'>Title: " +
$person.find("title").text() + "</div>")
});
}
Any idea?
This should do it. You need to store the instance of element outside the ajax and pass that into the success handling
$(".data").each(function() {
// store element instance
var $el = $(this),
path = $(this).attr("data-xml");
$.ajax({
url: path,
dataType: "xml",
success: function(xml) {
parse(document, $el);
},
error: function() {
alert("Error: Something went wrong with loading the playlist!");
}
});
});
function parse(document, $el) {
$(document).find("person").each(function() {
var $person = $(this);
$el.append(
"<div class='name'>Name: " +
$person.find("name").text() +
"</div><div class='title'>Title: " +
$person.find("title").text() + "</div>")
});
}

jQuery AJAX queue checkbox filters and send request to server

Hi I am creating a site using Laravel, jQuery & AJAX. I have multiple checkbox filters on a page that is sent to the server using AJAX and the results are filtered on the front end of the website. Now the problem I have is that everything a checkbox is changed a request is sent to the server; which I want to amend. I want to instead queue this in an array or something similar so that I can send it to the server every minute or perhaps when the last request has finished. But I'm not entirely sure how I would do this.
This is the code I have so far;
$('#filters input[type=checkbox]').click(function(e) {
console.info('Thank you for selecting "' + $(this).attr('value') + '"');
filters.update('/index/filter',$('#filters :input').serialize(), '&offset=0', true);
});
a typical filter looks as follows;
<input type="checkbox" id="tag_982" name="region[]" class="essex checkbox form-filters" value="Essex" data-name="Essex">
and the request is sent as follows;
var filters = {
update: function(url, data, offset, reset) {
var count = '&count=40';
if (typeof offset === 'undefined') {
data = data + count;
} else {
data = data + count + offset;
}
$('.loading-icon').fadeIn();
$('#adverts').addClass('loading');
$.ajax({
url: url,
async: true,
dataType: 'json',
data: data,
type: 'POST',
success: function(json) {
console.log('Adverts successfully loaded');
$('.loading-icon').fadeOut();
$('.append-data').html(json.data.viewData);
$('#adverts').removeClass('loading');
$('.info-num').html(json.data.offset + ' of ' + json.data.total + ' adverts');
if (json.data.offset >= json.data.total) {
$('#load-more').children('a').text('All adverts loaded').contents().unwrap();
} else {
$('#load-more').children('a').text('Show more adverts');
$('#load-more').children('a').attr('href', json.data.offset);
}
} // end success
}).done(function() {
}); //end ajax
}, //end update function
} //end var filters
Does anyone have any ideas how this can be achieved? I'm looking for some basic examples.

Upon querying a database, delete an item from a list obtained via getJSON

I have a list of items obtained upon querying a database. Result of the query is treated with jsonifyand finally obtained via getJson, by doing the following:
$(function() {
$.getJSON($SCRIPT_ROOT + '/appointments/', function(data) {
var output="<ul>";
for (var i in data.appts) {
output+="<li>" + data.appts[i].labo + "</li>"
}
output+="</ul>";
$("#result").html(output)
return false;
});
});
So far so good...
Now I need to give the possibility to delete each of the above listed items, by calling (for example ) the following Flaskfunction:
#app.route('/appointments/<int:appointment_id>/delete/', methods=['DELETE'])
def appointment_delete(appointment_id):
appt = db.session.query(Appointment).get(appointment_id)
db.session.delete(appt)
db.session.commit()
return jsonify({'status': 'OK'})
Unfortunately I have no clue on how it's possible to bridge these two pieces of code. Since I've being struggling on that for a while, I would appreciate any help that will allow me to get out of the mud... Thanks a lot.!
EDIT according to #dcodesmith's comment
The getJSON response:
{
"appts":[
{
"id":1,
"day":"Mardi",
"labo":"l1",
"modified":[
"21/01/2014"
],
"groups":"5",
"plage_h":"10h00",
"sem":"5",
"start":[
"28/01/2014"
]
},
{
"id":4,
"day":"Vendredi",
"labo":"l1",
"modified":[
"22/01/2014"
],
"groups":"5",
"plage_h":"10h00",
"sem":"5",
"start":[
"31/01/2014"
]
}
]
}
Changes required
Firstly, edit your output HTML to include an anchor tag which should have a data-id attribute with the appts id assigned to it.
Create a click event on the anchor tag in your list of appts
Code
$(function() {
$.getJSON($SCRIPT_ROOT + '/appointments/', function(data) {
var output = "<ul>";
for (var i in data.appts) {
var appt = data.appts[i];
output += "<li>" + appt.labo + "delete</li>"
}
output+="</ul>";
$("#result").html(output)
return false;
});
$(document).on('click', 'a.delete', deleteAppt);
function deleteAppt(e){
e.preventDefault();
var $this = $(this),
id = $this.data('id'),
url = "/appointments/" + id + "/delete/";
$.ajax({
url: url,
type: 'POST',
data: {id: id}
})
.done(function(data, textStatus, jqXHR){
if (data.status === 'OK'){
// if successful remove deleted row
$this.parent('li').remove();
}
})
.fail(function(jqXHR, textStatus, errorThrown){
//log your error here, if any is caught. This will be very helpful for debugging
})
}
});
Note: I know nothing about Flask, but this should work Ceteris Paribus

Categories