Reputation: 1774
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:
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:
Upvotes: 1
Views: 317
Reputation: 4987
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.
Upvotes: 2
Reputation: 4246
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)
Upvotes: 1