1

in a food truck app that I'm building, I have an order card component. On that order card component, it shows all the items that a user has in their order plus the count of each item. Where the count of each item is shown, I want to change that to render a select input where the default value of the select would be whatever count the user has already selected. I then want the user to be able to change the count using the select input.

Here is a screenshot of the component in the UI: enter image description here

What I want to change to a select input is the count to the left of each item in the order. For example, the first item in this order is chicken tacos. The count is 2. I want a select input there to be set dynamically to 2 but then that the user be able to increase or decrease the count of chicken tacos in their order if they so choose.

Here is the code from the component:

const OrderCard = props => {
    const orderCount = props.order.reduce(function(prev, cur) {
        return prev + cur.count;
    }, 0);

    return (
        <Card className="order-card-main">
            <i class="far fa-times-circle" style={{ position: 'relative', left: '0px', textAlign: 'left', width: '100%', marginTop: '3%', fontSize: '1.5rem' }} onClick={() => props.closeOrderCard()}></i>

            <h1 className="order-card-title">Your Order</h1>
            <p className="order-card-truck">from <span className="truck-name">{props.selectedTruck.name}</span></p>

            <div className="order-items-cont">
                {props.order.map(item => (
                    <div className="order-item-div">
                        <p className="order-item-count">{item.count}</p>
                        <p className="order-item-name">{item.item}</p>
                        <p className="order-item-total">{CurrencyFormatter.format(item.total, { currency: 'USD' })}</p>
                        <hr />
                    </div>
                ))}
            </div>

            <input className="order-note-input" type="text" placeholder="Note to truck..." />

            <button className="pay-button">
                <p className="total-items-count">{orderCount}</p>
                <p>Next step: pay</p>
                <p>{
                CurrencyFormatter.format(props.order.reduce(function(prev, cur) {
                    return prev + cur.total;
                }, 0), { currency: 'USD' })
                }</p>
            </button>
        </Card>
    )
}

const mapStateToProps = state => {
    return {
        selectedTruck: state.selectedTruck,
        order: state.order
    }
}

export default connect(mapStateToProps, { closeOrderCard })(OrderCard);

It's been really hard to find examples of this by Googling. Please let me know if you need any more context/info and thanks in advance for your help.

UPDATE:

For those asking why a select and not a regular input, I am just copying this design from what is on Uber Eats. I may use the idea suggested but I still want to know how I would do this using a select input. Here is a screenshot of the order component from Uber Eats:

enter image description here

3
  • 1
    I don't understand the use of a select instead of a simple input here, but you can still put your item.count inside and input, and trigger a method that edit your state on the 'onChange' event. Commented May 2, 2020 at 23:11
  • 1
    Agree with @QuentinGrisel, an input with type="number" will provide a numerical input a user can type in, but also provides a native increase/decrease button built in. Saves needing to populate a select's options. Commented May 2, 2020 at 23:17
  • @QuentinGrisel I updated my post to respond to your suggestion... Commented May 2, 2020 at 23:33

2 Answers 2

2

Here is your code modified with a select:

const OrderCard = (props) => {
  const [state, setState] = useState(props.order);

  const orderCount = props.order.reduce(function (prev, cur) {
    return prev + cur.count;
  }, 0);

  const displayOptions = (count) => {
    const options = [0, 1, 2, 3, 4, 5];

    return options.map((option) => (
      <option value={option} selected={option === count}>
        {option}
      </option>
    ));
  };

  const onSelectValueChange = (item) => {
    const selectedValue = document.getElementById('mySelect').value;
    // Do whatever you need with the value
    if(selectedValue === 0) {
      const newOrder = Object.assign({}, state); // better use deepclone() from lodash if you can
      for(let i = 0; i < newOrder.length; i++){
        const item = newOrder[i];

        if(item.id === item.id){
          newOrder.splice(i, 1);
          setState({...state, order: newOrder});
        }
      }
    }
  }

  return (
    <Card className='order-card-main'>
      <i
        class='far fa-times-circle'
        style={{
          position: 'relative',
          left: '0px',
          textAlign: 'left',
          width: '100%',
          marginTop: '3%',
          fontSize: '1.5rem',
        }}
        onClick={() => props.closeOrderCard()}
      ></i>

      <h1 className='order-card-title'>Your Order</h1>
      <p className='order-card-truck'>
        from <span className='truck-name'>{props.selectedTruck.name}</span>
      </p>

      <div className='order-items-cont'>
        {props.order.map((item) => (
          <div className='order-item-div'>
            <p className='order-item-count'>
              <select id='mySelect' onChange={() => onSelectValueChange(item)}>
                {displayOptions(item.count)}
              </select>
            </p>
            <p className='order-item-name'>{item.item}</p>
            <p className='order-item-total'>
              {CurrencyFormatter.format(item.total, { currency: 'USD' })}
            </p>
            <hr />
          </div>
        ))}
      </div>

      <input
        className='order-note-input'
        type='text'
        placeholder='Note to truck...'
      />

      <button className='pay-button'>
        <p className='total-items-count'>{orderCount}</p>
        <p>Next step: pay</p>
        <p>
          {CurrencyFormatter.format(
            props.order.reduce(function (prev, cur) {
              return prev + cur.total;
            }, 0),
            { currency: 'USD' }
          )}
        </p>
      </button>
    </Card>
  );
};

const mapStateToProps = (state) => {
  return {
    selectedTruck: state.selectedTruck,
    order: state.order,
  };
};

export default connect(mapStateToProps, { closeOrderCard })(OrderCard);

I assume you know the possible options to put in your select, else you really should use an input type='number' with min/max value if needed.

[Edit]: I added the delete option you wanted though the selectedValue of the select. The principle is the same with a button. I also assumed that you have a state with your order inside.

Sign up to request clarification or add additional context in comments.

3 Comments

Yeah, I was gonna put up to like 12 in the select. I also want an option to remove the item entirely that would be the 0 index of the select.
That not really user friendly to delete the item when you select 0. you should add a button 'x' which trigger a method to delete the given item, let me edit the code to add this option
const options = [...Array(12).keys()] ;) and for UI/UX, that is up for opinion, but I think it is common to have both a remove button and a "confirm update" button.
1

Is this the basic idea of what you're trying to do? I can add a bit more detail if it helps.
(It picks an option from the list using its index, so you may need to use the indexOf method first.)

const select = document.getElementById("select");
select.selectedIndex = 1;
<select id="select">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

(Reference: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select)

1 Comment

Yes, I think this is along the lines of what I want to do.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.