ng2-smart-table icon indicating copy to clipboard operation
ng2-smart-table copied to clipboard

How to use the nested JSON object through setting?

Open sskmail14 opened this issue 8 years ago • 38 comments

Hi I have a nested JSON

[country:{
    "name":"India",
     "states":{
                   [{
                     .................
                    }]
                  }

}
...
]

I have tried but doesn't work :(

settings:{
        columns:{
              country:{
                    title:"Countries"
              },
              country.states:{
                     title:"States"
              }
        }
}

sskmail14 avatar Dec 03 '16 07:12 sskmail14

Hi @sskmail14 have you find any solution for this ??

noboddee avatar Dec 30 '16 16:12 noboddee

@noboddee Its a work around and bad practice, but still I will let you know, i have copied the properties to the master JSON from nested JSON.

But that's not the proper solution.

sskmail14 avatar Dec 31 '16 13:12 sskmail14

having the same requirement. Need to display some attribute values of nested objects.

thilina01 avatar Feb 14 '17 06:02 thilina01

Hi, same requirement for me too. It would be great and more flexible.

BoyardIsBack avatar Feb 24 '17 10:02 BoyardIsBack

@thilina01 @BoyardIsBack Temporary Solution : Have the all the properties in the main JSON that you want to use.

But this not the proper solution.

sskmail14 avatar Feb 27 '17 06:02 sskmail14

@sskmail14 Thanks, I just rebuild a proper array from my nested JSON.

BoyardIsBack avatar Mar 02 '17 08:03 BoyardIsBack

Is there a better solution than flattening our nested JSON Objects ?

tanzeelrana avatar Mar 30 '17 08:03 tanzeelrana

`Need to flatten the objects,

Params :

objects : at least n>0 array off JSON objects (dose not matter is circular) target : {} path : ""

Note : make sure the Objects Array passed in is n>0 at least

flatten(objects, target, path) {
let me = this;    
let retArray = [];
for(let x=0; x < objects.length; x++) {
  
  let object = objects[x];
  path = path || '';
  target={};
  
  target = me.flattenHelper(object, target, path);
  
  retArray.push(target);
}
return retArray;}

..

flattenHelper(object, target, path){
let me = this;
Object.keys(object).forEach(function (key) {
  console.log("key : "+ key + " : object : " +  (object[key] && typeof object[key] === 'object') + " path : " + path);
  if (object[key] && typeof object[key] === 'object') {
      me.flattenHelper(object[key], target, path + key);
  }
  target[path + key] = object[key];
  console.log(target);
});
return target;}`

tanzeelrana avatar Mar 30 '17 09:03 tanzeelrana

Hi guys, I found a sollution: Use valuePrepareFunction for each element you need to prepare the value:

settings:{
        columns:{
              country:{
                    title:"Countries"
              },
              country:{
                     title:"States",
                     valuePrepareFunction: (country) => {
                         return country.state;
                     }
              }
        }
}

more on https://akveo.github.io/ng2-smart-table/#/documentation

OrenciucEvghenii avatar Apr 26 '17 15:04 OrenciucEvghenii

@OrenciucEvghenii Thanks... This looks good... So closing this issue.

sskmail14 avatar Apr 27 '17 05:04 sskmail14

@sskmail14, Hi again, no, it's not enough. so you can't duplicate fields in JS. Compiler says, that it's impossible to have duplicate field names in strict mode. So, the solution is possible, but not completely. Issue is still open, i think

OrenciucEvghenii avatar Apr 27 '17 08:04 OrenciucEvghenii

@OrenciucEvghenii Does the above example has the flaw or in some other example? If so can you kindly illustrate?

sskmail14 avatar Apr 27 '17 08:04 sskmail14

Hi guys! I'm facing the same @OrenciucEvghenii mentionated.

I have a json like this :

{ "group" : "tatuape", "publisher" : { "pubName" : "Valter Junior" }, "houseHolder" : { "hhName" : "Osas", "hhGender" : "male", "hhNationality" : "nigerien", "hhPhone" : "11979620954", "address" : { "hhZipCode" : "08275340", "hhAddress" : "Rua xavier Palmerim", "landmark" : "asf" } }, "status" : { "status" : "visit", "pubName" : "Aline Nascimento" }, "hhNotes" : "Teste", "_id" : ObjectId("590af6bfb8fb493797b5b269") }

I need to present it into smart-table, but when I try to get the value of houseHolder.hhName and houseHolder.hhGender it is not allowed, because as I understood, to valuePrepareFunction works the key of columns always need to be the wrapper, in this case houseHolder

valter-jnr avatar May 04 '17 10:05 valter-jnr

@juniorsml did you find a way around this?

hgarc014 avatar Jun 06 '17 23:06 hgarc014

Same as @OrenciucEvghenii.

Code: screen shot 2017-07-01 at 17 38 59

