jQGrid celledit in JSON data shows URL Not set alert - javascript

I need to load a JSON from server and i want to enable a user to click and edit the value.
But when they edit, it should not call server. i mean i am not going to update immediately. So i dont want editurl. So i tried
'ClientArray' But still it shows Url is not set alert box. But i need
all the edited values when the user click Add Commented Items button this button will fire AddSelectedItemsToSummary() to save those in server
MVC HTML Script
<div>
<table id="persons-summary-grid"></table>
<input type="hidden" id="hdn-deptsk" value="2"/>
<button id="AddSelectedItems" onclick="AddSelectedItemsToSummary();" />
</div>
$(document).ready(function(){
showSummaryGrid(); //When the page loads it loads the persons for Dept
});
JSON Data
{"total":2,"page":1,"records":2,
"rows":[{"PersonSK":1,"Type":"Contract","Attribute":"Organization
Activity","Comment":"Good and helping og"},
{"PersonSK":2,"Type":"Permanant","Attribute":"Team Management",
"Comment":"Need to improve leadership skill"}
]}
jQGRID code
var localSummaryArray;
function showSummaryGrid(){
var summaryGrid = $("#persons-summary-grid");
// doing this because it is not firing second time using .trigger('reloadGrid')
summaryGrid.jqGrid('GridUnload');
var deptSk = $('#hdn-deptsk').val();
summaryGrid.jqGrid({
url: '/dept/GetPersonSummary',
datatype: "json",
mtype: "POST",
postData: { deptSK: deptSk },
colNames: [
'SK', 'Type', 'Field Name', 'Comments'],
colModel: [
{ name: 'PersonSK', index: 'PersonSK', hidden: true },
{ name: 'Type', index: 'Type', width: 100 },
{ name: 'Attribute', index: 'Attribute', width: 150 },
{ name: 'Comment', index: 'Comment', editable: true,
edittype: 'textarea', width: 200 }
],
cellEdit: true,
cellsubmit: 'clientArray',
editurl: 'clientArray',
rowNum: 1000,
rowList: [],
pgbuttons: false,
pgtext: null,
viewrecords: false,
emptyrecords: "No records to view",
gridview: true,
caption: 'dept person Summary',
height: '250',
jsonReader: {
repeatitems: false
},
loadComplete: function (data) {
localSummaryArray= data;
summaryGrid.setGridParam({ datatype: 'local' });
summaryGrid.setGridParam({ data: localSummaryArray});
}
});
)
Button click function
function AddSelectedItemsToSummary() {
//get all the items that has comments
//entered using cell edit and save only those.
// I need to prepare the array of items and send it to MVC controller method
// Also need to reload summary grid
}
Could any one help on this? why i am getting that URL is not set error?
EDIT:
This code is working after loadComplete changes. Before it was showing
No URL Set alert

I don't understand the problem with cell editing which you describe. Moreover you wrote "i need the edited value when the user click + icon in a row". Where is the "+" icon? Do you mean "trash.gif" icon? If you want to use cell editing, how you imagine it in case of clicking on the icon on the row? Which cell should start be editing on clicking "trash.gif" icon? You can start editing some other cell as the cell with "trash.gif" icon ising editCell method, but I don't think that it would be comfortable for the user because for the users point of view he will start editing of one cell on clicking of another cell. It seems me uncomfortable. Probably you want implement inline editing?
One clear error in your code is usage of showSummaryGrid inside of RemoveFromSummary. The function RemoveFromSummary create jqGrid and not just fill it. So one should call it only once. To refresh the body of the grid you should call $("#persons-summary-grid").trigger("refreshGrid"); instead. Instead of usage postData: { deptSK: deptSk } you should use
postData: { deptSK: function () { return $('#hdn-deptsk').val(); } }
In the case triggering of refreshGrid would be enough and it will send to the server the current value from the '#hdn-deptsk'. See the answer for more information.
UPDATED: I couldn't reproduce the problem which you described, but I prepared the demo which do what you need (if I understand your requirements correctly). The most important part of the code which you probably need you will find below
$("#AddSelectedItems").click(function () {
var savedRow = summaryGrid.jqGrid("getGridParam", "savedRow"),
$editedRows,
modifications = [];
if (savedRow && savedRow.length > 0) {
// save currently editing row if any exist
summaryGrid.jqGrid("saveCell", savedRow[0].id, savedRow[0].ic);
}
// now we find all rows where cells are edited
summaryGrid.find("tr.jqgrow:has(td.dirty-cell)").each(function () {
var id = this.id;
modifications.push({
PersonSK: id,
Comment: $(summaryGrid[0].rows[id].cells[2]).text() // 2 - column name of the column "Comment"
});
});
// here you can send modifications per ajax to the server and call
// reloadGrid inside of success callback of the ajax call
// we simulate it by usage alert
alert(JSON.stringify(modifications));
summaryGrid.jqGrid("setGridParam", {datatype: "json"}).trigger("reloadGrid");
});

Related

How do I reload Jquery jtable with change in URL on select event

Consider I am showing toppers of each subject from a DB using Jtable.I have integrated this with Spring MVC.
$('#TableContainer').jtable({
//title: 'Members',
selectOnRowClick:true,
selecting: true, //Enable selecting
paging: true, //Enable paging
pageSize: 10, //Set page size (default: 10)
sorting: false, //Enable sorting
actions: {
listAction: myurl+'LoadMarks?subject='+subject,
},
fields: {
ExamDate: {
title: 'Exam Date',
},
StudentID: {
title: 'Student',
},
Marks: {
title: 'Marks Awarded',
}
}
});
At page load I am using $('#TableContainer').jtable('load');
Now I need to make this dynamic by providing user a dropdown and on change of dropdown I need to reload jQuery jTable with respective columns.
If using $('#TableContainer').jtable('reload'); the url is getting called but I need to change ListAction variable (URL) and reload the page.
I need to change url and load/reload jTable
Thanks In advance :)
Finally Found the Answer
I needed to destroy the Jtable.
But,$('#TableContainer').jtable('destroy'); does not work you can do it by.
refer link
$('#TableContainer').jtable({
});
$('#TableContainer').jtable('destroy');
then you need load JTable

