Opened 12 years ago

Closed 11 years ago

Last modified 6 years ago

#6251 closed enhancement (invalid)

DOJO Grid not supporting display of nested objects in JSON data

Reported by: guest Owned by: Bryan Forbes
Priority: high Milestone: 1.3
Component: DojoX Grid Version: 1.0
Keywords: Cc:
Blocked By: Blocking:

Description (last modified by Nathan Toone)

The JSON data returned by server (using JSON lib) gives me data which has nested objects.

for e.g.

serverData =    [{"ab":1,"bc":1234567891,"cd":79.23,"de":1100,"ef":2109,"fg":1000,"gh":190,"hi":900, "empDetail":{"firstName":"abc", "lastName":"def"}},{"ab":2,"bc":"1234567892","cd":80.30,"de":1200,"ef":3118,"fg":2000,"gh":290,"hi":1000, "empDetail":{"firstName":"BLAH", "lastName":"BLAHBLAH"}}];

Here, i want to access "empDetail" properties like "empDetail.firstName", "empDetail.lastName".

I am trying to define the grid layout like this:

var empView = {
	cells: [[
	            { name: 'First Name', field: 'empDetail.firstName', width: '10em' },
	            { name: 'Last Name', field: 'empDetail.lastName', width: '10em' }
	       ]]
	     }; 	

I would like to have the grid support nested objects, so i don't have to reformat the JSON data for each nested object and create a individual store for each nested object.

Change History (9)

comment:1 Changed 12 years ago by guest

All,

As a temporary solution, i am using the layout's "get" method, that passes the current row's index.

Here's how i am doing it:

var empView = {
        cells: [[
                { name: 'First Name', get:getefname, width: '10em' },
                { name: 'Last Name', get:getelname, width: '10em' }
               ]]
};

and in the "getefname" and "getelname" functions are defined as :

function getefname(inRowIndex){   
        if (gridWidget.model.getRow(inRowIndex)){                     
                return gridWidget.model.getRow(inRowIndex).emp.firstName;
        }              
}

function getelname(inRowIndex){   
        if (gridWidget.model.getRow(inRowIndex)){                            
                return gridWidget.model.getRow(inRowIndex).emp.lastName;
        }              
}

This works fine for 2-3 fields, but if have 10 different nested objects, it becomes a pain to write functions for all the fields in all these objects.

Hoping to get a better solution.

comment:2 Changed 12 years ago by bill

Milestone: 1.3

comment:3 Changed 12 years ago by guest

hi bill...any pointers on how to achieve this functionality? it would really help our current project...

comment:4 Changed 12 years ago by guest

for now i did another workaround. I used a library called SOJO (we use Java) to flatten an entire object graph into a map of key, value pairs. Each key would be the field name in the grid's view definition.

But it would be great if the grid can display the nested objects using the "dot" notation.

comment:5 Changed 11 years ago by Bryan Forbes

Owner: changed from sorvell to Bryan Forbes

comment:6 Changed 11 years ago by Nathan Toone

Description: modified (diff)
Resolution: invalid
Status: newclosed

The grid basically just calls store.getValue() and passes the attribute to the store for handling. Your store would be the one that should support the dot notation.

Closing for now - please open another bug against the store you wish to have support dot-notation.

comment:7 Changed 6 years ago by gadLinux

That's not really true.

In the case of DGrid column rendering it's not calling the store anymore. In my case is a modified version of JsonRest?.

renderRow: function(object, options){
			var self = this;
			var row = this.createRowCells("td", function(td, column){
				var data = object;
				// Support get function or field property (similar to DataGrid)
				if(column.get){ // <-- IF you don't define this it will go without dot notation support
					data = column.get(object);
				}else if("field" in column && column.field != "_item"){
					data = data[column.field];
				}
				
				if(column.renderCell){
					// A column can provide a renderCell method to do its own DOM manipulation,
					// event handling, etc.
					appendIfNode(td, column.renderCell(object, data, td, options));
				}else{
					defaultRenderCell.call(column, object, data, td, options);
				}
			}, options && options.subRows);
			// row gets a wrapper div for a couple reasons:
			//	1. So that one can set a fixed height on rows (heights can't be set on <table>'s AFAICT)
			// 2. So that outline style can be set on a row when it is focused, and Safari's outline style is broken on <table>
			return put("div[role=row]>", row);
		},

So I see that there is only two ways to do it.

Implement a new column type that supports dot notation.

Insert dot notation support where it says:

data = data[column.field];

I prefer the second one because it adds global wide dot support. I have this implemented on my systems with just one additional function:

dotNotationGet: function(str, obj) {
			// summary:
			//		Accepts dot notation to get object properties
			// str: string
			//		The dot notation query string for the object
			// obj: object
			//      The object to query from.
			// returns: object
			//		Value of the property
			var keys = str.split('.');
			var parent = obj;

			for (var i = 0; i < keys.length - 1; i++) {
				var key = keys[i];
				if (key in parent) 
				{
					parent = parent[key]; // get next parent
				}else{
					parent=null;
					break;
				}
			}
			if(parent)
				return parent[keys[keys.length - 1]];
			
			return null;
		},

comment:8 Changed 6 years ago by gadLinux

Please reopen

comment:9 Changed 6 years ago by gadLinux

Sorry! This is not DGrid, this is DojoX/Grid. My fault

Note: See TracTickets for help on using tickets.