And the error pop-up: screen shot 2017-07-01 at 17 36 25

pulfabio avatar Jul 01 '17 10:07 pulfabio

I'm in the same situation of pulfabio. Any solution?

Gradiusso89 avatar Jul 20 '17 10:07 Gradiusso89

Issue exists so opening this issue.

sskmail14 avatar Jul 25 '17 15:07 sskmail14

I solved this problem using type "custom" and then render an external component

Gradiusso89 avatar Jul 25 '17 15:07 Gradiusso89

@Gradiusso89 Can you kindly provide some sample snippet. So that it might help for the others to understand.

sskmail14 avatar Jul 27 '17 17:07 sskmail14

I have fixed the issue by using (cell, row) here is code snippet: initiator: { title: "Started By", type:'string', valuePrepareFunction: (cell,row) => { return row.startedBy.lastName; } }, email: { title: "Email", type:'string', valuePrepareFunction: (cell,row) => { return row.startedBy.email; } }, Hope it works for you too. :)

hamdullah avatar Aug 18 '17 08:08 hamdullah

Thanks @hamdullah ! Your solution works very well! and here's my version.

  settings = {
    mode: 'external',
    columns: {
      driverName: {
        title: 'Driver Name',
        valuePrepareFunction: (driver, trip) => {
          return `${trip.driver.firstName} ${trip.driver.lastName}`;
        }
      },
      driverContact: {
        title: 'Driver Contact',
        valuePrepareFunction: (driver, trip) => {
          return trip.driver.phoneNumber;
        }
      },
      status: {
        title: 'Status'
      },
      ratingByPassenger: {
        title: 'Rating'
      }
    }
  }

crossRT avatar Aug 30 '17 23:08 crossRT

The above solution does not seem to work with sorting

FJB-ZA avatar Sep 20 '17 14:09 FJB-ZA

I just referenced the nested properties by accessing it through the row argument that gets passed into the valuePrepareFunction. That seems to work pretty well for now.

mattmelgard avatar Sep 20 '17 18:09 mattmelgard

@hamdullah @mattmelgard and @crossRT If you use this logic, you will be able to display the table correctly but sorting and searching functionality of table wont work.

dgpuranik avatar Oct 26 '17 08:10 dgpuranik

@dgpuranik I agree, I'm having the same problem.

mathuranubhav avatar Nov 14 '17 19:11 mathuranubhav

Also here, you can display it right, but you can search, filter or edit. This is not working for me.

sophiecmusical avatar Feb 13 '18 09:02 sophiecmusical

Hello, Is there actually a solution for the filter and edit problem by using the logic of the cell and row ? Thanks

djibythiaw avatar May 01 '19 17:05 djibythiaw

You can also use filterFunction() to use filtering with nested JSON.

filterFunction(fieldname?: any, search?: string): boolean { if (fieldname.nestedvalue === search) { return true; } else { return false; } }

melaniecarr23 avatar Sep 26 '19 18:09 melaniecarr23

Same as @OrenciucEvghenii.

Code: screen shot 2017-07-01 at 17 38 59

And the error pop-up: screen shot 2017-07-01 at 17 36 25

I have same probleme? any solution? please, is urgent

jmgomez1986 avatar Oct 02 '19 13:10 jmgomez1986

Thanks @hamdullah ! here another example

getSettingSmartTable(){
    return {
      columns: {
        id: {
          title: '#Venta'
          // ,width: '15%'
          ,filter:false
        }
        ,precio: {
          title: 'Precio'
          ,type: 'number'
          ,filter:false
        }
        ,codigo:{
           title:"Codigo"
          ,filter:false
          ,valuePrepareFunction: (cell,row) => {
               return row.articulo.codigo;
           }
        }
        ,articulo:{
           title:"Articulo"
          ,filter:false
          ,valuePrepareFunction: (cell,row) => {
               return row.articulo.descripcion;
           }
        }
        ,cantidad: {
          title: 'Cantidad'
          ,type: 'number'
          ,filter:false
        }
        ,total: {
          title: 'Total'
          ,type: 'number'
          ,filter : false
        }
      }
      ,noDataMessage : 'Todabia no se registraron ventas el dia de hoy'
    };
  }// end getSettingSmartTable

and a json example.

{
  "data": [
    {
      "id": 1,
      "precio": "25.00",
      "costo": "15.00",
      "total": "25.00",
      "cantidad": 1,
      "articulo_id": 1,
      "created_at": null,
      "updated_at": null,
      "articulo": {
        "id": 1,
        "codigo": "7791669001103",
        "descripcion": "Bicarbonato Indias x25g",
        "stock": 0,
        "stock_minimo": null,
        "unidad_medida": "UNIDAD",
        "precio": "25.00",
        "costo": "15.00",
        "fecha_desde": "2020-01-04",
        "created_at": null,
        "updated_at": null
      }
    }
  ]
}

