Daryl Spitzer
Daryl Spitzer

Reputation: 149364

How do I update a react-bootstrap-table2 cell value after it's edited so a button component in a different column has it?

I've setup a react-bootstrap-table2 (aka react-bootstrap-table-next) table like this:

function buttonFormatter(cell, row) {
  return (
    <NominateButton
      row={ row }
      auctionId={ auctionId }
      teamId={ teamId }
    />
  );
}

const queue_columns = [{
  dataField: 'player.num',
  text: 'Player Num',
  editable: false
}, {
  dataField: 'player.name',
  text: 'Player',
  editable: false
}, {
  dataField: 'player.position',
  text: 'Position',
  editable: false
}, {
  dataField: 'initialBid',
  text: 'Initial Bid',
}, {
  text: 'Nominate',
  formatter: buttonFormatter,
  editable: false
}];

return (
  <BootstrapTable
    bootstrap4={ true }
    keyField='player.num'
    data={ this.state.data }
    columns={ queue_columns }
    cellEdit={ cellEditFactory({ mode: 'click',
                                 blurToSave: true }) }
    striped
    hover />
);

Here's what the table looks like: enter image description here

The problem is that the row object is passed into the NominateButton component when the table is created, so when the initialBid column is updated that updated value is not updated in the row property to the NominateButton for that row. The NominateButton uses that initialBid value in a GraphQL mutation.

After an Initial Bid cell in a row is edited and changed, how do I somehow update the state of the NominateButton with that changed value?

Is there some way to specify a function name in the call to cellEditFactory (with the afterSaveCell key) and pass that function name as a property into NominateButton?

Upvotes: 1

Views: 5701

Answers (1)

Daryl Spitzer
Daryl Spitzer

Reputation: 149364

I solved the problem by creating a function that returns the edited value in that row and column and passing the function down into the button component:

  getInitialBid = (row) => {
    return this.state.data.find(r => r.rank === row.rank).initialBid;
  }

  render() {
    const { auctionId } = this.props;
    const { teamId } = this.props;

    const buttonFormatter = (cell, row) => {
      return (
        <NominateButton
          row={ row }
          auctionId={ auctionId }
          teamId={ teamId }
          getInitialBid={ this.getInitialBid }
        />
      );
    }

The getInitialBid function finds the row in the table's data (in the component's state) and returns the data from the editable (initialBid) column.

The NominateButton component passes that along to a NominateButtonMutator component:

class NominateButton extends Component {
  render() {
    const { row } = this.props;
    const { auctionId } = this.props;
    const { teamId } = this.props;
    const playerId = parseInt(this.props.row.player.id, 10);

    return (
      <NominateButtonMutator
        auctionId={ auctionId }
        teamId={ teamId }
        playerId={ playerId }
        row={ row }
        nominationsOpen={ data.team.nominationsOpen }
        subscribeToNominationsOpenChanges={ subscribeToMore }
        getInitialBid={ this.props.getInitialBid }
      />
    );
  }
}

And the NominateButtonMutator component calls the getInitialBid function and passes the return value as a variable to an Apollo mutation:

const NominateButtonMutator = (props) => {
  const [submitBid] = useMutation(SUBMIT_BID_MUTATION);

  return (
    <div>
      <Button
        disabled={ !props.nominationsOpen }
        onClick={ () => {
          let initialBid = props.getInitialBid(props.row);
          submitBid({ variables: { auction_id: props.auctionId,
                                   team_id: props.teamId,
                                   player_id: props.playerId,
                                   bid_amount: parseInt(initialBid, 10) } });
        }}
        variant="outline-success">
        Nominate
      </Button>
    </div>
  );
};

Upvotes: 1

Related Questions