Ajay Gupta
Ajay Gupta

Reputation: 2033

How can I set refs and assign values to looped elements in ReactJS

I am having trouble in setting the values to looped elements in React.js

What I am trying to achieve is, there's a list of items:

[{ id: 1, rate: 120 } ...]

I want to create 4 text boxes: Rate, Total Cost, Advance and Balance.

Total cost is calculated using the rate and another property from the object, size (rate * size). Now, everytime rate changes, I want to calculate the total cost, and assign it to the respective row's total cost textbox. Also, on first load, the textboxes should be pre-filled with these calculated values.

array.forEach((item) => {
  <div>
    <input type="text" ref/id={`item_r_${item.id}`} /> // Rate
    <input type="text" ref/id={`item_r_${item.id}`} /> // Total Cost
    <input type="text" ref/id={`item_r_${item.id}`} /> // Advance
    <input type="text" ref/id={`item_r_${item.id}`} /> // Balance
  </div>
})

How can I achieve this?

I've tried using refs but couldn't get it to work.

Thanks!

Upvotes: 1

Views: 333

Answers (1)

Ahsan Ali
Ahsan Ali

Reputation: 5135

I have a solution without using refs, it updates the value of inputs with their index.

UPDATE

Calculation of advance and balance is added in function calculateBalance and onChangeAdv respectively.

class App extends React.Component {

  constructor() {
    super();
    this.state = {
      data: [
        { id: 1, rate: 120, size: 3, adv: 0 },
        { id: 2, rate: 150, size: 7, adv: 0 },
        { id: 3, rate: 180, size: 5, adv: 0 }
      ]
    };
  }
  onChange(e, i) {
    const data = [...this.state.data];
    data[i].rate = e.target.value;
    data.splice(i, 1, data[i]);
    this.setState({ data });
  }

  onChangeAdv(e, i) {
    const data = [...this.state.data];
    data[i].adv = e.target.value;
    data.splice(i, 1, data[i]);
    this.setState({ data });
  }

  calculateBalance(i) {
    let { data } = this.state;
    let bal = 0;
    bal = (data[i].rate * data[i].size) - data[i].adv;
    return bal;
  }

  render() {
    let { data, adv } = this.state;
    return (
      <div>
        {data.map((item, i) => {
          return (
            <div key={i}>
              <input
                type="text"
                value={item.rate}
                onChange={e => this.onChange(e, i)}
              />
              // Rate
              <input type="text" value={item.rate * item.size} /> // Total Cost
              <input type="text" value={item.adv} onChange={e => this.onChangeAdv(e, i)} /> // Advance
              <input type="text" value={this.calculateBalance(i)} /> // Balance
              <br />
              <br />
            </div>
          );
        })}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Upvotes: 1

Related Questions