Telerik MVC grid sort order preserve - asp.net-mvc

I have an old Telerik MVC grid(not Kendo). It's sortable:
.Pageable(pager => pager.Enabled(true).PageSize(20))
.Selectable()
.Sortable()
The problem is it doesn't preserve its state after navigation or page refresh. My goal is to preserve the sort state in one session. So if the user made a sort on one of the cells he should see that sorting even if he navigates elsewhere on the page, but after he logs out/ or closes the browser it can reset. How can I achieve this?
UPDATE
if (window.sortHelper) {
sessionStorage.sortSettings = JSON.stringify(e.sortedColumns[0]);
} else {
if (sessionStorage.sortSettings != 'undefined')
e.sortedColumns[0] = JSON.parse(sessionStorage.sortSettings);
window.sortHelper = true;
}
I did this so far in the OnBeforeDataBinding event, the logic seems to be good, but it doesn't work. Doesn't makes the grid sorted despite that the sortingColumns was set.
Any idea?

Related

Kendo UI ComboBox Loading delay

I am working on web application (shipping domain) and using kendo UI for look and feel. While using kendo combo box I am facing an issue. In the database we have thousands of records in Vessel table which is bounded to a combobox, It took near about 6 sec to load if user wants to see all vessels (first time), but it took the same amount of time to get load second time also (that's the problem here) even it doesn't hit the Action method in controller (second time). I think its kendo's default functionality for combobox that if all records got loaded at 1st time (without filter) it will not send request to server to get the response for same request till we enter something in combobox filter, but if the combo box is getting load from the cache then it should't took the same time (6 sec) to load the combo box. I have searched for caching opting in kendo combobox documentation but no luck :( till now.
Here is my kendo combobox code:-
#(Html.Kendo().ComboBoxFor(i => i.VesselId)
.Name("VesselId").HtmlAttributes(new { style = "width:100%" })
.DataTextField("VesselName")
.Placeholder("Select Vessel...")
.DataValueField("VesselId")
.Filter(FilterType.Contains)
.AutoBind(false)
.MinLength(1)
.Value(proFormaVesselId)
.Text(proFormaVesselName)
.DataSource(source =>
{
source.Custom()
.ServerFiltering(true)
.Type("aspnetmvc-ajax")
.Transport(transport =>
{
transport.Read("GetFilteredVessels", "Common");
})
.Schema(schema =>
{
schema.Data("Data").Total("Total");
});
})
.Events(eve => eve.Change(#<text>
function () {
if (this.value() && this.selectedIndex == -1)
{
var dt = this.dataSource._data[0];
this.text('');
}
}
</text>
))
)
here is action method:-
public JsonResult GetFilteredVessels([DataSourceRequest] DataSourceRequest request)
{
var data = _IVesselService.GetVessel().Select(x => new
{
VesselId = x.VesselId,
VesselName = x.Status == (byte)enumRecordStatus.Accepted ? x.VesselName : (x.Status == (byte)enumRecordStatus.Draft ? x.VesselName + "(D)" : x.VesselName + "(R)")
}).OrderBy(x => x.VesselName);
var result= Json(data.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
result.MaxJsonLength = int.MaxValue;
return result;
}
please don't get confused with this line of code result.MaxJsonLength = int.MaxValue; previously i was getting error about the json lenth it too high issue, so I have settled it like this.
Now Combo box got loaded and took 6 sec but second time when I tried to load the same records (All records) it took 6 sec again even the breakpoin which I have placed on the GetFilteredVessels ActionMethod doesn't got hit. If combo box it getting load from cache then why it took 6 sec ?
I hope you understood my problem if not please comment I can explain more.
Thanks in advance.
as per #David Shorthose suggestion I found a temporary solution for this problem. Please refer to this Demo I am not selecting this as answer because may be someone or me can provide better solution for this, lets hope for the best. I am still looking doing research on it

Kendo UI Grid in MVC with Conditional Custom Command Button

I have a KendoUI Grid I'm using an MVC web application, all working fine however I want to add a custom command button that is shown conditionally in the UI and simply executes a command on my controller passing it the required parameter.
columns.Command(command => command.Custom("UnlockAccount").SendDataKeys(true).Click())
The command is specified as above but I only want the button to show when the DataItems IsLocked property is true.
I also cannot figure out how to just call and method on the controller rather. I cannot find a demo of this on the Kendo site and not sure how to move this forward.
Here is a specific example for using client templates for conditional command buttons.
const string ShowUpdateButton = "#if (IsNetReversal == false) {#<a class='k-button k-button-icontext k-grid-edit' href='\\#'><span class='k-icon k-edit'></span>Update</a>#}#";
const string ShowReverseButton = "#if (IsNetReversal == false) {#<a class='k-button k-button-icontext k-grid-reverse' href='/JournalDetail/Reverse/#: ID #' ><span class='k-icon k-reverse'></span>Reverse</a>#}#";
const string ShowDeleteButton = "#if (IsAdjustment == true) {#<a class='k-button k-button-icontext k-grid-delete' href='\\#'><span class='k-icon k-delete'></span>Delete</a>#}#";
You can do the template inline but I find it easier (particularly for multiple buttons) if you declare constants and then use string.format to concatenate them.
col.Template(o => o).ClientTemplate(string.Format("{0}{1}{2}", ShowUpdateButton, ShowDeleteButton, ShowReverseButton));
The upside is it will work with popup editor whereas jquery hacks will ignore the conditional status when a user cancels out of edit. A cancel from the popup editor will restore the grid row from the viewmodel or wherever Kendo stores it which results in button states from before any jquery/javascript hack. The method above will also auto-wire the standard commands since I copied their HTML output for the client template.
The downside is that if Kendo changes their pattern for command buttons the client template may fail. I tired several other methods besides this one and the downside to this method seems better than the other methods.
Note on Kendo Forums: As of the date of this post, they do not appear to allow people who do not pay for support to post to the forums so I would suggest posting questions here instead. They monitor Stack Overflow and in my experience they seem to answer questions more quickly here.
Use template column instead - via the ClientTemplate method.
Conditional templates are covered here and multiple times on the forums - the Command columns is not that flexible.
As of the December 2018 release of Kendo, you can now conditionally display custom buttons more easily, but it still relies on JavaScript to do its work, this function should be defined before your dataGrid or you'll run into issues.
function showCommand(dataItem) {
console.log("determining to hide or show" + dataItem);
// show the Edit button for the item with Status='New'
if (dataItem.Status == 'New') {
return true;
}
else {
return false;
}
}
Then the code for the Grid.
.Columns (columns => {
columns.Command (
command => command.Custom ("Approve")
.Visible ("showCommand")
.Click ("approveFunc")
)
.Width (100)
.HeaderTemplate ("Actions")
})
You can control custom command button visibility by Visible property.
columns.Command(command => command.Custom("UnlockAccount").SendDataKeys(true).Click().Visible("unlockAccountVisible"))
Visible property accepts JS function name and passes current dataItem as an argument.
JS function that evaluates button visibility:
<script>
function unlockAccountVisible(dataItem) {
// show the UnlockAccount button only when data item property IsLocked == true
return dataItem.IsLocked;
}
</script>
Read more in Show Command Buttons Conditionally kendo-ui documentation article.

Rails 3, bootstrap modal multiple layers of remote calling

I've been racking my head against this for 2 days now. I'm massively frustrated, and I can't seem to find any information on this with searching.
The issue. I'm using a :remote => true link to load some html from a different controller.
$('.managed_locations').bind('ajax:complete', function(evt, xhr, status){
$('#locations_modal').modal('show')
$('#locations_modal').html(xhr.responseText);
});
So it gets the html, dumps it into the bootstrap modal and displays the modal. This is working fine.
But inside of the modal I ALSO have a form which also uses :remote => true. Now to make life harder, when a button is pressed I clone the form and display it. So the user could have many forms.
Now the issue. Whenever the form is submitted it just loads it like a normal page. It's as if the :remote => true is being ignored. But this only in the modal. If I just load the modal controller by itself it works just fine. I also had this developed before using another jquery lightbox where it was working fine. I'm just switching in bootstrap for consistency.
So my initial thoughts are that the jquery_ujs.js isn't finding the new forms. So I added some code to output the form elements.
$("#log_events").click(function () {
$(document).find(".new_stored_physical_location").each(function() {
console.log( $(this).data() );
console.log( $(this).data('events') );
});
return false;
});
Which outputs in the console:
Object { type="html", remote=true}
Object { ajax:complete=[1]}
So I see that the events are being set in jQuery. Each of these forms has :remote => true and has the ajax event for when the request is complete. But it's just not doing an ajax request when I hit submit.
Is there something I'm missing that is required to make sure an ajax request will happen from the form???? The data() looks fine, the data('events') look fine. But is there some other event/binding that I need to look at?
The html that is loaded in from the modal right now is loading a layout. But i've done it both with a layout, without a layout. It's driving me nuts. Thanks for the help guys.
Edit: Some extra weirdness. The modal also loads some additional remote links, all of which are working correctly. It's only the form links which don't seem to work.
I got a solution. The big issue was within jquery_ujs.js Especially this line:
$(document).delegate(rails.formSubmitSelector, 'submit.rails', function(e) {
FYI, rails.formSubmitSelector = 'form'. So this code found all of the forms in the document, overwrote the submit with this function. But the issue was that once you loaded in some ajax, and that ajax contained a it wouldn't add this fancy event to it. You need to re-add it.
So this is what I did.
Inside of jquery_ujs there is a bunch of functions that are accessible outside of it using $.rails. So things like: $.rails.enableElement, $.rails.nonBlankInputs. And the code for the submit event was sitting around all willy nilly. It only executes once when the page is loaded. So I put that in a function addSubmitEvent():
// Add the form submit event
addSubmitEvent: function(element) {
//$(element) was before $(document) but I changed it
$(element).delegate(rails.formSubmitSelector, 'submit.rails', function(e) {
var form = $(this),
remote = form.data('remote') !== undefined,
blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector),
nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector);
if (!rails.allowAction(form)) return rails.stopEverything(e);
// skip other logic when required values are missing or file upload is present
if (blankRequiredInputs && form.attr("novalidate") == undefined && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
return rails.stopEverything(e);
}
if (remote) {
if (nonBlankFileInputs) {
return rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]);
}
// If browser does not support submit bubbling, then this live-binding will be called before direct
// bindings. Therefore, we should directly call any direct bindings before remotely submitting form.
if (!$.support.submitBubbles && $().jquery < '1.7' && rails.callFormSubmitBindings(form, e) === false) return rails.stopEverything(e);
rails.handleRemote(form);
return false;
} else {
// slight timeout so that the submit button gets properly serialized
setTimeout(function(){ rails.disableFormElements(form); }, 13);
}
});
}
This is basically the exact same code. But now it's $(element) instead of $(document). This was changed because now I can sniff for when the modal has loaded in the html. Then I can call:
$.rails.addSubmitEvent('#my_modal');
I then had an issue of it adding the event too many times from when I opened/closed the modal multiple times. So I just put a simple true/false if around it to call it once only.