Ext.Defer gives getAsynchronousLoad Error

I've just defined a combobox. Firstly it loads a countrylist and when select a value it's fire a change event which doing a ajax query to DB within searching service;
The thing; this configuration works pretty well when I click and open combobox items. But when I'm typing to combobox's field it's fires listener's store.load and because of none of country selected yet, the search query url gives not found errors of course.
{
xtype: 'countrycombo',
itemId: 'countryName',
name:'country',
afterLabelTextTpl: MyApp.Globals.required,
allowBlank: false,
flex: 1,
// forceSelection: false,
// typeAhead: true,
// typeAheadDelay: 50,
store: {
proxy: {
type: 'ajax',
// isSynchronous: true,
url: MyApp.Globals.getUrl() + '/country/list?limit=250',
// timeout: 300000,
reader: {
type: 'json',
rootProperty: 'data'
}
},
pageSize: 0,
sorters: 'description',
autoLoad: true
}
,
listeners: {
change: function (combo, countryId) {
var cityStore = Ext.getStore('cityCombo');
cityStore.getProxy()
.setUrl(MyAppp.Globals.getUrl() + '/city/view/search?query=countryid:'+ countryId);
// Ext.defer(cityStore.load, 100);
cityStore.load();
}
}
},
I've tried several things as you see in code above to set a delay/timeout for load during typing to combobox text field; Ext.defer, timeoutconfig on proxy, typeAhead config on combo but none of them worked!
I thought that Ext.defer is the best solution but it gives this error:
Uncaught TypeError: me.getAsynchronousLoad is not a function at load (ProxyStore.js?_dc=15169)
How can I set a delay/timeout to combobox to fires load function?
Instead of Ext.defer(cityStore.load, 100);
try using this :
Ext.defer(function(){
cityStore.load
}, 300);
If this doest work, try increasing your delay
or you can put a logic before loading
like this :
if(countryId.length == 5){
cityStore.load
}
This will ensure that you Entered the right values before loading
Hope this helps, and Goodluck on your project
well.. I've tried to implement #Leroy's advice but somehow Ext.defer did not fire cityStore.load. So I keep examine similar situations on google and found Ext.util.DelayedTask
So configured the listerens's change to this and it's works pretty well;
listeners: {
change: function (combo, countryId) {
var alert = new Ext.util.DelayedTask(function () {
Ext.Msg.alert('Info!', 'Please select a country');
});
var cityStore = Ext.getStore('cityCombo');
cityStore.getProxy().setUrl(MyApp.Globals.getUrl() + '/city/view/search?query=countryid:'+ countryId);
if (typeof countryId === 'number') {
cityStore.load();
} else {
alert.delay(8000);
}
}
}

