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

How to pass editable state into column formatters #231

Open
JohnVLinton opened this issue Feb 27, 2018 · 14 comments
Open

How to pass editable state into column formatters #231

JohnVLinton opened this issue Feb 27, 2018 · 14 comments

Comments

@JohnVLinton
Copy link

JohnVLinton commented Feb 27, 2018

I am trying to implement a toggle button which has its own jsx inside one of the boostrap table's columns (for leftmost cell each row).

My issue is I can't seem to find a way to pass the parent's callback function from the react-bootstrap-table itself into a column formatter (i.e. there is no bind this allowed) such that a callback gets called from the parent that can change state based on whether someone hits the toggle button in each cell or not.

Basically my overall goal is to have some "parent rows" with expander button on left-hand most column and if a person hits that expander button it will change the state of a hiderow[] array of booleans and redraw the table data showing the once hidden child rows based on parent expansion. (These are basically the same display style as the parents, it's just that the parent expander button "uncoils them into view".)

Every other bit of the logic works in this pipeline except how to get a state-changing function passed to an external .jsx as a callback. Because as opposed to normal React parent-child interaction I have to somehow feed the callback function through the column formatter function, which seems to reside outside the React component that uses it (hence passing state functions not easy).

I have to go through the column formatter obviously because this toggle button appears on every single row and so has to be replicated, calling different ids, etc... I tried to use a generic column click event but lol can't get rowID from that nor grab the inner toggle imagebutton except for maybe low-level js. Similarly the row click event. (There does not appear to be a cell-click event but this too would need a further "zoom in" on the image button inside it).

@JohnVLinton JohnVLinton changed the title How to update state in cell components How to pass editable state into column formatters Feb 27, 2018
@resistancecanyon
Copy link

I'm also not able to update columns with dynamic data in the formatter: functions of column definition.
Each time state gets updated the column formatter: functions were never run

@resistancecanyon
Copy link

@JohnVLinton It is possible to do so.. formatters: are pure functions and you need to pass external state data using formatExtraData along with formatter
please check doc below
https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columnformatextradata-any

@clemlem
Copy link

clemlem commented Dec 6, 2018

I have the same issue. if I set formatExtraData: this.props.teams and the data attached to this cell or row with isDummyField: true, the cell doesn't update when this.props.teams change (immutability respected). Do you have the same problem?

I could be wrong but I think that the issue is it updates only if the number of column change

shouldUpdatedByNormalProps(nextProps) {
const shouldUpdate =
this.props.rowIndex !== nextProps.rowIndex ||
this.props.editable !== nextProps.editable ||
!_.isEqual(this.props.row, nextProps.row) ||
this.props.columns.length !== nextProps.columns.length;
return shouldUpdate;
}

It would be great to trigger rows update if formatExtraData is modified. Would this change work in should-updater.js? shouldComponentUpdate should be modified accordingly in cell.js too to track change on formatExtraData

    shouldUpdatedByNormalProps(nextProps) {
      const shouldUpdate =
        this.props.rowIndex !== nextProps.rowIndex ||
        this.props.editable !== nextProps.editable ||
        !_.isEqual(this.props.row, nextProps.row) ||
        this.props.columns !== nextProps.columns;

      return shouldUpdate;
    }

@AllenFang your thoughts?

@pastinepolenta
Copy link

Same here, passing this.state.something into formatExtraData does not seem to re-run the formatter

@senecaso
Copy link

senecaso commented Jul 21, 2019

Did any of your find a workaround for this? I'm hitting the same issue right now. For now, I'm using this dirty little hack to get around it by setting a hidden field to a random value on the desired row. That way, it forces a re-render

this.setState({ 
    data: data.map(row => {
        if (row.id == id) {
            return { ...id, dirty: Math.random() }
        }

        return row;
    });
}

@jvlinton
Copy link

Yes I believe there is a way we found (not right in front of me).

Key is for you to console.log() inside the formatter the objects and you should be able to find how to pass an additional property. You basically walk it out until you use up all the fields the library needs, (p1, p2, p3, ...) then the next space is where you can add your own, I think, if I recall right...

@anuragb26
Copy link

anuragb26 commented Aug 21, 2019

@jvlinton ,Could you please provide an example for this..i need to show a tooltip on hover of a cell..stuck with the same issue,state is updated but formatter is not being invoked.

 `formatter: (cell, row, rowIndex, { showTooltip }) => {
      console.log('in cel', cell) // not being logged when showTooltip is changed
      console.log('tooltipOpen in formatter', showTooltip)
      const tags = cell.split(',').filter(a => a)
      console.log('tags', tags)
      if (tags.length <= 2) {
        console.log('in first')
        return <div>{cell}</div>
      } else {
        return (
          <div>
            <div id={`TooltipExample${row.id.replace(/\//g, '')}`}>{`${
              tags[0]
            },${tags[1]} + ${tags.length - 2} more`}</div>
            <Tooltip
              placement="right"
              isOpen={showTooltip}
              target={`TooltipExample${row.id.replace(/\//g, '')}`}
              toggle={this.toggleTooltip}
            >
              {`${tags.slice(2).join(',')}`}
            </Tooltip>
          </div>
        )
      }
    },
    formatExtraData: {
      showTooltip
    }`

toggleTooltip = () => {
console.log('in toggle')
this.setState(prevState => ({ showTooltip: !prevState.showTooltip }))

}

@resistancecanyon
Copy link

I had to re-render the component with a show/hide react condition after trying to solve it for hours.
It used to work in previous version(^1.1) but after 2, i believe performance checks inside the component has made this update to not happen.

@DorienMay
Copy link

DorienMay commented May 5, 2020

The same issue for me unfortunately :/

EDIT #1: Upgrading to version 4.0.1 resolved my issue

@TempleClause
Copy link

@DorienMay

Do you have a working example? I still can't get this to work even on 4.0.1...

@jvlinton
Copy link

I'll try to find an example of the code... The secret to figuring out how is to console.log each of the things coming into the formatter, if I remember rightly, and keep adding params until you can add something new that the library isn't already sending in... Or else I think you can hack/overwrite the row object and return extra param or something like that

@adityaraj52
Copy link

Try: static keyword

  1. Bind the static method in constructor
    MyClass.showModal = MyClass.showModal.bind(this);

  2. Define the method
    static showModal() {
    this.setState({
    show: true
    })
    };

  3. Call the static method from Formatter method

const cellFormatter = () => {
return (
<Button className={'btn btn-primary'} onClick={MyClass.showModal}>Attend
);
};

@wiwsem
Copy link

wiwsem commented Sep 5, 2020

First set a key on the bootstrap table. When you update the data which you're not seeing reformatted, also change the key name of the bootstrap table. That will force React to re-rendered the table and your formatter method will, just like magic, do its thing.

@Hanh28111995
Copy link

did you find any solution for this ?

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

No branches or pull requests