Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dataField can't access subobject #50

Closed
kopax opened this issue Sep 11, 2015 · 51 comments
Closed

dataField can't access subobject #50

kopax opened this issue Sep 11, 2015 · 51 comments

Comments

@kopax
Copy link

kopax commented Sep 11, 2015

I have an object which is like that

{
  "person_id": 1,
    "username": "UserTest",
    "created_at": "2015-09-10T21:13:56.000Z",
    "updated_at": "2015-09-10T21:13:56.000Z",
    "deleted_at": null,
    "Person": {
          "id": 1,
          "firstname": "UserTest",
          "lastname": "Obama",
          "note": "DevOps",
          "email": "iam@obama.com",
          "created_at": "2015-09-10T21:13:56.000Z",
          "updated_at": "2015-09-10T21:13:56.000Z",
          "deleted_at": null
    }
}

I can't access the subojbect using

<TableHeaderColumn dataField="Person.firstname">Firstname</TableHeaderColumn>

Is there any workaround not specified in the doc ?

@AllenFang
Copy link
Owner

Hi @kopax, the nested object does not supported on newest version in this component, sorry for that. But I can add it in the future, but this is not in my plan, so I need more plan or thinking on this feature. :)

@kopax
Copy link
Author

kopax commented Sep 12, 2015

I have made a little modification in TableBody.js
I don't know if this is enough for the rest of the feature provided by your lib, could you check a quick look ?

/blob/master/lib/TableBody.js line 101 replaced by :

        var fieldValue = null;

        if( column.name.indexOf('.') != -1 ){
          var depth = column.name.split('.');
          while(depth.length > 0){
            fieldValue = fieldValue ? fieldValue[depth.shift()] : data[depth.shift()]
          }
        }
        else{
          fieldValue = data[column.name];
        }

What do you think ?
I think you should also handle errors.

Edit: I have just tried with filter field, doesn't work (input placeholder is "Person.firstname")

@AllenFang
Copy link
Owner

Hi @kopax , it's a way to implement this feature and I think it will be OK. but there are a lots of feature in this component, include cell edit, filter ..etc. so I need to consider these part for design this feature, so it will take some time. Anyway, if you just want to "display" the nested data on component, I think your solution is ok :)

@kopax
Copy link
Author

kopax commented Sep 15, 2015

Hi @AllenFang , I am really trying hard to implement subobject management but the problem is that some comments are missing in your code.
Could you provide me further runtime details ?

My idea would be to add a dataPath="Person" to TableHeaderColumn props

@AllenFang
Copy link
Owner

Hi @kopax , did you folk my project? I cant find your repository. I thinks I can spend a little time to watch out your folk and help you debug :)

@kopax
Copy link
Author

kopax commented Sep 15, 2015

I didn't for some (stupid) reasons :

I have two table Person and User
User doesn't have a primaryKey, the indexKey in User is person_id

The current add/edit feature add new User instance to dataSet with wrong nested Object (created key is "Person.firstname", insteand of "Person": { "firstname": ... }

I think I can't use this feature so I will need to do a bunch of modification just for my needs

@AllenFang
Copy link
Owner

Hi @kopax, you mean you want the add/edit feature work with nested object? If yes, I thinks it's a very very hard work. And you really cant solve the problem on your side, I can help you, but you need give me your folk first

@lebeier
Copy link

lebeier commented Jan 28, 2016

This feature is definitely welcomed. the fact that it does not support nested objects make it feel rather rigid in design. I hope to see this implemented soon =)

@kopax
Copy link
Author

kopax commented Jan 28, 2016

@AllenFang sorry for not replying. I really liked your table unfortunately I wasn't able to implement anything in your code.
I would also love to reuse react-bootstrap-table in the futur so +1 for adding the feature

@AllenFang
Copy link
Owner

that's ok, I know this feature is very important, but I'm busy and there are lot of things to do, so I prefer to fix bug first. If I've free time, I'll come back and support this features. Anyway, PR is welcome :)
Thanks

@juancarlosfarah
Copy link

+1
Will try and have a look at this too!

@ronsc
Copy link

ronsc commented Feb 2, 2016

+1

1 similar comment
@VenkataKotra
Copy link

+1

@awlh
Copy link

awlh commented Jun 21, 2016

+1

2 similar comments
@ZacharyKlein
Copy link

+1

@daniel1943
Copy link

+1

@nguyenchanhnghia
Copy link

using dataFormat to rewrite this cell .

@kopax
Copy link
Author

kopax commented Jul 15, 2016

I did have a look at the code and this seems complicated to implement the way it is made. I doubt this feature will be added in the futur.

@AllenFang
Copy link
Owner

AllenFang commented Jul 18, 2016