How to delete a jqgrid row without reloading the entire grid?

I have a webpage with multiple jqgrids each with inline editing enabled, "action" column (edit icons) enabled and pager disabled. I need to handle the delete event for each row so that I can process the delete without reloading server-side data. I've looked at the approach mentioned in jqGrid Delete a Row and it's very helpful except I have two questions that are stumping me -
Are there more details around the rp_ge parameter in the delOptions.onClickSubmit event?
My column has the delOptions set as this -
delOptions: {onclickSubmit: function(rp_ge, rowid) {return onRowDelete(rp_ge,rowid);}},processing:true }},
Is there a way to get the grid id from within that event? I'd like to have a generic function that I can use to handle delete events from all the grids on the page. The rp_ge parameter has a gbox which sometimes contains the grid id appended? But I have no idea what it is since i'm not able to figure out when it's populated, when it's not.
function onRowDelete(rp_ge, rowid) {
//hardcoded grid id.. don't like it.
var gridid = '#Grid_X';
//what is this gbox?? can i get grid id predictable from it?
//var gridid = rp_ge.gbox.replace("#gbox_", "");
var grid = $('#Grid_X');
rp_ge.processing = true;
var result = grid.delRowData(rowid);
if (result) {
$("#delmod" + grid[0].id).hide();
}
return true;
}
In the jqGrid Delete a Row approach, the code $("#delmod"+grid[0].id).hide(); is hiding the popup delete confirmation dialog manually. What I noticed is that when the dialog pops-up, jqgrid de-emphasizes the background page (makes it light greyish). But after the popup is manually closed (hidden actually?), the background remains de-emphasized. So it looks like the page doesn't have focus (or even disabled). Any way this can be fixed? This can also be seen on the demo that Oleg wrote.
Any help would be appreciated.
(PS - I would've commented on the same post but I don't have enough points to comment on someone else's answer yet.)
In answer to your second point.
Several examples by Oleg such as this one have the following modification.
$("#delmod" + grid[0].id).hide();
is replaced with
$.jgrid.hideModal(
"#delmod"+grid_id,
{gb:"#gbox_"+grid_id,jqm:rp_ge.jqModal,onClose:rp_ge.onClose}
);
This will return focus after the delete operation.

ASP.net MVC - IE9 has an extra item with an empty key in forms collection

I have a bit of an odd problem, and I'm struggling to track down the root cause...
I have an ASP.net MVC site, and recently one of my colleagues started using IE9, and noticed a problem with one of the pages - it wasn't updating on click of save.
I figured that this would probably be a script issue, as there is a fair bit of jQuery used on this page, and it may still be, but:
If I submit this page in Chrome (or in IE8/7/6), then I get a forms collection with 11 items in it, as I would expect. If I submit the same page in IE9, I get an extra item at the end of the collection which has an empty string as key and an empty string as the value. This causes the call to UpdateModel() to not work (but not throw an exception) - none of these values are updated in my object, and the ModelState is still showing as valid.
So far, I've only found this one page, but I'm curious if anybody might know what is causing this?
Update 04/04/2011 - Narrowed down the culprit:
I removed bits of code until this worked and narrowed it down to some code in my validation. I use the jQuery validate plugin, and had the following as a submit handler (some redaction performed on names...):
submitHandler: function (form) {
var submitForm = true;
var newValue, originalValue;
newValue= $("#newValue").val();
originalValue= $("#originalValue").val();
if (newValue!= originalValue) {
//affectedValues is an array populated at the top of the page.
if ($.inArray(originalValue, affectedValues) != -1 &&
$.inArray(newValue, affectedValues) == -1) {
submitForm = confirm("Are you sure you want to do this");
}
}
if (submitForm) {
form.submit();
}
},
Removing this from the code (which I can thankfully do, as it's a bit of legacy code), seems to make this work, my empty item in the forms collection is gone. If anybody has any idea why this might have been happening, that'd be great.
Might be worth checking all the form fields in firebug to see if you have any un-named elements? I know I got caught out by the Select behaviour in IE before.
pdate 04/04/2011 - Narrowed down the culprit:
I removed bits of code until this worked and narrowed it down to some code in my validation. I use the jQuery validate plugin, and had the following as a submit handler (some redaction performed on names...):
submitHandler: function (form) {
var submitForm = true;
var newValue, originalValue;
newValue= $("#newValue").val();
originalValue= $("#originalValue").val();
if (newValue!= originalValue) {
//affectedValues is an array populated at the top of the page.
if ($.inArray(originalValue, affectedValues) != -1 &&
$.inArray(newValue, affectedValues) == -1) {
submitForm = confirm("Are you sure you want to do this");
}
}
if (submitForm) { form.submit(); }},
Removing this from the code (which I can thankfully do, as it's a bit of legacy code), seems to make this work, my empty item in the forms collection is gone. If anybody has any idea why this might have been happening, that'd be great.
I had some problems with my MVC sites due to the caching features introduced for IE9. My work around was to disable caching in my controller by adding an attribute:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class FaxController : Controller
FF, Chrome, Opera sends just value of FORM elements (button, input,..) with NAME.
IE always sends elements to server, even Submit with empty name and value which causes error.
So to be sure, always name elements.

Resources