[enter image description here](https://i.stack.imgur.com/f7Tss.png)
I wanted to make a Range Slider in text input fields, but the following problem appeared: when I plan to enter a new minimum or maximum value into the slider text field, I have to delete the old value before entering a new one. And while deleting the old one, the green background shifts outside the slider.
How can I fix this problem when changing the value? Because the slider is almost done, but this problem does not allow us to complete the task completely.
Maybe the solution is to not be able to enter a value less than the one initially set? For example, initially minValue=100 and 99 cannot be entered. So that the search range is only higher than the original one.
And how can you make sure that the new value is not set until it is completely entered?
I published this task in codesandbox: https://codesandbox.io/p/devbox/price-range-slider-zwfzyz?file=%2Fsrc%2Frange-slider%2FrangeSlider.scss%3A32%2C24
[enter image description here](https://i.stack.imgur.com/f7Tss.png)
And provide code below
Thanks for any help
React code
function MultiRangeSlider({ minPrice, maxPrice, onChange }) {
const [minPriceVal, setMinPriceVal] = useState(minPrice);
const [maxPriceVal, setMaxPriceVal] = useState(maxPrice);
const minValRef = useRef(null);
const maxValRef = useRef(null);
const range = useRef(null);
const convertToPercent = useCallback(
(value) => Math.round(((value - minPrice) / (maxPrice - minPrice)) * 100),
[minPrice, maxPrice],
);
useEffect(() => {
if (maxValRef.current) {
const minPercent = convertToPercent(minPriceVal);
const maxPercent = convertToPercent(+maxValRef.current.value);
if (range.current) {
range.current.style.left = `${minPercent}%`;
range.current.style.width = `${maxPercent - minPercent}%`;
}
}
}, [minPriceVal, convertToPercent]);
useEffect(() => {
if (minValRef.current) {
const maxPercent = convertToPercent(maxPriceVal);
const minPercent = convertToPercent(+minValRef.current.value);
if (range.current) {
range.current.style.width = `${maxPercent - minPercent}%`;
}
}
}, [maxPriceVal, convertToPercent]);
useEffect(() => {
onChange({ min: minPriceVal, max: maxPriceVal });
}, [minPriceVal, maxPriceVal, onChange]);
const minInputField = (e) => {
setMinPriceVal(e.target.value);
};
const maxInputField = (e) => {
setMaxPriceVal(e.target.value);
};
return (
<div className={"rangeSlider"}>
{/* text input field MIN */}
<input
value={minPriceVal}
type={"number"}
onChange={(e) => {
minInputField(e);
}}
/>
{/* text input field MAX */}
<input
value={maxPriceVal}
type={"number"}
onChange={(e) => {
maxInputField(e);
}}
/>
<div className="container">
<input
type="range"
min={minPrice}
max={maxPrice}
value={minPriceVal}
ref={minValRef}
onChange={(event) => {
const value = Math.min(+event.target.value, maxPriceVal - 1);
setMinPriceVal(value);
event.target.value = value.toString();
}}
className="thumbMin"
/>
<input
type="range"
min={minPrice}
max={maxPrice}
value={maxPriceVal}
ref={maxValRef}
onChange={(event) => {
const value = Math.max(+event.target.value, minPriceVal + 1);
setMaxPriceVal(value);
event.target.value = value.toString();
}}
className="thumbMax"
/>
<div className="slider">
<div className="track" />
<div ref={range} className="range" />
</div>
</div>
</div>
);
}
export default MultiRangeSlider;
.slider {
position: relative;
width: 200px;
.track {
border-radius: 3px;
height: 5px;
position: absolute;
background-color: black;
width: 100%;
z-index: 1;
}
.range {
display: block;
border-radius: 3px;
height: 5px;
position: absolute;
background-color: greenyellow;
z-index: 2;
}
}
.container {
margin-top: 40px;
.thumbMin {
pointer-events: none;
position: absolute;
height: 0;
width: 200px;
outline: none;
z-index: 3;
&::-webkit-slider-thumb {
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
}
&::-webkit-slider-thumb {
background-color: #f1f5f7;
border: none;
border-radius: 50%;
box-shadow: 0 0 1px 1px #ced4da;
cursor: pointer;
height: 18px;
width: 18px;
margin-top: 4px;
pointer-events: all;
position: relative;
}
&::-moz-range-thumb {
background-color: #f1f5f7;
border: none;
border-radius: 50%;
box-shadow: 0 0 1px 1px #ced4da;
cursor: pointer;
height: 18px;
width: 18px;
margin-top: 4px;
pointer-events: all;
position: relative;
}
}
.thumbMax {
pointer-events: none;
position: absolute;
height: 0;
width: 200px;
outline: none;
z-index: 4;
&::-webkit-slider-thumb {
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
}
&::-webkit-slider-thumb {
background-color: #f1f5f7;
border: none;
border-radius: 50%;
box-shadow: 0 0 1px 1px #ced4da;
cursor: pointer;
height: 18px;
width: 18px;
margin-top: 4px;
pointer-events: all;
position: relative;
}
&::-moz-range-thumb {
background-color: #f1f5f7;
border: none;
border-radius: 50%;
box-shadow: 0 0 1px 1px #ced4da;
cursor: pointer;
height: 18px;
width: 18px;
margin-top: 4px;
pointer-events: all;
position: relative;
}
}
}
I tried to introduce a restriction on entering a new value by checking through the function: if (newValue < oldValue) return;
But it doesn't work as it should
I tried several ways, but it doesn't work. I just can’t understand what the problem is.