I have an ASP.Net MVC site with a KOGrid in one of my views. This pulls data by making an Ajax call to a controller which then selects from SQL Server via EF. My data table can be seen below:
I have the following column definition for my KO Grid:
self.columnDefs = [
{ width: 50, field: 'workflowTask_WorkflowTaskId', displayName: 'Id' },
{ width: 150, field: 'Timestamp', displayName: 'Timestamp', cellFilter: function (data) { return moment(data).format('DD/MM/YYYY h:mm a') } },
{ width: 100, field: 'currentState', displayName: 'Crnt State' },
{ width: 500, field: 'note', displayName: 'Notes' },
{ width: 100, field: 'previousState', displayName: 'Prev State' },
{ width: 100, field: 'currentUser', displayName: 'Crnt User', sortable: false },
{ width: 100, field: 'amendedByUser', displayName: 'Amnd By', sortable: false },
{ width: 100, field: 'previousUser', displayName: 'Prev User', sortable: false }
];
I have the following grid options:
self.gridOptions = {
data: self.recs,
columnDefs: self.columnDefs,
autogenerateColumns: false,
showGroupPanel: true,
canSelectRows: false,
showFilter: true,
filterOptions: self.filterOptions,
enablePaging: true,
pagingOptions: self.pagingOptions,
sortInfo: self.sortInfo,
rowHeight: 35
};
I have an observable array to hold the data to be displayed in the kogrid:
self.recs = ko.observableArray([]);
This is populated by the following javascript function:
self.get = function () {
$loadingIndicator.show();
$.ajax({
url: BASE_URL + 'TaskHistory/GetRecords',
type: 'get',
data: {
'page': self.pagingOptions.currentPage(),
'pageSize': self.pagingOptions.pageSize(),
'filter': self.filterOptions.filterText == undefined ? '' : self.filterOptions.filterText(),
'sort': self.sortInfo().column.field + ' ' + self.sortInfo().direction
},
contentType: 'application/json; charset=utf-8',
success: function (data) {
self.pagingOptions.totalServerItems(data.RecCount);
var recsArray = [];
$.each(data.PageOfRecords, function (key, value) {
recsArray.push(
new Task(value.WorkflowTaskHistoryId,
value.Timestamp,
value.PreviousState,
value.CurrentState,
value.AmendedByUser,
value.Note,
value.PreviousUser,
value.CurrentUser,
value.WorkflowTask_WorkflowTaskId));
});
self.recs(recsArray);
}
});
$loadingIndicator.hide();
};
As can be seen in the following screen grab from Chrome Developer tools, this observable is correctly populated:
My problem is - when displayed, the date shown are all for the current machine datetime - not related to the data retrieved from the ajax call, as shown below:
Can anyone see where I went wrong please?
You have a typo in your code, in your column def you have 'Timestamp' with a capital T but your property is called timestamp.
So the fix is very simple:
{ width: 150, field: 'timestamp', displayName: 'Timestamp', cellFilter: function (data) { return moment(data).format('DD/MM/YYYY h:mm a') } },
Why the strange behavior:
the KoGrid does not check that you provide a valid field name and in this case it passes undefined to the cellFilter function as the data parameter
if you call moment function without a valid date it defaults to the current time, that is why all your columns show the same time
Related
I am trying to add button instead of View column but i tried with formatter still button is not loading but records are coming for the rest of the columns.
Below is my code:
$(function () {
$("#grid").jqGrid({
url: "/Location/LocationsList1",
datatype: 'json',
mtype: 'Get',
colNames: ['Id', 'Country Name', 'State Name', 'City Name', 'Location Name','View'],
colModel: [
{ key: true, hidden: true, name: 'Id', index: 'Id', editable: true },
{ key: false, name: 'CountryName', index: 'CountryName', editable: true },
{ key: false, name: 'StateName', index: 'StateName', editable: true },
{ key: false, name: 'CityName', index: 'CityName', editable: true },
{ key: false, name: 'Name', index: 'Name', editable: true },
{ key: false, name: 'View', index: 'View', editable: true,formatter:ViewButton }],
pager: jQuery('#pager'),
rowNum: 10,
rowList: [10, 20, 30, 40],
height: '100%',
viewrecords: true,
caption: 'Location',
emptyrecords: 'No records to display',
jsonReader: {
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: false,
Id: "0"
},
});
});
function ViewButton(cellvalue, options, rowObject) {
var rowid= options.rowid;
var button = "<button class=\"viewLineItem\" id="+ rowid+">View Line Item</button>"
$('#' + rowid).die();
$('#' + rowid).live('click', function (rowId) {
alert("hi");
alert(rowId);
});
};
I am new to JqGrid and don't know how it works. Any guidance/Help will be appreciated.
The code has some problems
options has no rowid property, but it has rowId property. You should change options.rowid to options.rowId
The formatter will be called during building the HTML fragment of the grid body. No element of the grid exist at the moment on the page. Thus you can't use $('#' + rowid).live('click', ...); at the moment.
The formatter have to return the HTML fragment, which will be placed in the corresponding cell (inside of <td>). One misses return button; at the end of the formatter.
There are exist well-known name conversion in JavaScript. One should use functions, which starts with capital letter only if you define the constructor of the new class. You see that ViewButton will be displayed in the other color to distinguish classes from other function. You should rename ViewButton to viewButton to hold the standard name conversion of JavaScript.
It's better don't specify index property in colModel. In the same way one should not include the properties with the defaul value, like key: false. To specify common property for many columns you can use cmTemplate property.
One should reduce the number of global functions, because the functions will be considerd as the properties of window object.
instead of usage hidden column with name: 'Id' one can specify id: 'Id' property of jsonReader. You use repeatitems: false property, which means that every item of input data has properties CountryName, StateName and so on. The default name of the id property (the rowid - the id of <tr> elements) is id, but you use Id instead. The property id: "Id" informs jqGrid about it.
The modified code could be about the following
$(function () {
function viewButton(cellvalue, options, rowObject) {
return "<button class=\"viewLineItem\" id=\"" +
options.rowId + "\">View Line Item</button>";
}
$("#grid").jqGrid({
url: "/Location/LocationsList1",
datatype: 'json',
colNames: ['Id', 'Country Name', 'State Name', 'City Name', 'Location Name','View'],
colModel: [
{ name: 'Id', key: true, hidden: true },
{ name: 'CountryName' },
{ name: 'StateName' },
{ name: 'CityName' },
{ name: 'Name' },
{ name: 'View', editable: false, formatter: viewButton }
],
cmTemplate: { editable: true },
pager: '#pager',
rowNum: 10,
rowList: [10, 20, 30, 40],
height: '100%',
viewrecords: true,
caption: 'Location',
emptyrecords: 'No records to display',
jsonReader: { repeatitems: false, id: "Id" }
});
$("#jqGridA").click(function (e) {
var $td = $(e.target).closest("tr.jqgrow>td"),
rowid = $td.parent().attr("id"),
p = $(this).jqGrid("getGridParam");
if ($td.length > 0 && p.colModel[$td[0].cellIndex].name === "View") {
alert(rowid);
}
});
});
The last part of the above code ($("#jqGridA").click(...);) register one click handler for the whole grid. If the user clicks on any cell then the event handler will be called because of event bubbling. The e.target gives as the DOM element, which was clicked (for example the <button>). By using closest we can go to the outer <td> element, which parent is the row (<tr>) of the grid. The .attr("id") of the row is the rowid. Such binding works more effectively as binding click handler to every button inside of the grid.
By the way jqGrid has already one click event handler. One can use beforeSelectRow callback, because it will be called inside of the click handler. One should only don't forget to return true from the beforeSelectRow callback to inform jqGrid that you allow to select the row. The callback beforeSelectRow has already rowid as the first parameter, which simplify our code a little. The final code will be
$(function () {
function viewButton(cellvalue, options, rowObject) {
return "<button class=\"viewLineItem\" id=\"" +
options.rowId + "\">View Line Item</button>";
}
$("#grid").jqGrid({
url: "/Location/LocationsList1",
datatype: 'json',
colNames: ['Id', 'Country Name', 'State Name', 'City Name', 'Location Name','View'],
colModel: [
{ name: 'CountryName' },
{ name: 'StateName' },
{ name: 'CityName' },
{ name: 'Name' },
{ name: 'View', editable: false, formatter: viewButton }
],
cmTemplate: { editable: true },
pager: '#pager',
rowNum: 10,
rowList: [10, 20, 30, 40],
height: '100%',
viewrecords: true,
caption: 'Location',
emptyrecords: 'No records to display',
jsonReader: { repeatitems: false, id: "Id" },
beforeSelectRow: function (rowid, e) {
var $td = $(e.target).closest("tr.jqgrow>td"),
p = $(this).jqGrid("getGridParam");
if ($td.length > 0 && p.colModel[$td[0].cellIndex].name === "View") {
alert(rowid);
}
}
});
});
I am new to web development, I have run into this problem and have researched and tried many other methods to no avail. I need to populate a drop down list in a jqgrid only with values that are in my database. The url that I am using to do this gives me the correct response in JSON as follows (note that I only sent through selected fields):
{
"serviceBranchResult": [
{
"branch_services": [],
"queues": [],
"service_description": null,
"service_id": 2,
"service_name": "Forex",
"service_status": null
},
{
"branch_services": [],
"queues": [],
"service_description": null,
"service_id": 3,
"service_name": "Tellers",
"service_status": null
}
]
}
When I try to do a dropdownlist from the method below without reading the json from the url it works 100% however it isnt dynamic, I use the method getAllSelectOptions() and where I am using it in the grid looks like this:
function getAllSelectOptions() {
var services = {
'1':'Forex', '2':'Tellers', '3':'Consultants'};
return services;
}
My code for the grid:
url: "http://localhost:8080/service.svc/employees/3"
datatype: "json",
type: "GET",
contentType: "application/json; charset=utf-8",
height: '250',
colNames: ['ID', 'Name', 'Surname', 'Username', 'Email', 'Branch ID', 'User Type', 'Status', 'Speciality'],
colModel: [
{ name: 'employee_id', index: 'employee_id'},
{ name: 'employee_name', index: 'employee_name', editable: true },
{ name: 'employee_surname', index: 'employee_surname', editable: true },
{ name: 'employee_username', index: 'employee_username', editable: true },
{ name: 'employee_email', index: 'employee_email', editable: true },
{ name: 'branch_id', index: 'branch_id', editable: true },
{ name: 'user_type', index: 'user_type', editable: true },
{ name: 'employee_state', index: 'employee_state', editable: true },
{ name: 'employee_speciality', index: 'employee_speciality', editable: true,
sortable: true,
align: 'center',
editable: true,
cellEdit: true,
edittype: 'select',
formatter: 'select',
editoptions: { value: getAllSelectOptions() }
}],
rowNum: 20,
rowList: [10, 20, 30],
pager: '#pager_jqgrid',
And this works perfectly.
However I use this following method to potentially replace the getAllSelectOptions() method and it does return the information when I use alert boxes, but does not work.
function availAtBranch() {
$.ajax({
type: "GET",
url: "http://localhost:8080/service.svc/branch/3",
dataType: "json",
success: function (data) {
$.each(data.serviceBranchResult, function (i, obj) {
//alert(obj.service_id + ":" + obj.service_name);
var div_data = obj.service_name + ":" + obj.service_name;
//alert(div_data);
});
return div_data;
}
});
I think it has something to do with how in parsing the JSON to the editoptions method, or sending an object through. How do I get my JSON to be in the format as described in the getAllSelectOptions() method, or how do I display my data in the dropdownlist. Thank you in advance
I have two JavaScript files called FileA.js and FileB.js.
FileA.js contains the following function:
Reports.CompanySearch.InitGrid = function (viewModel, emptyInit) {
var columns = [
{
name: 'CompanyName',
width: 150,
hidedlg: true,
search: false,
formatter: function namelinkformatter(cellvalue, options, rowObject) {
return "<a href='#/CompanyDetails/" + rowObject["Id"] + "'>" + rowObject["CompanyName"] + "</a>";
}
},
{ name: 'Address', width: 300, search: false },
{ name: 'City', width: 100, search: false },
{ name: 'State', width: 50, search: false },
{ name: 'Zip', width: 80, search: false, hidden: true },
{ name: 'Country', width: 120, search: false, hidden: true }
];
var grid = $("#searchGrid");
grid.jqGrid({
jsonReader: { root: 'rows', total: 'total', page: 'page', records: 'records', cell: 'cell', id: 'Id', repeatitems: false },
colNames: [
'Company Name',
'Address',
'City',
'State',
'Zip',
'Country'],
colModel: columns,
postData: Reports.CompanySearch.CreateSearchModel(viewModel),
url: '/CompanyReport/Search',
datatype: emptyInit ? 'local' : 'json',
mtype: 'POST',
viewrecords: true,
loadonce: false,
shrinkToFit: false,
multiselect: false,
autowidth: true,
altRows: true,
height: 'auto'
});};
Basically the function creates on a page (Page A) a data grid which contains a list of companies loaded from a table in SQL Server.
The Company name has a link, allowing users to click it and get the company detail on a different page (Page B).
Page A is controlled by JavaScript FileA.js and Page B by JavaScript FileB.js.
I would like to pass the Company ZipCode to a function in FileB.js everytime the user clicks on the company name.
The solutions I ran into on the web were not helpful so far and any help would be very appreciated. Thanks!
Since you're using Knockout, have a look at Components.
The way to coordinate the two is to have a parent file that knows about both of them and mediates between them. The parent would create the data objects and pass them to both of the component objects.
I am trying to make a cell in a jqxGrid editable depending on the value of another column in the row (with the name Editable).
{ text: "Percentage", datafield: "Percentage", columntype: 'numberinput', width: 100, cellsformat: 'p2',
editable: function (index, datafield, value, defaultvalue, column, rowdata) {
return rowdata.Editable;
}
},
This does not work. The cell is always editable regardless of the value of rowdata.Editable.
Replacing return rowData.Editable; with return false; does not work either.
I am using jqWidgets 3.9.0 in combination with JQuery 1.7.1.
Can anybody explain why this does not work and how to get it to work?
I got this to work by doing the following:
Replacing the url in the data source with localdata which references a local array called "data".
This array is filled using the original source url.
var data = [{}];
var source =
{
datatype: "json",
datafields: [
{ name: 'Id', type: 'number' },
{ name: 'Name', type: 'string' },
{ name: 'Percentage', type: 'string' },
{ name: 'Editable', type: 'bool' }
],
localdata: data
}
Using the cellbeginedit property instead of the editable property when defining the columns in the jqxGrid:
var dataAdapter = new $.jqx.dataAdapter(source);
$("#myGrid").jqxGrid(
{
width: 800,
source: dataAdapter,
editable: true,
editmode: 'click',
selectionmode: 'singlecell',
columns: [
{ text: "Id", datafield: "Id", columntype: 'textbox', editable: false, hidden: true },
{ text: "Name", datafield: "Name", columntype: 'textbox', width: 400, editable: false },
{ text: "Percentage", datafield: "Percentage", columntype: 'numberinput', width: 100, cellsformat: 'p2',
cellbeginedit: function (row) {
return data[row].Editable;
}
},
]
});
I was using the cellclick to do this kind of control.
$("#jqxGrid").on('cellclick', function (event) {
var args = event.args;
var datafield = event.args.datafield;
var rowIndex = args.rowindex;
var data = $('#jqxGrid').jqxGrid('getrowdata', rowIndex);
if(datafield == 'assign'){
if(data.assign){
$('#jqxGrid').jqxGrid('setcolumnproperty', 'datafield', 'editable', true);
}else{
$('#jqxGrid').jqxGrid('setcolumnproperty', 'datafield', 'editable', false);
}
}
});
I'm trying to display 10 records per page but is hows the NAN values Below is the Code snippet
$('#JarDistHist').jtable('detach');
$('#JarDistHist').jtable({
title: 'Jar Distribution History',
paging: true,
pageSize: 10,
sorting: true,
defaultSorting: 'Date ASC',
actions: {
listAction: 'StudentActions.php?action=list&DistId='+cname+'&fitem='+fitem+'',
deleteAction: 'StudentActions.php?action=delete'
},
fields: {
id: {
key: true,
create: false,
edit: false,
list: false,
},
Date: {
title: ' Date',
type: 'date',
displayFormat: 'dd-mm-y',
width: '40%'
},
TotRecvJars: {
title: 'Rec. ',
width: '30%',
display: function (data) {
return $(''+data.record.TotRecvJars+'');
// return $('<a href="JarFillingDetail.php?id=' + data.record.id + '">'+data.record.Date.format('DD-MM-YY')+');
}
},
NoOfJarsFill: {
title: 'Filled ',
width: '30%',
type:'integer',
display: function (data) {
return $(''+data.record.NoOfJarsFill+'');
}
},
BalanceJars: {
title: 'Bal. ',
width: '30%',
type:'integer',
display: function (data) {
return $(''+data.record.BalanceJars+'');
}
}
}
});
//Load person list from server
$('#JarDistHist').jtable('load');
In your column definitions you are saying type: 'integer' (NoOfJarsFill and BalanceJars), which means you want to display a number. But then you are returning HTML content as the value, which is not a number. "Not A Number" is exactly what NAN stands for.
Change type: 'integer' to type: 'string' and your problem will be solved.