@kopax, yes, it's little hard to implement.. I only have a way, is create a preparer and flat the nested object according user's defined and take this flatted object into table. I prefer to tackle v3.0.0 and go back to check my idea whether is work or not.

Sorry, make this issue pending...

@kopax
Copy link
Author

kopax commented Jul 19, 2016

Ok, all I can say is thanks for sharing the code. Wait & see

@galpratama
Copy link

Really need this feature too..

@welcoMattic
Copy link

👍 Is there any fork of this project with this feature?

@AllenFang
Copy link
Owner

#508 (comment)

@Obiwarn
Copy link

Obiwarn commented Sep 22, 2016

+1

@gengjiawen
Copy link

You can use formatExtraData to hack

const column_meta = [
    {columnName: 'user_detail.phone_number', displayName: 'User Phone'},
];

function extraFormatter(cell, row, extra) {
  return eval(`row.${extra}`);
}

let columns = column_meta.map(i => {
    return <TableHeaderColumn dataField={i.columnName} dataFormat={extraFormatter} formatExtraData={i.columnName}>
        {i.displayName}</TableHeaderColumn>
      });

then add colunms to BootstrapTable.

@AllenFang
Copy link
Owner

@gengjiawen, I will. Sorry for making this feature delay

@gengjiawen
Copy link

And this is quite common case if you are using graphql.However, you can easily hack it even without eval, google js flattern object you will get the answer.

@alanqthomas
Copy link

+1
Working around it is fairly simple, but it shouldn't need a workaround at all.

@ferrwan
Copy link

ferrwan commented Feb 14, 2017

I'm using lodash's _.get lib to achieve this.

import _ from 'lodash'

const renderCustom = (cell, row, extra) => {
    const value = _.get(row, extra.path)
    return <div>{value}</div>
}

const columns = [
    {path: 'Person.firstname', title: 'Firstname'},
    {path: 'Person.lastname', title: 'Lastname'},
    {path: 'this.is.a.long.path.of.an.object', title: 'Long Path'},
]

const tableColumn = _.map(columns, (column) => (
    <TableHeaderColumn
        dataField={column.path}
        dataFormat={renderCustom}
        formatExtraData={column}
    >{column.title}</TableHeaderColumn>
))

@Siyfion
Copy link

Siyfion commented Mar 17, 2017

I was just about to add to this... Why can't we simply make a PR that uses both the lodash _.get:
https://lodash.com/docs/4.17.4#get
and _.set:
https://lodash.com/docs/4.17.4#set

When retrieving and setting values?

@nivek91
Copy link

nivek91 commented Apr 5, 2017

+1 still no fix for this?

@nivek91
Copy link

nivek91 commented Apr 5, 2017

@ferrwanz the key is missings in your code:

import _ from "lodash";

const renderCustom = (cell, row, extra) => {
const value = _.get(row, extra.path);
return

{value}
;
};

const columns = [
{ path: "CPA", title: "cpa", isKey: true },
{ path: "entreCalles.calleA", title: "entreCa" }
];

const tableColumn = _.map(columns, column => (
<TableHeaderColumn
dataField={column.path}
dataFormat={renderCustom}
formatExtraData={column}
isKey={column.isKey}
key={column.path}

{column.title}
));

@aaronryden
Copy link

hey @nivek91, any thoughts on sorting this nested field?

@nivek91
Copy link

nivek91 commented Apr 6, 2017

which field @aaronhayes ?

@PraxentSupport
Copy link

I solved the issue without modification of the project 👍
<TableHeaderColumn dataField='Contact' dataFormat={ this.contactFormatter } >Contact</TableHeaderColumn>

and the function :
contactFormatter(cell, row){ return ${cell.first} ${cell.last}; }

@logolevel
Copy link

logolevel commented Jun 22, 2017

Working example with the required field is the key. Thanks to ferrwanz and nivek91.

import _ from 'lodash';

const renderCustom = (cell, row, extra) => {
	const value = _.get(row, extra.path);
	return <div>{value}</div>;
};

const columns = [
	{ path: "id", title: "ID", isKey:true },
	{ path: "animal.cat", title: "Cat" },
];

const tableColumn = _.map(columns, column => (
	<TableHeaderColumn
		dataField={column.path}
		dataFormat={renderCustom}
		formatExtraData={column}
		isKey={column.isKey}
		key={column.path}
	>{column.title}</TableHeaderColumn>
));

Then you need to add to the method render, next code:

render() {
	return(
		<BootstrapTable data={ transactionData }>
                     {tableColumn}   
		</BootstrapTable>
	);
}

@kopax
Copy link
Author

kopax commented Jun 22, 2017

@logolevel does all the features works ?

@logolevel
Copy link

kopax, yes.

@romainPellerin
Copy link

@logolevel thanks so much for this example.

