I've been searching for a solution for a couple of weeks now to no avail.
My web application uses Spring/Hibernate. When I make an AJAX call to retrieve data for my table(using Datatables), everything show up fine. However, when I click on a link and then click BACK to return to the table, IE and Firefox seem to behave differently :
FIREFOX :
Display table page (AJAX call);
Click link to go to new page;
Click Back to return to table page;
Database DAO NOT called to re-display data
INTERNET EXPLORER :
Display table page (AJAX call);
Click link to go to new page;
Click Back to return to table page;
Database DAO IS called to re-display data
Why is this happening and how can I fix this ? Basically I'd like IE to behave like Firefox in this particular scenario.
Sample code (JSP):
$('#tableWithData').DataTable( {
serverSide : false,
ajax: {
"url": "/app/search/rowData",
"data": function ( d ) {
d.searchDeptlCntnrNo = $('#criteriaDeptlCntnrNo').val();
d.searchCntlNoCd = $('#criteriaCntlNoCd').val();
d.searchExactMatch = $('#criteriaExactMatch').val();
d.searchCntlNoCmpnt1 = $('#criteriaCntlNoCmpnt1').val();
d.searchCntlNoCmpnt2 = $('#criteriaCntlNoCmpnt2').val();
d.searchCntlNoCmpnt3 = $('#criteriaCntlNoCmpnt3').val();
d.searchCntlNoCmpnt4 = $('#criteriaCntlNoCmpnt4').val();
d.searchRangeField = $('#criteriaRangeField').val();
d.searchCntlNoCmpntQty = $('#criteriaCntlNoCmpntQty').val();
d.searchCntlNoCmpntRng = $('#criteriaCntlNoCmpntRng').val();
}},
stateSave: true,
pagingType: "full_numbers",
deferRender: true,
scrollY: 400,
scrollCollapse: true,
scroller: true,
lengthChange: false,
"columns": columns,
language: {
"loadingRecords": loading data..."},
fnInitComplete: function(oSettings, json) {
$("#loading-div-background").hide();
},
language :{
"emptyTable": "Your query returned 0 results."
}
} );
EDIT :
This would be a BFCache issue and since I use JQuery and it has an embedded onload event, Internet Explorer cannot retrieve the cache ? https://stackoverflow.com/a/1195934/1501426
For anyone having the same problem, here is what I've found :
This is an IE issue with jQuery and Internet Explorer :
jQuery automatically attaches an unload event to the window, so
unfortunately using jQuery will disqualify your page from being stored in > the bfcache for DOM preservation and quick back/forward.
https://stackoverflow.com/a/1195934/1501426
It looks like I'm stuck with this. For now, I will open a new window when the user clicks a link but IMO, that's a bad design.
Related
I'm using Inertia/Laravel/VueJs. I have a page with many posts and each post can be marked as completed. When a post is marked as completed on the front-end I have a v-bind which toggles a CSS class which should be applied to completed tasks.
The behaviour I would like is: a user scrolls down a page, clicks the completed button, and the back-end sends that newly updated data to the front-end, making the v-bind true, causing the CSS class to be applied without jumping to the top of the page.
With the code below I can click the completed button, and it is updated in the database, but that new data isn't sent to the front-end.
Controller:
public function markAsCompleted(Request $request)
{
$post = Post::find($request->id);
$post->completed = true;
$post->save();
return Redirect::route('posts');
}
Javascript function called at click of completed button:
completed(id) {
this.completedForm.put(`/endpoint/completed/${id}`, {
preserveScroll: true
});
},
If I change the Javascript function to:
completed(id) {
this.completedForm.put(`/endpoint/completed/${id}`, {
preserveScroll: true,
onSuccess: () => {
Inertia.get('posts');
},
});
},
In this case, the new data is returned to the front-end with the post being marked as completed, but the preserveScroll doesn't work, and jumps the user to the top of the page.
Any ideas on how to get my desired use case working? Users could have hundreds of posts so I can't have the page jump up to the top every time.
Thank you for any help!
To update your app while preserving the state:
Inertia.get('posts', params, {
preserveState: true,
})
One way, not the cleanest, but it is a solution. Just click "Completed Button" to send a request to the backend, and ONLY to check if the response is success, then update that task in frontend as complete. So you just update (add class) this element and you don't rerender whole DOM. Because, if you get success response, thats done in the backend for sure.
I have loaded my JQuery and Datatables code correctly into the page. My data is loaded from the sAjaxSource option in the Datatables initialisation function.
I am loading buttons into the cells that have classes and IDs that the should allow JQuery to fire functions when clicked. As the Datatable uses pagination, only the first page works, as I load the JQuery click function as a function call once the Datatable has initialised (using fnInitComplete).
I suffered a previous issue and realised that I had to load the data into the HTML before initialising the Datatable, and all calls to the JQuery click function worked, but that was using HTML table data, not data from an Ajax Source.
In short, my JQuery click functions aren't running on elements loaded into the table through AjaxSource. (FYI, my click functions are trying to reload different data into the table, and after the first reload, no click events work at all, so I am worried that my second issue will be getting the click events to run after that too). My code is below.
<script src="fnReloadAjax.js"></script>
<script>
$(document).ready(function() {
//Any table related events need to go in here so that it initialises post data load
function tableInit() {
$('.myButton').click(function() {
oTable.fnReloadAjax('mySource2.php');
});
}
var oTable;
oTable = $("#taskTable").dataTable({ bSort: true,
"bProcessing": true,
"sAjaxSource": 'mySource1.php',
bAutoWidth: true,
"iDisplayLength": 5, "aLengthMenu": [5, 10, 25, 50, 100], // can be removed for basic 10 items per page
"sPaginationType": "full_numbers",
"aoColumnDefs": [{ "bSortable": false, "aTargets": [-1, 0]}],
"fnInitComplete": function(oSettings, json) {
tableInit();
}
});
});
</script>
Jquery's traditional event handling doesn't work for dynamically added content. You should use delegated events. Instead of this :
function tableInit()
{
$('.myButton').click(function() {
oTable.fnReloadAjax('mySource2.php');
});
}
you should do this :
function tableInit()
{
$('anyParentSelector').on('click','.myButton',function() {
oTable.fnReloadAjax('mySource2.php');
});
}
Note that I did put "anyParentSelector" , it could be body or even document, but best-practices advises it to be the most direct static parent of your dynamically created .myButton elements. This for performance reasons...
Im trying to work form editing with autocomplete .. its source is different every time user opens edit form
when opening edit form :
beforeShowForm: function(frm) {
var id = grid.jqGrid('getGridParam','selrow');
if (id) {
var ret = grid.jqGrid('getRowData',id);
AccCode = ret.szAccCode;
};
$.post("url_getchildren", { szAccCode: AccCode}).
done(function(data) {
lschildcode=data;
});
},
i have managed result from server,
but i cant send it to grid.
colModel :
{name:'szAccParentCode',index:'szAccParentCode', editable:true, edittype:'text',
editoptions : {
dataInit: function(elem){
$(elem).focus(function(){
this.select();
}),
$(elem).autocomplete({
source:lschildcode
})
}
}
},
why i cant pass lschildcode to autocomplete's source? and autocomplete kept sending term to server every time i type in the box.
TIA
I think that dataInit (and so autocomplete) will be called before done of the $.post will be executed.
To fix the problem you can for example call $("#szAccParentCode").autocomplete({source:lschildcode}) inside of done.
Another way: one can use URL as the value of source. The URL can contains some additional parameters. If you need use HTTP POST you can declare source as function and call response parameter (callback function) inside of success or done of your source implementation. Just look at the implementation of source in the remote with caching example and examine the code (click on "view source") or examine the source code of jQuery UI Autocomplete near $.ajax usage (see here).
EDIT: I have abandoned the conditional structure and just create the window fresh each time. That works. Still wondering whether refresh() works with urls though.
I have a conditional structure that resembles this one:
What is the proper way to load new content into a kendo window?
If the kendo window already exists, refresh() the window rather than create it anew.
The difference is, I'm using an iframe with url.
The problem: I set a different query string with setOptions before invoking refresh(), but the original url is being requested from the server again.
if (!kwindow) {
kwindow = $("#messagewindow").kendoWindow({
iframe: true,
width: "400px",
height: "600px",
title: "original title",
content: "foo.htm?id=1",
type: "GET"
}).data("kendoWindow");
}else {
kwindow.setOptions({
iframe: true,
type: "GET",
title: aDifferentTitle,
url : "foo.htm?id=2"
});
kwindow.refresh();
}
kwindow.open();
I know the the setOptions method is passing the options to the kendo window because the titlebar of the window correctly shows aDifferentTitle. However, looking at the network traffic monitor, the url requested from the server is foo.htm?id=1 but it should be foo.htm?id=2.
I cannot see what is wrong with my code and would be grateful if someone could point out the error to me.
The answer you were looking for was
kwindow.options.content.url = url;
Then the refresh icon / methods will work on the new url
To refresh from different URL you need to pass this through an option object to the refresh method (you do not need to use setOptions). Here is snippet from the documentation:
var windowObject = $("#window").data("kendoWindow");
windowObject.refresh("/feedbackForm");
windowObject.refresh({
url: "/feedbackForm"
});
I used the following and it seems to work in an MVC project:
window.setOptions({
title: "New Title"
});
window.refresh({
url: "/ControllerName/Action"
});
window.open();
At work I have been tasked with adding additional functionality to an existing MVC 3/Razor project. I haven't used MVC before, but am quite versed with Web Forms.
However, I am not quite sure where to place everything I need.
When the app is first loaded, a login page appears. When the user logs in successfully, the user sees a dashboard type page.
The new functionality is to detect whether the user has FollowUpItems with a Due Date < Now. If Count > 0 then display a Modal popup with some text and a link to 'View Followup Items'.
There is already a controller and action made for viewing Followup items. I need to display the modal, and I would like to make the modal a reuseable type of object - I am assuming/thinking a PartialView where I can pass in the name of the Controller, Action, Params for a possible ActionLink that I would display in the modal popup, and the message text, etc.
I need a little guidance on how to open the modal since it isn't attached to a click, but rather to whether an expression evaluates true or false, and where the best place for the pieces are.
Thanks in advance for the guidance
I would detect if the user has FollowUpItems in the Action that loads the dashboard page, and store that information in the ViewBag. For example,
public ActionResult Dashboard()
{
ViewBag.HasFollowupItems = UserHasFollowupItems();
return View();
}
In this example, UserHasFollowupItems() returns a string, something like 'true' or false'.
In the dashboard view, add an empty div into which the modal data will be loaded
<div id="followup_items"></div>
then add a document.ready() in the same view which defines the modal and determines if the modal should be loaded:
$(document).ready(function ()
{
// define modal
$("#followup_items").dialog({
autoOpen: false,
height: 'auto',
width: 825,
title: 'Followup Items',
position: [75, 75],
modal: true,
draggable: true,
closeOnEscape: true,
buttons: {
'Close': function ()
{
$(this).dialog('close');
}
},
close: function ()
{
$('.ui-widget-content').removeClass('ui-state-error');
},
});
if(#ViewBag.HasFollowupItems == 'true')
{
$('#followup_items').load("/FollowupItems/Load", function (data, txtStatus, XMLHttpRequest)
{
$('#followup_items').dialog('open');
}
});
});
In this example /FollowupItems/Load is the URL to the proper controller/action that generates the data for the view. You are correct, the view for this would be a partial view, loaded into the empty followup_items div on the page.
So you can use the #ViewBag object anywhere in the view, in this case passing in your boolean indicating if the modal should be loaded/opened. I have not found a way to use ViewBag in an external javascript file, so I typically use embedded script tags in my views so I can use the ViewBag.
You could also add in the user id in the same way (/FollowupItems/Load/#ViewBag.Userid), or any other data the followup action needs.