Pagination is not working in jQgrid, what I am missing?

I have the following setup for jQgrid 5.1.0:
<div id="grid_container">
<table id="grid"></table>
<div id="gridpager"></div>
</div>
<script type="text/javascript">
$.fn.fmatter.btnFormatter = function (cellValue, options, rowData, addOrEdit) {
var btn =
'<a href="#">' +
'<img class="api_button" data-id="' + options.rowId + '" src="/images/icons/16x16/view.png" alt="Show API Response data" title="Show API Response data" />' +
'</a>' +
'<a href="#">' +
'<img class="error_button" data-id="' + options.rowId + '" src="/images/icons/16x16/view.png" alt="Show errors" title="Show errors" />' +
'</a>';
return btn;
};
$(function () {
$("#grid").jqGrid({
url: '/sf/api-logs',
datatype: "json",
colNames: {{ colNames|raw }},
colModel: {{ colFormats|raw }},
width: 980,
height: 300,
pager: "#gridpager",
toppager: true,
hoverrows: true,
shrinkToFit: true,
autowidth: true,
rownumbers: true,
viewrecords: true,
rowList: [10, 20, 50, 100],
data: [],
rownumWidth: 50,
sortable: true,
jsonReader: {
root: 'rows',
page: 'page',
total: 'total',
records: 'records',
cell: '',
repeatitems: false
},
loadComplete: function (data) {
if (data.records === 0) {
$("#load_grid").addClass("info_msg").html($("<span>", {
"class": "grid-empty",
"text": "No results were found."
})).delay(800).fadeIn(400);
}
}
}).on('click', '.api_button', function () {
var apiResponseContent = $('#apiResponseContent');
$.ajax({
type: "GET",
url: '/sf/api-logs/api-response',
data: {id: $(this).data('id')},
dataType: 'json',
success: function (data) {
if (typeof data[0].error !== 'undefined') {
apiResponseContent.text(data[0].error);
}
apiResponseContent.text(data[0].apiResponse);
$('#api_dialog').dialog('open');
}
});
return false;
});
$('#api_dialog').dialog({
autoOpen: false,
width: 600,
height: $(window).height() * 0.9,
modal: true,
buttons: {
Ok: function () {
$(this).dialog('close');
}
}
}).show();
});
</script>
But as the image below shown the pagination is not working and the small icon for refresh the grid is not being displayed either, what I am doing wrong here?
UPDATE
I have managed to show the refresh button by adding the following code:
$('#grid').jqGrid('navGrid', '#gridpager', {
edit: false,
add: false,
del: false,
search: false,
refresh: true,
refreshstate: "current"
})
But it only appears on the #gridpagger what about if I want it also on the top bar?
Here is an example of the data returned by the server: https://gist.github.com/reypm/b1d2a303ba471261e55d72bbef099b74
You reported about two problems: pagination not working and the Refresh button appears on the bottom pager only (not on the top-pager).
The problem with Refresh button seems be mostly simple. You use commercial Guriddo, which probably still have the same logic of working with pagers like jqGrid 4.7. Old jqGrid has two pager options: pager and toppager, which values have to be specified in different ways. Working with toppager is easy: one can add toppager: true option and jqGrid will generate the top-pager div itself and to replace the value of toppager from true to the id selector of new pager. It will be toppager: "#grid_toppager". On the other side, to create the pager on the bottom of the grid one have to create somewhere on the HTML page dummy div, like <div id="gridpager"></div> and to use pager parameter in the form pager: "gridpager". jqGrid will move the div on another place inside of the grid and to fill it with data. Other methods like navGrid, inlineNav, navButtonAdd have to use #gridpager or "#grid_toppager" as parameter to create the navigator bar and to add buttons to the bar. Thus you have to use the code like
$('#grid').jqGrid('navGrid', '#grid_toppager', {
edit: false,
add: false,
del: false,
search: false,
refreshstate: "current"
});
or
var $grid = $('#grid'),
topPagerSelector = $grid.jqGrid('getGridParam', 'toppager');
$grid.jqGrid('navGrid', topPagerSelector, {
edit: false,
add: false,
del: false,
search: false,
refreshstate: "current"
});
to create the navigator bar on the top-pager and to add the Refresh button to it. Alternatively you can use cloneToTop: true option of navGrid to add the same pagers to both pagers:
$('#grid').jqGrid('navGrid', '#gridpager', {
cloneToTop: true,
edit: false,
add: false,
del: false,
search: false,
refreshstate: "current"
});
You can't use the option if you want to have only one top pager. You will have to use '#grid_toppager' with navButtonAdd method.
I develop free jqGrid fork of jqGrid. I simplified the behavior already in the first version of free jqGrid published in the 2015: see the wiki article. One can use pager: true in the same way like toppager: true and one can skip pager parameter in navGrid, inlineNav, navButtonAdd. The usage of navGrid could be
$('#grid').jqGrid('navGrid', {
edit: false,
add: false,
del: false,
search: false,
refreshstate: "current"
});
to add the navigator buttons on all pagers of the grid (top, bottom or both).
It's only one small difference between free jqGrid and Guriddo jqGrid. There are hundreds of other changes. I recommend you to consider to migrate to free jqGrid even if you payed Guriddo jqGrid license. I'd recommend you to read the page with the base information about the usage of free jqGrid.
The paging of data don't work because the response from your server is wrong. It looks like
{
"page": 1,
"total": 0,
"records": 67,
"rows": [
{ "id": "590a363477336501ad44ab02", "dataObject": "Account", ...},
...
{ "id": "590c97197ad70f00575a310a", "dataObject": "AgreementHistory", ...}
]
}
You use datatype: "json" option without loadonce: true option, which corresponds server side paging. It means that jqGrid send to url requests with rows and page parameter. The first request, which send jqGrid will contains page=1&rows=20 (20 is the default value of rowNum parameter of jqGrid) and the server have to return 20 or less rows (return only one requested page of data). Additional total and records property informs jqGrid about the total number or pages and records. Based on the value of total parameter jqGrid will disable pager buttons and the user will be not able to make paging correctly.
One the other side, your server response contains wrong value of total property and all 67 rows instead of 20 requested rows. Other 47 rows of the serve response will be just ignored by jqGrid.
If you have scenario, where the total number of records is not large (like 67 in you case), then it's recommended to add loadonce: true option (and forceClientSorting: true additionally in case of usage free jqGrid) and to modify the server response to
[
{ "id": "590a363477336501ad44ab02", "dataObject": "Account", ...},
...
{ "id": "590c97197ad70f00575a310a", "dataObject": "AgreementHistory", ...}
]
with all rows of the grid. jqGrid will fill internal data parameter, it will change datatype to "local" automatically after the first loading the data. As the result paging, sorting and filtering/searching (try filterToolbar or search: true of navGrid) locally without any additional communication to the server. It essentially simplify the server code and improves the performance of jqGrid. Even relatively large number of rows can be processed very quickly if you use small enough page size (like rowNum: 20 or rowNum: 10). You can try the demo with 60000 rows, 15 columns and 25 rows per page. You can test the time of paging, sorting and filtering.