I am trying to aggregate data within one column like animal.firstname + animal.lastname into a path (yes I named my cat with a full name ;)).

Does any one have a solution for that?

@StohlmanMatteo
Copy link

StohlmanMatteo commented Jul 12, 2017

building on @PraxentSupport's response. I'm using:
function objectFormat(data, cell) { if(data.constructor===Array){ if(data[0]=='last'){ return <p>${cell[data.length-1][data[1]]}</p> } return <p>${cell[data[0]][data[1]]}</p> } return <p>${cell[data]}</p>; }

dataFormat={ objectFormat.bind(this, [0,'address'])}
or
dataFormat={ objectFormat.bind(this, 'number')}

Note: need to ad ` around return values.

@janpauldahlke
Copy link

@StohlmanMatteo
works fine for me, thanks. just a quick note for all the other coming from google. just hsow how to use `` :-)

@georgewritescode
Copy link

Building off the above: (This is using lodash but can work out how to use if dont want to use lodash/underscore)

First create a method in your react component like this replacing 'datapropertywithnested.nestedpropertyname' this your specifics:

depthFormatter(cell, row)
    { 
        console.log("contactFormatter")
        console.log(row)
        console.log(cell)
        let val =  window._.get(row,'datapropertywithnested.nestedpropertyname');
        return <div>{val ? val : 'none found'}</div>;
    }

Then in your table:
<TableHeaderColumn dataField='anything' dataFormat={this.depthFormatter}> Custom </TableHeaderColumn>

@georgewritescode
Copy link

georgewritescode commented Aug 19, 2017

However the above solution doesn't support filtering

As such I found the easiest solution is to modily your data before it enters the table to flatten it, such as through:

 let data = tableData;
        data = data.map((item,index) => {
            if(_.has(item,'contact_company.name')) {
                item.contact_company_name = item.contact_company.name;
            }
            return item;
        });

Table as regular:

<BootstrapTable data={data}>
<TableHeaderColumn filter={{ type: 'TextFilter', delay: 100 }} dataSort={true} dataField='contact_company_name'>
Company Contact Name
</TableHeaderColumn>
</BootstrapTable>

@AllenFang
Copy link
Owner

AllenFang commented Aug 20, 2017

sorry guys, as I mention on README, I already decide to create react-bootstrap-table2, I trust it will be better than react-bootstrap-table. A good news is I'll support the nested data in react-bootstrap-table2 start from v0.0.1, bad news is I will not support the nested data in react-bootstrap-table.

Feel free to let me know your idea and any idea/issues is welcome on react-bootstrap-table2

Sorry for inconvenience.

@maxpdx
Copy link

maxpdx commented Dec 12, 2017

Any updates?

@Ogglas
Copy link

Ogglas commented Dec 25, 2017

To people finding this thread: Using lodash works well with displaying data but the data presented will not be searchable or sortable.

import _ from 'lodash'

const renderCustom = (cell, row, extra) => {
    const value = _.get(row, extra.path)
    return <div>{value}</div>
}

const filterValue = (cell, row) => {
        //Cells that are subobjects won't hit this metod
        debugger; 
 }

const columns = [
    {path: 'Person.firstname', title: 'Firstname'},
    {path: 'Person.lastname', title: 'Lastname'},
    {path: 'this.is.a.long.path.of.an.object', title: 'Long Path'},
]

const tableColumn = _.map(columns, (column) => (
    <TableHeaderColumn
        dataField={column.path}
        dataFormat={renderCustom}
        formatExtraData={column}
        filterValue={filterValue}
    >{column.title}</TableHeaderColumn>
))

@AdnanBoota
Copy link

AdnanBoota commented Mar 15, 2019

@Ogglas any idea about sorting the field? or any approach to dataSort and also dataFormat with formatExtraData?

image

Thanks.

@AdnanBoota
Copy link

AdnanBoota commented Mar 29, 2019

To go furthher into nested fields, i'm passing string and then returning the key/value pair.

const nestedFields = (data, row, field) => {
  let nested_field = field.split(',');
  return data[nested_field[0]][nested_field[1]];
}

<TableHeaderColumn row='1' dataField="torque_sensor" formatExtraData="top_hits,process" dataFormat={nestedFields} dataSort>Process</TableHeaderColumn>

@mcmwhfy
Copy link

mcmwhfy commented Apr 10, 2019

Or the simplest way:

tableDataFormat(cell, index){ 
    return (
    <React.Fragment>
        <span className="d-block">{index.name}</span> 
        <span className="d-block">{index.location}</span>
    </React.Fragment>)
}

<TableHeaderColumn dataSort={ true } dataFormat={this.tableDataFormat}>Name </TableHeaderColumn>

you need also dataField only if you are using isKey={ true } on element

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.