MallonEmanuel avatar Jan 04 '20 05:01 MallonEmanuel

Thanks @MallonEmanuel

I have tried you example.

But Your example don't work with data format like this.

[ {"name": "Product 1", "series":[{"name":"Area 1","value":3},{"name":"Area 2","value":1}] }, {"name":"Product 2", "series":[{"name":"Area 2","value":3}] } ];

What can I do to make it work?

I have tried it with with series[0].name. This work but shows me only one entry and not all.

Kind regards

nicole-ge avatar Jan 28 '20 14:01 nicole-ge

Hi @nicole-ge !! the getSettingSmartTable function is used to return the table configuration

with this data:

[{"name": "Product 1",
"series": [{"name": "Area 1", "value": 3}, {"name": "Area 2", "value": 1}]},
{"name": "Product 2",
"series": [{"name": "Area 2", "value": 3}]}
];

If you want to see something like this, you could get the max size of serial arrays and programmatically build the table configuration.

| Product | series [0] | series [1] |
| Product1 | Area 1    |    Area2   |
| Product2 | Area 2    |                 |

But generally when you want to see the contents of two arrays, where one depends on the another you could use master-detail. Or maybe I'm not understanding what you want to do. You could also tell me how you want to see the data, that would help a lot.

Finally if you want a table similar to the following, where series is a selec list.

| Product | Series |
| Product1 | Area 1  |
| Product2 | Area 2  |
getSettingSmartTable () {
    return {
      columns: {
         name: {
           title: 'Product'
         },
        ,Serie: {
          title: 'series'
          ,editor:{
              type: 'list'
              , config: {
                  selectText: 'Select'
                  , list: [
                      {value: 1, title: 'Area 1'}
                      , {value: 2, title: 'Area 2'}
                  ]
              }
          }
        }
   }; // end return
} // end getSettingSmartTable

MallonEmanuel avatar Jan 29 '20 01:01 MallonEmanuel

Hi guys, I found a sollution: Use valuePrepareFunction for each element you need to prepare the value:

settings:{
        columns:{
              country:{
                    title:"Countries"
              },
              country:{
                     title:"States",
                     valuePrepareFunction: (country) => {
                         return country.state;
                     }
              }
        }
}

more on https://akveo.github.io/ng2-smart-table/#/documentation

Doing this works fine. But the filter doesn't work on the values. Any solution to cater the filter as well?

muneebattamindravel avatar Jun 09 '20 21:06 muneebattamindravel

I have fixed the issue by using (cell, row) here is code snippet: initiator: { title: "Started By", type:'string', valuePrepareFunction: (cell,row) => { return row.startedBy.lastName; } }, email: { title: "Email", type:'string', valuePrepareFunction: (cell,row) => { return row.startedBy.email; } }, Hope it works for you too. :)

Thanks @hamdullah Doing this displays the value fine, but sorting and filtering doesn't work. Any solution for this?

muneebattamindravel avatar Jun 09 '20 21:06 muneebattamindravel

Thanks @hamdullah ! Your solution works very well! and here's my version.

  settings = {
    mode: 'external',
    columns: {
      driverName: {
        title: 'Driver Name',
        valuePrepareFunction: (driver, trip) => {
          return `${trip.driver.firstName} ${trip.driver.lastName}`;
        }
      },
      driverContact: {
        title: 'Driver Contact',
        valuePrepareFunction: (driver, trip) => {
          return trip.driver.phoneNumber;
        }
      },
      status: {
        title: 'Status'
      },
      ratingByPassenger: {
        title: 'Rating'
      }
    }
  }

Hi @crossRT Doing this displays the value fine, but sorting and filtering doesn't work. Any solution for this?

muneebattamindravel avatar Jun 09 '20 21:06 muneebattamindravel

You may consider flattening your JSON object. See topic: Fastest way to flatten / un-flatten nested JSON objects You can also take a look at lodash flatten, flattenDeep, and flattenDepth functions.

almawhoob avatar Jul 05 '20 15:07 almawhoob

@hamdullah solution works. However in order for the filtering to work you need to do something like this:

` filterFunction(rowValueObject?: any, search?: string): boolean {

      if (rowValueObject.propertyName.toUpperCase().includes(search.toUpperCase())) {
           return true;
      } else {
           return false;
      }
    }

`

NOTE: Replace the propertyName with the property in your nested json. Then only it will work

Fayiz-A avatar Jan 02 '21 12:01 Fayiz-A

Something Like This:

settings = {
columns: {
name: {
title: 'Driver Name',
valuePrepareFunction: (cell, row) => { return row.driver.name; },
filter: false
},
mobilenumber: {
title: 'Mobile Number',
valuePrepareFunction: (cell, row) => { return row.driver.mobilenumber; },
filter: false
},
},
}

thapliyalmanoj avatar Apr 12 '22 18:04 thapliyalmanoj