Kendo combobox takes time to load and open if datasource has a huge amount of data

I have tried using a Kendo Combobox with a datasource having a structure like:
{text: "12 Angry Men", value:"1"}
and the Kendo Combobox is initialised as:
$("#movies").kendoComboBox({
dataTextField: "text",
dataValueField: "value",
dataSource: data,
height: 100
})
.closest(".k-widget")
.attr("id", "movies_wrapper")
;
$("#filter").kendoDropDownList({
change: filterTypeOnChanged
});
It is found that for data of about 40,000 objects the combobox takes a 3 sec delay to load and 6-7 secs of delay to open it each time.
I debugged the native code and found out that it does take some time to handle the animation for so many objects to be shown in the popup.
I therefore tried passing animation as false.
But this still did not reduce the delay.Can someone help solve this problem?
I had a similar issue myself with trying to load approx. 20000 items into a combobox.
The way round it is to use server filtering to only pull back a limited number of results. I find 100 is a decent enough number and if the result isn't there then the filter term needs to be a bit more specific to get the eventual correct item.
It obviously means more trips to the server to get the results but I find that is trade off worth taking.
$('#' + fullControlID).kendoComboBox({
dataTextField: 'Text',
dataValueField: 'Value',
filter: "contains",
autoBind: true,
ignoreCase: true,
minLength: 3,
change: function (e) {
$('#' + fullControlID).data("kendoComboBox").dataSource.read();
},
dataSource: {
serverfiltering: true,
serverPaging: true,
pageSize: 100,
transport: {
read:
{
type: "POST",
dataType: "json",
url: transportUrl,
cache: false,
data: {
filterText: function () {
var filter = $('#' + fullControlID).data("kendoComboBox").input.val();
if(filter === '{the place holder text ignore it}')
{
filter = '';
}
return filter;
}
},
}
}
}
});
above is some code that I use to do this with the appropriate controller/action (using mvc) behind the scenes.
if you need more info then let me know.
Note: (fullcontrolID is the id for the control that is the combobox).

