window.history.pushState the pages do not update - javascript

I am using window.history.pushState() to change the url of the page and put it in the history list, everything works but I have a problem, if for example in a page I execute an operation (ajax), which changes the values ​​in the db and textually update a part of the page, if I browse elsewhere and return to this page, I find what was originally there and not the changes made, to see them correctly I have to refresh the page.
I don't currently use any caching systems
Some contents are loaded with ajax others are directly on the page
window.history.pushState() is used only in the home page in the others I don't need it even if it happens on all
in the example page I have this code
function init() {
$('#weekDays').on('show.bs.modal', function(event) {
var modal = $(this);
$.ajax({
type: 'post',
cache: false,
url: '/my_account/get_giorni_chiusura_sett',
dataType: 'html'
}).done(function(data) {
modal.find('.modal-content').html(data);
});
});
$('body').on('click', '#save-closing-days', function() {
var dataString = $('#form-weekdays-close').serialize();
$.ajax({
type: 'post',
cache: false,
url: '/my_account/set_giorni_chiusura_sett',
data: dataString,
dataType: 'json'
}).done(function(data) {
if (data.update === 'ok') {
var daysClose = $.map(data.giorni, function(v) {
return '<strong>' + v + '</strong>';
}).join(' - ');
$('#list-days-close').html(daysClose);
$('#weekDays').modal('hide');
}
});
});
}
when I arrive in the page the content is loaded without ajax and generated by php, the first function loads the content in the modal upon opening, the second one saves / updates the data on the database and updates the text on the DOM
Closing days: Saturday - Sunday
Update and become
Closing days: Sunday
Now I move to other pages from the menu and back, but I find it again:
Saturday - Sunday
If I reload the page, the data is updated

The History API doesn't maintain the state of the DOM for you. You need to do that yourself. MDN has a good guide but the short version is:
When the user clicks a link then your JS should prevent the default behaviour and call pushState to change the URL and use DOM methods to update the page to match what the server would send for that URL.
When the user presses the back button in their browser and a popstate event fires then your JS should read the URL (and state data if applicable) from the event and using DOM methods to update the page to match what the server would send for that URL (i.e. undoing the changes from the previous paragraph).

Related

Ajax request within partial view loaded through another Ajax request does not work properly in IE 11

