15

How do I render nested JSON data on react material UI data grid. In the sandbox attached I want to show the phone numbers of the users from the json on the data grid-Nested JSON Data Grid

Learner Forever
  • 163
  • 1
  • 1
  • 5

5 Answers5

23

I use this in my project :

{ 
    field: 'idMaintenancePlan',
    headerName: 'Plan de maintenance', 
    sortable: false, width: 200, 
    valueGetter: (params) => params.row?.maintenancePlan?.name 
}
brismuth
  • 36,149
  • 3
  • 34
  • 37
TheoB
  • 231
  • 1
  • 2
  • 3
    In new v5 version - this will not work. Instead use valueGetter. – Naitik Soni May 30 '22 at 09:23
  • 2
    This works fine in v5 like valueGetter – Julián Jul 29 '22 at 22:36
  • 2
    Take into account that the value that we get from `valueFormatter` is not used for filtering and sorting so in the majority of cases using `valueGetter` will be a better solution. From [MUI Data-grid documentation](https://mui.com/x/react-data-grid/column-definition/#value-formatter): The value generated is only used for rendering purposes. Filtering and sorting do not rely on the formatted value. Use the valueParser to support filtering. – Ariel Gerstein Aug 01 '22 at 18:20
  • 1
    For current version, it's like following: `valueGetter: (params) => params.row?.jobType?.name` – Rafi Mahmud Mar 25 '23 at 03:24
18

To solve the problem, let's see params object passed in valueGetter function. Log that and you will find a row object under it. Instead of using params.getValue(), you should access the row object. It seems that params.getValue() can only be used on one-level JSON object. Here is the code snippet to output phone field.

  {
    field: "phone",
    headerName: "Phone",
    width: 160,
    valueGetter: (params) => {
      console.log({ params });
      let result = [];
      if (params.row.phone) {
        if (params.row.phone.home) {
          result.push("home: " + params.row.phone.home);
        }
        if (params.row.phone.office) {
          result.push("office: " + params.row.phone.office);
        }
      } else {
        result = ["Unknown"];
      }
      return result.join(", ");
    }
  }

Update

To have more flexibility on checking if every key under a object exists, I have created a helper method:

const checkKeysUnderObject = (obj, result) => {
  for (let key in obj) {
    if (key) { // push the value to the result array only if key exists
      result.push(key + ": " + obj[key]);
    }
  }
};

usage of the helper method:

if (params.row.phone) {
  checkKeysUnderObject(params.row.phone, result);
}else{
  result = ["Unknown"];
}

I have also updated the codesandbox here.

Janice Zhong
  • 836
  • 7
  • 16
  • 1
    The sandbox is returning errors... No row with id #firstName found – Adam Youngers Oct 13 '21 at 00:35
  • I worked around the error using this: valueGetter: params => `${params?.params?.row?.firstName || ""} ${params?.params?.row?.lastName || ""}` – Adam Youngers Oct 13 '21 at 00:47
  • Also, are we saying that sorting is not an option for nested object responses? I'm currently on the fence as to this approach or passing API response through a method to flatten it so `,phone:{home:"11", office:"22" }` would become `,phone_home:"11", phone_office:"22"` – Adam Youngers Oct 13 '21 at 00:58
8

this works fine for me

{ field: 'parserInfo', headerName: 'Parser Title', valueFormatter: ({ value }) => value.title }
Manish Rawat
  • 1,142
  • 1
  • 18
  • 34
6

this works fine also

{
     field: "family",
     headerName: "Family",
     width: 150,
     renderCell: (params) => {
       return <div className="rowitem">{params.row.family.name}</div>;
     },
},
saberbouagila
  • 69
  • 1
  • 1
  • suggestion : you can use code fences instead of snippets since the snippet feature here is not necessary, also add a language identifier to highlight the code based on the language and make it more readable – I_love_vegetables Jul 14 '21 at 08:45
0

This one worked for me:

const columns = [
    { 
        field: "post", 
        headerName: "TITLE", 
        valueFormatter: (post: any) => post.value.title
    }
]

In my case post is a property of the tutorial entity.

<DataGrid
    rows={tutorials}
    columns={columns}
    slots={{
        toolbar: GridToolbar,
    }}
/>

The Tutorial entity

export interface Tutorial {
    id: number;

    ...

    post: Post;
}

... and the Post entity.

export interface Post {
    id: number;
    title: string;

    ...
}
PeterPazmandi
  • 533
  • 10
  • 13