Issue with jqGrid and jquery click event

I'm loading a jqGrid on my page. The grid has a Delete button for each row. I'm trying to use the jquery UI dialog confirmation on my Delete button.
Here's my javascript code:
<script type="text/javascript">
$(document).ready(function () {
$("#list").jqGrid({
url: '/MyController/MyFunction/',
datatype: 'json',
mtype: 'POST',
colNames: ['', 'Name', ''],
colModel: [
{ name: 'Edit', index: 'Edit', width: 40, align: 'left', sortable: false },
{ name: 'Name', index: 'Name', width: 120, align: 'left' },
{ name: 'Delete', index: 'Delete', width: 50, align: 'left', sortable: false }],
pager: $('#pager'),
rowNum: 10,
rowList: [10, 20, 50],
sortname: 'Name',
sortorder: "asc",
viewrecords: true,
width: 700
});
$("#dialog-confirm").dialog({
autoOpen: false,
modal: true,
buttons: {
"Delete": function () {
window.location.href = $(this).attr("href"); ;
},
Cancel: function () {
$(this).dialog("close");
}
}
});
$("a.confirm").click(function () {
alert("HELLO");
//$("#dialog-confirm").dialog("open");
});
});
</script>
I'm passing in data from my controller to the grid. I have the class "confirm" added to the Delete link for each row.
If I click on my Delete button, nothing happens. The link has the correct class, and all my javascript is loading correctly. I placed an alert at the end of my document.ready function to make sure there were no errors.
But if I comment out my jqGrid and add a link onto my page with the class "confirm", the click event will fire.
Has anyone ever run into this?
The main problem which you have is that you try to make 'click' binding with $("a.confirm").click(...) before the elements "a.confirm" are loaded.
You should either place the binding code inside of loadComplete or gridComplete event handler or use jQuery.live
$("a.confirm").live('click', function() {
alert("HELLO");
//$("#dialog-confirm").dialog("open");
});
instead of $("a.confirm").click(...).
One more general remark. The best practice working with jqGrid is dividing data from the HTML markup. I suppose that you place HTML fragment with <a class="confirm">...</a> inside of JSON data returned from the server. jqGrid supports another ways to archive the same results. You can 1) use showlink formatter; 2) use custom formatter which allow create any HTML fragment for the grid cell based on the row of data (see rowObject parameter) returned from the server 3) use unobtrusive JavaScript (see my answer with the code example) 4) any mix from both (see another answer with the code example). The way 3 seems me mostly close to what you do.
In any way having clear separation of JSON data from HTML markup is good not only because of design reason. It allows additionally reduce the size of data send from server. (see this answer for more information)

Categories