Current Magento pwa-studio provides you a dropdown field for quantity selection on product detail page which I found very amusing as it is literally useless for real world applications.
Quantity field on product details page only contains 1 to 4 quantity selection from dropdown and there is no option to the user to add more if he needs.
With this post, I will show you how we can replace this with an increment decrement field which makes more sense for a quantity field. I have created a separate component for this. Below are the things I did to achieve it.
First of all create a new component with name “ProductQuantityIncDec“
Create a new file pwa-studio/packages/venia-concept/src/components/ProductQuantityIncDec/index.js
This will be a simple index file.
export { default } from './quantity';
Create another file with name pwa-studio/packages/venia-concept/src/components/ProductQuantityIncDec/quantity.js
This file contains all the elements like quantity textbox, increment and decrement buttons and quantity update functionality.
import React, { Component } from 'react';
import { arrayOf, number, shape, string } from 'prop-types';
import classify from 'src/classify';
import defaultClasses from './quantity.css';
import { Text } from 'informed';
class Quantity extends Component {
static propTypes = {
classes: shape({
root: string,
increment_button: string,
decrement_button: string,
quaText: string,
quaBtn: string
})
};
state = {
quantity: 1,
show: true,
max: 9999,
min: 1
};
constructor(props) {
super(props);
this.ref = React.createRef();
}
incrementQty = () => {
this.setState(prevState => {
if(prevState.quantity < this.state.max) {
this.ref.current.value = this.state.quantity + 1;
this.props.clickHandler(this.state.quantity + 1);
return {
quantity: parseInt(prevState.quantity) + 1
}
} else {
return null;
}
});
};
decrementQty = () => {
this.setState(prevState => {
if(prevState.quantity > this.state.min) {
this.ref.current.value = this.state.quantity - 1;
this.props.clickHandler(this.state.quantity - 1);
return {
quantity: parseInt(prevState.quantity) - 1
}
} else {
return null;
}
});
};
handleChange =(event)=>{
let elementValue = parseInt(event.target.value) || 0 ;
if(elementValue != '' && elementValue != '0') {
this.setState({quantity: elementValue});
}
else {
this.setState({quantity: ''});
}
var event = new Event('input', { bubbles: true });
this.ref.current.dispatchEvent(event);
}
render() {
const { classes, ...restProps } = this.props;
return (
<div className={classes.root}>
<div className={classes.quaBtn}>
<span onClick={this.decrementQty} className={classes.decrement_button}>-</span>
</div>
<div className={classes.quaText} >
<Text
className={classes.quantity_input}
initialValue={`${this.state.min}`}
field="quantity"
label=""
forwardedRef={this.ref}
onChange = {this.handleChange}
/>
</div>
<div className={classes.quaBtn}>
<span onClick={this.incrementQty} className={classes.increment_button}>+</span>
</div>
</div>
);
}
}
export default classify(defaultClasses)(Quantity);
I have also added a css file to add styling for the elements.
.root {
display: flex;
width: 100%;
}
.quantityTitle {
font-size: 14px;
font-weight: normal;
margin: 0 0 10px 0;
}
.quantityBox {
display: table;
width: 100%;
height: 36px;
width: 100%;
}
.quaBtn {
display: inline-block;
width: 40px;
vertical-align: top;
height: 40px;
}
.quaBtn span {
border-radius: 4px;
background: #ebebeb;
height: 36px;
font-size: 28px;
line-height: 30px;
cursor: pointer;
width: 40px;
display: block;
text-align: center;
}
.quaText {
display: inline-block;
vertical-align: top;
width: 56px;
height: 36px;
padding: 0 5px;
}
.quaText input {
width: 100%;
height: 36px;
text-align: center;
border: #eeeeee solid 1px;
color: #333;
font-size: 15px;
font-weight: 700;
margin: 0;
border-radius: 4px;
}
.errormsg {
display: block;
font-size: 13px;
color:red;
}
That’s it. This is the component for quantity increment-decrement field. Now you can use it in your product details page to replace existing dropdown. To add the component on Product details page, edit your pwa-studio/packages/venia-concept/src/components/ProductFullDetail/ProductFullDetail.js file and import our newly created component.
import QuantityIncDecField from 'src/components/ProductQuantityIncDec';
Now replace the quantity dropdown code with below code to add our component.
<QuantityIncDecField clickHandler={this.setQuantity}/>
The component will display like below.