I cannot get my jqGrid to populate - json

Edited with working code as per Mark's answer below.
I'm really starting to loath MVC. I have been trying all day to get a simple grid to work, but I'm having more luck banging a hole in my desk with my head.
I'm trying to implement a search page that displays the results in a grid. There are 3 drop-down lists that the user can use to select search criteria. They must select at least one.
After they have searched, the user will be able to select which records they want to export. So I will need to include checkboxes in the resulting grid. That's a future headache.
Using JqGrid and Search form - ASP.NET MVC as a reference I have been able to get the grid to appear on the page (a major achievement). But I can't get the data to populate.
BTW, jqGrid 4.4.4 - jQuery Grid
here is my view:
#model Models.ExportDatex
<script type="text/javascript">
$(document).ready(function () {
$('#btnSearch').click(function (e) {
var selectedSchool = $('#ddlSchool').children('option').filter(':selected').text();
var selectedStudent = $('#ddlStudent').children('option').filter(':selected').text();
var selectedYear = $('#ddlYear').children('option').filter(':selected').text();
var selectedOption = $('#exportOption_1').is(':checked');
if (selectedSchool == '' && selectedStudent == '' && selectedYear == '') {
alert('Please specify your export criteria.');
return false;
}
selectedSchool = (selectedSchool == '') ? ' ' : selectedSchool;
selectedStudent = (selectedStudent == '') ? ' ' : selectedStudent;
selectedYear = (selectedYear == '') ? ' ' : selectedYear;
var extraQueryParameters = {
school: selectedSchool,
student: selectedStudent,
year: selectedYear,
option: selectedOption
};
$('#searchResults').jqGrid({
datatype: 'json',
viewrecords: true,
url: '#Url.Action("GridData")?' + $.param(extraQueryParameters),
pager: '#searchResultPager',
colNames: ['SchoolID', 'Student Name', 'Student ID', 'Apprenticeship', 'Result'],
colModel: [
{ name: 'SchoolID' },
{ name: 'Student Name' },
{ name: 'StudentID' },
{ name: 'Apprenticeship' },
{ name: 'Result' }]
}).trigger('reloadGrid', [{ page: 1 }]);
});
});
</script>
#using (Html.BeginForm("Index", "Datex", FormMethod.Post))
{
<h2>Export to Datex</h2>
<div class="exportOption">
<span>
#Html.RadioButtonFor(model => model.ExportOption, "true", new { id = "exportOption_1" })
<label for="exportOption_1">VET Results</label>
</span>
<span>
#Html.RadioButtonFor(model => model.ExportOption, "false", new { id = "exportOption_0" })
<label for="exportOption_0">VET Qualifications</label>
</span>
</div>
<div class="exportSelectionCriteria">
<p>Please specify the criteria you want to export data for:</p>
<table>
<tr>
<td>School:</td>
<td>#Html.DropDownListFor(model => model.SchoolID, Model.Schools, new { id = "ddlSchool" })</td>
</tr>
<tr>
<td>Student: </td>
<td>#Html.DropDownListFor(model => model.StudentID, Model.Students, new { id = "ddlStudent" })</td>
</tr>
<tr>
<td>Year Completed:
</td>
<td>
#Html.DropDownListFor(model => model.YearCompleted, Model.Years, new { id = "ddlYear" })
</td>
</tr>
</table>
<table id="searchResults"></table>
<div id="searchResultPager"></div>
</div>
<div class="exportSearch">
<input type="button" value="Search" id="btnSearch" />
<input type="submit" value="Export" id="btnExport" />
</div>
}
Here is my Controller. As we don't have a database yet, I am just hardcoding some results while using an existing table from a different DB to provide record IDs.
[HttpGet]
public JsonResult GridData(string sidx, string sord, int? page, int? rows, string school, string student, string year, string option)
{
using (SMIDbContainer db = new SMIDbContainer())
{
var ds = (from sch in db.SCHOOLs
where sch.Active.HasValue
&& !sch.Active.Value
&& sch.LEVEL_9_ORGANISATION_ID > 0
select sch).ToList();
var jsonData = new
{
total = 1,
page = 1,
records = ds.Count.ToString(),
rows = (
from tempItem in ds
select new
{
cell = new string[]{
tempItem.LEVEL_9_ORGANISATION_ID.ToString(),
tempItem.SCHOOL_PRINCIPAL,
"40161",
"No",
"Passed (20)"
}
}).ToArray()
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
}

Is the JSON you are passing back to the grid valid? Are you passing back the information that the jqGrid needs? Why setup your jqGrid inside of an ajax call instead of inside your $(document).ready(function () { ?
Here is an example of the portion of code I use to format my json for jqGrid:
var jsonData = new
{
total = (totalRecords + rows - 1) / rows,
page = page,
records = totalRecords,
rows = (
from tempItem in pagedQuery
select new
{
cell = new string[] {
tempItem.value1,
tempItem.value2, ........
}
}).ToArray()
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
If you want to make your user search first, you can on the client side, set the jqgrid datatype: local and leave out the url. Then after your user does whatever you want them to do you can have the jqGrid go out and fetch the data, via something like:
$('#gridName').jqGrid('setGridParam', { datatype: 'json', url: '/Controller/getGridDataAction' }).trigger('reloadGrid', [{ page: 1}]);
If you want to pass in the search data, or other values to the controller/action that is providing the data to the jqGrid you can pass it via the postData: option in the jqGrid. To set that before going out you can set it via the setGridParam option as shown above via postData: { keyName: pairData}.
MVC and jqGrid work great...there are a ton of examples on stackoverflow and Oleg's answers are a vast resource on exactly what you are trying to do. No hole in desk via head banging required!

Related

How do I update the model for a WebGrid using Ajax?

I'm trying to create a WebGrid that allows me to update the data source with Ajax. The data source is assigned a List<> containing a model I created to hold the data. The WebGrid populates correctly and I have no problem sorting using the header of the WebGrid or paging.
The code for the View:
#model IEnumerable<TestDataModel.Models.TestData>
#{
ViewBag.Title = "Test Website";
var grid = new WebGrid(canPage: true, canSort: true, ajaxUpdateContainerId: "grid", ajaxUpdateCallback: "callBack");
grid.Bind(Model, rowCount: 10);
grid.Pager(WebGridPagerModes.All);
#grid.GetHtml(htmlAttributes: new { id = "grid" },
tableStyle: "webgrid-table",
headerStyle: "webgrid-header",
alternatingRowStyle: "webgrid-alternating-row",
rowStyle: "webgrid-row-style",
mode: WebGridPagerModes.All,
firstText: "<< First",
previousText: "< Prev",
nextText: "Next >",
lastText: "Last >>",
columns: grid.Columns("This is a place holder,
I have a lot of columns"
));
}
<div>
<br />
<p>
Page Number: <input type="text" name="pageNumber" id="pageNumber" />
</p>
<p>
<input type="button" name="pageNumberButton" id="pageNumberButton" value="Page" />
</p>
</div>
<script type="text/javascript">
$(document).ready(function () {
$("#pageNumberButton").click(function () {
var pageNumber = $("#pageNumber").val();
$.ajax({
url: '#Url.Action("GetData", "Test")?pageNumber=' + pageNumber,
success: function (data) {
$("#grid").html(data);
},
error: function (data) {
alert("Error");
}
})
});
});
</script>
The bottom script tag is the ajax call that I'm trying to use to update the WebGrid. All that the "GetData" does is create a list pulling data from an SQL server and returns Json(testData, JsonRequestBehavior.AllowGet).
Code for Controller:
public ActionResult GetData(string pageNumber)
{
List<TestData> testData = new List<TestData>();
if (string.IsNullOrEmpty(pageNumber))
{
testData = Data.Data.TestDataGet();
}
else
{
try
{
var pageInt = Convert.ToInt32(pageNumber);
List<ParameterSQL> parameter = new List<ParameterSQL>();
parameter.Add(new ParameterSQL { Name = "#pageOffset", Value = pageInt });
testData = Data.Data.TestDataGet(parameter);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
return Json(testData, JsonRequestBehavior.AllowGet);
}
The error that I'm experiencing is when I push the button the WebGrid disappears entirely. The reason that I need to be able to update the WebGrid data source is because my table is millions of lines long and I'm only grabbing them a few thousand at a time. Once the user reaches the end of the of the list I want them to be able to load more using a SQL query that I already have working. Any help would be great, thanks.

JSON.stringify() function is replacing the file object with an empty one

ISSUE
Hello guys, can anyone please help me to solve this complicated issue? :
I'm creating an application using Spring boot v2.0.5 and React.js v15.6.2, ReactDom v15.6.2, React Bootstrap v0.32.4, and the linking between my frontend and serverside parts is made of restful web services using Spring annotations on the back and fetch API on the front. My React components are made by following the Parent-Children design pattern concept, that means: some of my components can be children of some others and vice versa.
How it works?
I have a table with columns and rows, each row inside the table has a unique id, 2 drop-downs, 1 text input, 2 datepickers and 1 file upload input which is causing the main issue; The user can add more rows that has same components as the previous ones, by clicking on the "+ Document" button; Each row has a unique incremental Id of type number (integer); the drop-downs and the inputs events are handled by one method inside the parent component based on their tag names;
I'm storing all data entered by the user inside a list ([]) of objects({}).
Example: if the user fill only the first row; the object stored inside the list state will be like this:
[{id:0,type:"forms",lang:"all",libelle:"some strings",dateBegin:"11-12-2018",dateEnd:"12-12-2018",document:{File(154845)}]
if the user adds one other row and then filled it like the first one, the list will be like this:
[{id:0,type:"forms",lang:"all",libelle:"some strings",dateBegin:"11-12-2018",dateEnd:"12-12-2018",document:{File(154845)},{id:1,type:"howTo",lang:"en",libelle:"some strings",dateBegin:"11-12-2018",dateEnd:"01-01-2019",document:{File(742015)}]
Check this image to see how the table look like: Table Demo
The table as code in Presentational component Class (child of the main component)
class Presentational extends React.Component {
constructor(props) {
super(props);
this.state = {
docObjList: [],
element: (
<FormDocRowItem // this contains the table tbody tds elements..
id={1}
handleChanges={this.props.handleChanges}/>)
};
this.handleAddDocumentRow = this.handleAddDocumentRow.bind(this);
}
// handleAddDocumentRow method
handleAddDocumentRow(e) {
const value = e.target.value;
const name = e.target.name;
if (name === 'add') {
let arr = this.state.docObjList; // get the list state
// assign the new row component
arr = [...arr, Object.assign({}, this.state.element)];
// set the new list state
this.setState({docObjList: arr});
}
// if name === 'delete' logic..
}
// render method
render() {
const {handleReset} = this.props;
return(
<FormGroup>
<Form encType="multipart/form-data">
<Table striped bordered condensed hover>
<thead>
<tr>
<th>id</th>
<th>Type</th>
<th>Lang</th>
<th>Title</th>
<th>Date begin</th>
<th>Date end</th>
<th>+ Document</th>
<th>Options</th>
</tr>
</thead>
<tbody>
{this.state.element} // this row is required as initialization
{
this.state.docObjList.map((doc, index) => {
// as index in map() starts from 0 and there is an
// already row component above => The index inside the
// table should start from 1 except The key property
// which should know the right index of the function
const id = index+1;
return (
<tr key={index}>
<td>
{id}
</td>
<td>
<DocumentTypes id={id} handleChange={this.props.handleChanges}/>
</td>
<td>
<DocumentLanguage id={id} handleChange={this.props.handleChanges}/>
</td>
<td>
<DocumentLibelle id={id} handleChange={this.props.handleChanges}/>
</td>
<td>
<FormControl id={''+id} name="dateBegin" componentClass="input" type="date"
onChange={this.props.handleChanges}/>
</td>
<td>
<FormControl id={''+id} name="dateEnd" componentClass="input" type="date"
onChange={this.props.handleChanges}/>
</td>
<td>
<Document id={id} handleChange={this.props.handleChanges}/>
</td>
{
this.state.docObjList.length == index + 1 &&
<td>
<button type="button" style={{verticalAlign: 'middle', textAlign: 'center'}} id={index + 1}
name="delete"
onClick={this.handleAddDocumentRow}>
Delete
</button>
</td>
}
</tr>
);
})
}
</tbody>
</Table>
<button type="button" name="add" onClick={this.handleAddDocumentRow}>+ Document</button>
<FormGroup>
<Button type="reset"
style={{marginRight: '20%'}}
className="btn-primary"
onClick={this.props.handleClickSubmit}>Submit</Button>
<Button name="back" onClick={this.props.handleClickSubmit}>Annuler</Button>
</FormGroup>
</Form>
</FormGroup>
)
}
}
The row component class (Child component of Presentational)
const FormDocRowItem = (props) => {
const {id} = props; // the ID here is refering the column that is going to be
// show inside the table not the index of the map function
return(
return (
<tr>
<td>
{id}
</td>
<td>
<DocumentTypes id={id} handleChange={this.props.handleChanges}/>
</td>
<td>
<DocumentLanguage id={id} handleChange={this.props.handleChanges}/>
</td>
<td>
<DocumentLibelle id={id} handleChange={this.props.handleChanges}/>
</td>
<td>
<FormControl id={''+id} name="dateBegin" componentClass="input" type="date" onChange={this.props.handleChanges}/>
</td>
<td>
<FormControl id={''+id} name="dateEnd" componentClass="input" type="date" onChange={this.props.handleChanges}/>
</td>
<td>
<Document id={id} handleChange={this.props.handleChanges}/>
</td>
</tr>
);
}
}
Parent Component Class (The main component)
constructor(props) {
this.state ={
docDataList: [],
formIsReadyToSubmit: false
}
this.handleSubmit = this.handleSubmit.bind(this); // button submit click
this.handleReset = this.handleReset.bind(this); // button reset click
this.fillWithData = this.fillWithData.bind(this); // handle changes
}
// handleReset method..
fillWithData(e) {
const name = e.target.name; // get the name of the target
const id = parseInt(e.target.id); // get the id of the target
let value = e.target.value; // get the value of the target
let arr = this.state.docDataList; // get the list state
// if the target is a file upload
if (name === 'selectDocument')
value = e.target.files[0];
// create properties with null values starting from the first onchange
// event handling, to not get a misplaced properties inside the
// objects of the list state
arr.map((x) => {
x.type = x.type ? x.type : null;
x.lang = x.lang ? x.lang : null;
x.libelle = x.libelle ? x.libelle : null;
x.dateBegin = x.dateBegin ? x.dateBegin : null;
x.dateEnd = x.dateEnd ? x.dateEnd : null;
x.document = x.document ? x.document : null;
});
// if the event target name is not delete
if (name != 'delete') {
// check if the object id already exist in the table
// if it exists, the new value should replace the previous one
// and not allowed to add a new object to the list state
if ((arr.find((x) => x.id == id))) {
// loop through the list state to find the id of the object
arr.map((x) => {
if (x.id == id) {
// helper variable to prevent empty strings
const val = value != '' ? value : null;
switch (name) {
case 'selectType':
x.type = val;
break;
case 'selectLang':
x.lang = val;
break;
case 'libelle':
x.libelle = val;
break;
case 'dateBegin':
x.dateBegin = val;
break;
case 'dateEnd':
x.dateEnd = val;
break;
case 'selectDocument':
x.document = val;
break;
}
}
});
// assign the new list to my docDataList state
// mentioning that the id of the element already exist
this.setState({docDataList: arr}, () => {
console.log(' ID exist; new dataList :', this.state.docDataList);
});
}
// if the id doesn't exist (means that the button +document is clicked)
else {
// again, a helper variable as the previous statement
const val = value != '' ? value : null;
this.setState({
docDataList: [...arr, Object.assign({
id: id,
type: name === 'selectType' ? val : null,
lang: name === 'selectLang' ? val : null,
libelle: name === 'libelle' ? val : null,
dateBegin: name === 'dataBegin' ? val : null,
dateEnd: name === 'dateEnd' ? val : null//,
//document: name==='selectDocument'? val:null
})]
}, () => {
console.log('ID doesnt exist; new dataList :', this.state.docDataList);
});
}
}
}
HandleSubmit() method (Inside the Parent component class)
// Submit button click handler
handleSubmit(e) {
let docDataList = this.state.docDataList;
// if the user didn't touch any thing on the table rows
// that means the list is empty and its length = 0
if (docDataList.length === 0) {
this.setState({
alerts: {
message: 'Please enter your document information ',
show: true
}
});
}
// if the user has entered a data on the table row
else if (docDataList.length > 0) {
let data = new FormData(); // object which will be sent
// check the docDataList before request
console.log('DocDataList before request:', docDataList);
data.append('docDataList', JSON.stringify(docDataList));
fetch('http://localhost:8080/api/files/uploadFile', {
method: 'POST',
body: data
}).then(response => {
console.log('success document upload', response);
}).catch(error => {
console.log('error', error);
});
this.setState({
formIsReadyToSubmit: true,
docDataList: [], // reset the list
alerts: {updateAlert: true} // make an alert
});
}
}
To see what the console show when I fill the row with data: CLICK HERE PLEASE
To see the response of the request: CLICK HERE PLEASE
NOTE: You may notice after watching those screenshots, that there is an extra list of data called "arrContrats" which which I didn't mention it in my issue because it doesn't have any problem; the problem is with the "docDataList" list. Thanks in advance
If your problem is that you're getting a File object from the browser, and then later using JSON.stringify on it (or something containing it) and getting {} for it in the JSON, that's correct. The browser's File object has no own, enumerable properties. JSON.stringify only includes own, enumerable properties.
If you want the various properties that File objects have (inherited accessor properties), you'll need to copy them to a new object.
If you want the file data, it's not accessible as a property on the object, you have to use one of the methods it inherits from Blob to read the file data, such as stream, text, or arrayBuffer (or alternatively, you could use a FileReader, but there's no need to except in obsolete environments that don't have the modern methods).
function stringifyFileObject(arrWithFiles = []) {
const arrData = [];
for (let i=0; i < arrWithFiles.length; i++) {
const file = arrWithFiles[i];
const obj = {
lastModified: file.lastModified,
name: file.name,
size: file.size,
type: file.type,
webkitRelativePath: file.webkitRelativePath,
}
arrData.push( obj );
}
}
Or whatever that suits your needs. You get the idea...
Don't use JSON.stringify() with FormData instance. And don't use headers: {'Content-Type': 'application/json'} if you are sending a file.
Example:
let data = new FormData(form);
let config = {
method: "POST",
body: data
}
const response = await fetch(url, config);
const responseData = response.json();

Unable to populate JSON Data in ExtJS grid (4.2.1) in Grails 2.1

The JSON data is in Correct Format ! yet i am unable to bind the JSON data with the Grid . I dont even get an Empty Grid ! The problem lies with my extjs code,I am a new to Extjs! i am using 4.2.1
I am Trying to Render the Grid in the upload.gsp div by using
renderTo: 'csvGrid' in the extjs Panel .
It simply Renders the JSON data but not inside the grid ! Please help !
Grails Contoller Actions Contoller Code
def index() {
render (view:"upload")
}
def upload() {
def uploadedCSVFile = request.getFile('file')
// def csvMap = [:]
// def listOfCsvMap = []
def materialCode
def serialNumber
def label
String [] row ;
char separator = ';';
CSVReader reader = new CSVReader(new InputStreamReader(uploadedCSVFile.getInputStream()),separator);
String [] header = reader.readNext()
// String [] temp;
if (header[0].equalsIgnoreCase("Material_Code") && header[1].equalsIgnoreCase("Serial_Number") && header[2].equalsIgnoreCase("#Labels") )
{
List <String []> fileData = reader.readAll()
Iterator<String[]> rowIterator = fileData.iterator()
def listOfCsvMap = []
while (rowIterator.hasNext())
{
def csvMap = [:]
row = rowIterator.next()
materialCode = row.collect().get(0)
serialNumber = row.collect().get(1)
label = row.collect().get(2)
csvMap.put('Material_Code', materialCode)
csvMap.put('Serial_Number', serialNumber)
csvMap.put('Labels', label)
listOfCsvMap.add(csvMap)
}
render([items:listOfCsvMap] as JSON)
upload.gsp
<body>
<div class="body">
<g:uploadForm action="upload" enctype="multipart/form-data">
<input type="file" name="file">
<g:submitButton name="upload" value="Upload"/>
</g:uploadForm>
<g:javascript src="grid.js" />
<div id="csvGrid"> </div>
and in the grid.js
var store1;
Ext.onReady(function() {
store1 = new Ext.data.JsonStore({
storeId: 'myStore1',
pageSize: 20,
proxy: {
type: 'ajax',
url:'upload',
reader: {
type: 'json',
root: 'items'
}
},
fields: ['Material_Code','Serial_Number','Labels']
});
var grid = Ext.create('Ext.grid.Panel', {
store: store1,
stateful: false,
layout:'fit',
enableColumnMove: true,
enableColumnResize:true,
emptyText:'<b style="font-size:14px;color: #F49000;">'+'Please fill all the mandatory fields!!!'+'</b>',
columns: [
{
text : 'Material Code',
width:175,
sortable : true,
dataIndex: 'Material_Code',
},
{
text : 'Serial Number',
width :275,
sortable : true,
dataIndex: 'Serial_Number'
},
{
text : '#Labels',
width :275,
sortable : true,
dataIndex: 'Labels'
}
],
bbar: Ext.create('Ext.PagingToolbar', {
store: store1,
pageSize: 20,
displayInfo: true,
displayMsg: 'Displaying rows {0} - {1} of {2}',
emptyMsg: "No rows to display"
}),
height: 350,
width: 850,
renderTo: 'csvGrid',
viewConfig: {
stripeRows: true,
enableTextSelection:true
}
});
store1.reload();
});
The error that is causing the issue directly is this :
<g:uploadForm action="upload" enctype="multipart/form-data">
The action is upload, which is the url that returns the JSON.
A solution would be to create a separate page, define it as action and load the JavaScript on that page.
Alternatively, instead of submitting the form you can send the values as parameters when you load the store (pass them in the options object of store1.load({params: {...}}). In this case it would be a better design to create the whole page with extjs, including the form.
There are other problems with the code, like you have store1.reload();, but you never called load() before.

Unable to sort Dgrid

var CustomGrid = declare([Grid, Keyboard, Selection]);
var questionGrid = new CustomGrid({
store: questionCacheStore,
columns: [
editor({
label: "Questions",
field: "question",
editor: "text",
editOn: "dblclick",
sortable:true})
],
selectionMode: "single",
cellNavigation: false
}, "questions");
I am new to Dgrid. So, please do bear with me .
i was able to populate the dgrid with a JsonStore content. But when i click on the column 'Questions', it doesn't get sorted as in local data store.instead it shows an error Uncaught TypeError: Object [object Object] has no method 'sort'. Is it required to define such a method . If so, how and where should i define it ?
I am not the person to answer your J2EE question. I asked that question recently. The solution that I found was to inject the HttpServletRequest directly. This allowed me access to the query string parameters. From there I was able to get the sort direction (ascending, descending) and column to sort. Hopefully the snippets below will help.
Example Grid Setup
require(["dojo/store/JsonRest", "dojo/store/Memory", "dojo/store/Cache",
"dojo/store/Observable", "dgrid/OnDemandGrid", "dojo/_base/declare", "dgrid/Keyboard",
"dgrid/Selection", "dojo/domReady!"],
function(JsonRest, Memory, Cache, Observable, Grid, declare, Keyboard, Selection) {
var rest = new JsonRest({target:"/POC_Admin/rest/Subcategory/", idProperty: "subcatId"});
var cache = new Cache(rest, new Memory({ idProperty: "subcatId" }));
var store = new Observable(cache);
var CustomGrid = declare([ Grid, Keyboard, Selection ]);
var grid = new CustomGrid({
columns: {
subcatId: "ID",
name: "Name"
},
store: store
}, "grid");
grid.on("dgrid-select", function(event){
// Report the item from the selected row to the console.
console.log("Row selected: ", event.rows[0].data);
});
grid.startup();
});
Example Rest GET
#Context private HttpServletRequest servletRequest;
#GET
#Path("")
#Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
public String getSubcategories(#QueryParam("name") String name) throws IOException {
//Respond to a QueryString value.
if (servletRequest.getQueryString() != null && servletRequest.getQueryString().length() > 0) {
String querystringKey = servletRequest.getQueryString();
System.out.println("QSKey = " + querystringKey);
System.out.println("Substr: " + querystringKey.substring(0, 4));
if (querystringKey.length()>4) {
if (querystringKey.substring(0, 4).contains("sort")) {
//We have the sort request.
}
}
}
//Return all results otherwise from your DAO at this point
}

linq and json, anonymous type cannot have multiple properties with the same name

i have a json which is this:
var jsonData = new
{
total = totalPages,
page = page,
records = totalRecords,
rows = reservations.Select(x => new { x.ReservationId, x.Employee.Name,roomName = x.Room.Name, x.Date, x.StartTime, x.EndTime, x.Notes}).ToList()
.Select(x => new
{
id = x.ReservationId,
cell = new string[]
{
roomName,
x.Name,
x.Date.ToString().Split(' ')[0],
x.StartTime.ToString().Remove(5) +" - " +x.EndTime.ToString().Remove(5),
x.Notes,
String.Format("<input type=\"button\" value=\"DETAILS\" onclick=\"window.location.href='/Reservation/Details/{0}'\"/>&nbsp &nbsp<input type=\"button\" value=\"EDIT\" onclick=\"window.location.href='/Reservation/Edit/{0}'\"/>&nbsp &nbsp<input type=\"button\" value=\"DELETE\" onclick=\"window.location.href='/Reservation/Delete/{0}'\"/>", x.ReservationId),
}
}).ToArray(),
};
this json will be returned to a jqGrid. when i typed x.Room.Name in the first select statement, an error occured because a property with the same name already exists (i.e. x.Employee.Name).
so i tried "roomName=x.Room.Name" and i put roomName in the cell content.
however, when the json is returned to my jqGrid, the column, which supposedly contains the roomName, is empty. how could i show the values of x.Room.Name in other ways?
Since you have renamed the column to roomName make sure that on the client you have a corresponding column:
$('#grid').jqGrid({
colNames: [ 'roomName', 'Name', ..... other columns ],
colModel: [
{ name: 'roomName', index: 'roomName' },
{ name: 'Name', index: 'Name' },
.....
],
........
});