Following is the exact scenario in my ASP.NET MVC application:
The parent page is having 3 tabs, and following javascript is written to bind click event to each of the tabs:
Each function invokes a controller action (specified in the data-url attribute), and renders the result in the partial view which is expected to be displayed within "ContactMainContainer" div.
jQuery(document).ready(function () {
$('#ContactTabs a').on('click', function () {
var dr = $(this).closest('li');
var url = $(this).attr("data-url");
if (url != undefined && url != '') {
var projectDetailTabModel = $("#ContactID").val();
$('#successDiv').hide();
$('#errorDiv').hide();
$.ajax({
type: "POST",
url: getUrlWithTabId(url),
data: projectDetailTabModel,
success: function (result) {
$('#ContactMainContainer').html(result);
},
error: function (errMessage) {
if (errMessage != null && errMessage.length > 0) {
$("#errorDiv").show();
$("#errorText").html(errMessage);
}
}
});
}
});
});
Contents of one of the partial view is built using javascripts (mostly ajax calls). (I am unable to put the whole javascript here as it is a client project and confidentiality agreement, and the javascript library is too large to place here).
The issue is that when a user navigates to that particular tab (having Ajax call), it takes a long time to execute and render the result. But after that if user clicks on any other tab the browser stucks and hangs for infinitely.
This issue is only in IE11, and works very well in all other browsers (Chrome, firefox, and all).
Could anyone please suggest what could be the reason?
It's a caching issue and IE is well known for caching. You need to make sure in your Ajax call to set the catching as false
Setting the cache property in an AJAX call
$.ajax(url, {
dataType: 'json',
cache : false,
//Other things ...
}
I prefer to use cache buster in the request URL, that is adding the current timestamp as parameter, so that it cant be cached

window.location.reload(true) not reloading the page correctly

I have a PHP page which fetches data from a MYSQL database and generates HTML content based on rows returned from the database.
I am adding a new row in database on click of a button using AJAX, Jquery and PHP. After adding the new row, I am using window.location.reload(true); to reload the page. But the HTML elements corresponding to new row are not shown when I click the button. However, if I manually refresh the page using F5, the newly added content is shown.
Anyone knows why this could happen?
Below is the function which I call on click of a button. The page increaseCount.php updates database to increase the count of actors. But the HTML elements corresponding to new count are not shown until I refresh the page using F5.
function increaseCountOfNewActor(characterName) {
var actorName = document.getElementById("txt_actor_"+characterName).value;
var actorImage = document.getElementById("img_actor_"+characterName).src;
$.ajax( {
url: "increaseCount.php",
method: "POST",
data: {
name: actorName,
image: actorImage,
character: characterName
},
success: function( data ) {
alert("Vote received");
}
} );
window.location.reload(true);
}
The problem is that you are mixing ajax with a complete page reload.
The $.ajax call by default is asynchronous (the first a from ajax...). Therefore it sends a request to increasepostcount.php and then immediatelly reloads the page - not waiting for increasepostcount.php to process the request. By the time you manually refresh the page, increasepostcount.php will have completed the processing of the ajax call, therefore its result are reflected on the page.
If you use ajax, you should not use page reloading. Use javascript to update that part of the page where these records are displayed based on the results returned by the ajax call.
You need to be sure that the ajax call has done to do what you want, in your case "window.location.reload(true);" is running before the ajax response, due to asynchronous communication between Client and Server to avoid "freezing" on the screen and an unresponsive user experience.
You have to put your refresh code on Success ajax response or on done :
function increaseCountOfNewActor(characterName) {
var actorName = document.getElementById("txt_actor_"+characterName).value;
var actorImage = document.getElementById("img_actor_"+characterName).src;
$.ajax( {
url: "increaseCount.php",
method: "POST",
data: {
name: actorName,
image: actorImage,
character: characterName
},
success: function( data ) {
alert("Vote received");
// to do here
//window.location.reload(true);
}
} ).done(function () {
// or to do here
window.location.reload(true);
});
}
in your page increaseCount.php consider adding a header at the end.
For example:
if(isset($_POST['name'] &&
isset($_POST["image"] &&
isset($_POST["character"]) {
/* do your stuff here */
header("Location: /thePageYouWantToRefresh.php");
exit;
}

How to store/remember the data fetched from ajax call?

I'm retrieving some data into a JSON array, then display it into an HTML table which contains some data enclosed within hyper links. i.e. a couple of the columns' data are clickable, once clicked it displays another JSP page (say page #2) with some more data which was kept on the JSON array itself.
Now this page 2 has a 'Back' button functionality - the expected behavior is when user clicks the 'Back' button it should go back to page 1 where the HTML table data was displayed and user should be able to see the data which they first fetched too. i.e. there should be some way to remember the data fetched from my initial AJAX request and retrieve the same data which user fetched in page 1 when they go back to that page from the child page#2.
Th AJAX call is triggered when user enters an account# and the type of account - I fetch data accordingly and get the result in the 'response' object and neatly display it on html table, but after user moves from that page and again hits the back button I see the page#1 without the table. Now again I cannot ask the user to re-enter the details to see the data that they retrieved earlier. It's pretty annoying.
Please give me a solution to this problem. Thanks All.
Appreciate for taking time to read this.
Here's a part of the code:
$(document).ready(function () {
var flag = "1";
$('#accountType').bind('change', function (event) {
var accountType = $('#accountTypeSelect').val();
var account = $('#accountText').val();
jQuery.ajax({
type: 'POST',
url: '${pageContext.request.contextPath}' + "/Page1.spr", //request page
cache: false,
dataType: "json",
data: {
"accountType": accountType,
"account": account,
"flag": flag
}, //data sent to request page
success: function (response) {
// code to display the data into the html table
},
error: (function (message) {
console.log("error message : " + message);
}),
statusCode: {
404: function () {
alert("page not found");
}
}
});
});
You can save the data in HTML5 sessionStorage or localStorage using the setItem method as follows:
success: function(response) {
sessionStorage.setItem("result", response)
// code to display the data into the html table
}
And access it later using the getItem() When you come back to the page like
var prevResponse = JSON.parse(sessionStorage.getItem("result"));
if(prevResponse)
{
// code to be executed when old dats is found
}
else{
}
Ideally you code in first pages load will be something like
var prevResponse = JSON.parse(sessionStorage.getItem("result"));
if(prevResponse)
{
// data exists : code to be executed when old dats is found
}
else{
jQuery.ajax({}) // send the AJAX request to fetch data
}
You can read more about session and local Storage here
Browser support for web storage API.
Update
If you don't have HTML5 support, you could use jQuery cookie plugin (There are plenty of others as well) for storing data at client side.
You can store data into a cookie as follows:
$.cookie("result", response);
Then to get it from the cookie like:
$.cookie("result");
You maybe can use cookie via jquery. But user have to enable the browser's cookie. It usually enabled by default setting.
To add:
$.cookie("key1", data1);
$.cookie("key2", data2);
To read:
$.cookie("key1");
To delete:
$.removeCookie("key1");
So, you can try to read cookie to load table data, if no data, call ajax:)
Another way is to save it in a hidden input:
success: function(response){
$("#hiddenInput").val(JSON.stringify(response));
}

Ajax request 'onError' handler

There is one feature on my site: delete without page refresh. The user just presses 'delete' and the browser will send Ajax-request. It will load 'delete' script with id parameter.
All work well. But it is not very good because of referential integrity of the database. For example, It is possible to delete street, where some people are living.
I want to upgrade my script. I want to add a check to delete script and don't let delete data if some 'people' are connected to 'street' table.
jQuery handler of button click:
$('body').on('click', '.deleteStreet', function()
{
var id = $(this).attr('id');
var hideMe = $(this).parent().parent();
var dataString = 'id=' + id;
if(confirm("Are you sure you want to delete street? It is possible some people living there!"))
{
$.ajax({
type: "GET",
url: "/index.pl?mode=streets&action=delete",
data: dataString,
cache: false,
success: function(e)
{
hideMe.hide();
}
});
return false;
}
});
It will call script anyway and now will delete data anyway. I can add some checks to delete script now and it wouldn't delete, but jquery script would work anyway and will hide table row anyway (because request was send ok, without 404, etc)
1) Is it possible to see delete script result and hide or not hide row depending on it? For example, it will return true or false, js script will catch it and show message about deleting or not deleting of data depending on it.
2) This problem caused by structure of my site. There are some switches on index.pl and load appropriate scripts loading depending on query (mode=street then load street.pl, mode=user then load users.pl etc). So it will show all data loaded before delete.pl script and it will be impossible to check script returned true or false.
Any help? :) Thank you!
P.S.: I am very sorry for my awful english.
You can have the result of your ajax call in the first parameter of the success callback. ex:
$.ajax({
type: "POST",
url: "/index.pl?mode=streets&action=delete",
data: dataString,
cache: false,
success: function(e)
{
if(e === '1'){
hideMe.hide();
}
}
});
try to log your result in the console for tests: console.log(e).
For deleting data you should use a POST request ( or DELETE but not supported by all browsers).
I dont know how your datas (streets) looks like but an other way could it be to return all your existing streets in a json object on the delete request result. And refresh all lines.

Using the value recieved from within a click handler that is inside a ajax request outside the function

It was suggested that I try to explain my problem with no code so here it goes. I have a webpage that lists a bunch of links with project names as seen in this jsfiddle. What I want to do next is display a second webpage after a project link is clicked by a user. The second webpage would need to make a second ajax request like in this Second page jsfiddle to get new information to display a project summary, citations and names for that particular project. The part that's killing me is the ajax request for the second page currently has a number 504216b6e4b04b508bfd333b in the url which means it will only use that project for the second page to display summary, citations and names. I need that ajax request to take a variable for any id number. However to compound the problem the id number comes from a user clicking a link on the first page. So my problem is getting the value of the id once a link is clicked and putting it into the ajax request for the next page. I have all the work done for what the pages will display but I can't get the value from the one file to the next. Any help is appreciated, Thanks.
wouldn't let me save without putting some code so this is just the bare bones,
// The ajax request is in another file but it works good
promise.done(function (json) {
// Make some links
// Which link was clicked? I need to see some id please
$('#sbItems a').on('click', function (e) {
e.preventDefault();
// Do stuff to find the id for the link the user clicked
// Assign the id to a variable that I can use in the next ajax request
// that is called in a seperate file
testId = json.items[itemId].id;
}); // END Click event
}).fail(function() {
alert("Ajax call failed!");
});
second file has,
// Need to somehow, someway get the testId variable that holds the id
// into this file
var url = 'https://www.sciencebase.gov/catalog/item/ + THE TESTID + ?format=
jsonp&fields=relationships,title,body,contacts';
$.ajax({
type: 'GET',
url: url,
jsonpCallback: 'getSBJSON',
contentType: "application/json",
dataType: 'jsonp',
complete: onComplete,
success: function(json) {
// Display some stuff based off this url
}
});
If you're trying to get a number from the first page and into the second page when you click a link that takes you to the second page so you can use it in the second page ajax call, then there are several options:
Attach the value onto the URL when requesting the second page as a search parameter like this: http://www.sample.com/mypage?id=504216b6e4b04b508bfd333b. The in the second page, parse that id value out of the URL and use it for your ajax call. This is the safest of these three options because it works properly even if the user has multiple windows open clicking on different pages in your site.
When clicking on the link in the first page, store the id value as a cookie. In the second page, retrieve the id from the cookie.
Same as option 2, but store the value in local storage.

Categories

Resources