I building a React component using Mui TextField
. Its a number field so there are two ways to update the TextField
component: Editing the text itself and using the step arrows. When "blurring" the field, I want to snap the value to the nearest multiple of 5. I also set the step="5"
as well.
The component itself has an onChange
event that passes the number value but I only want this event to fire when the user "steps" the value or the user "blurs" the field. Here's what I've got so far:
interface WeightFieldProps {
name?: string
placeholder?: string
label?: string
value?: number
onChange?: (value: number) => void
}
const WeightField: React.FC<WeightFieldProps> = ({
name,
placeholder,
label,
value = 0,
onChange
}) => {
const [weight, setWeight] = useState(value)
// Update the component but do not fire the parent onChange event.
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = parseInt(event.target.value)
setWeight(value)
}
// Update the component as usual but notify the parent component that
// the value has changed.
const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {
const value = snapWeightValue(parseInt(event.target.value))
setWeight(value)
if (onChange) onChange(value)
}
// Ideally, I want the parent component only be notified when the user
// is changing the input value via the step arrows.
// const handleStepChange = (event: React.SomeEvent) => {
// const value = parseInt(event.target.value)
// setWeight(value)
// if (onChange) onChange(value)
// }
return <TextField
name={name}
type="number"
placeholder={placeholder}
label={label}
InputProps={{
endAdornment: <InputAdornment position="end">lbs</InputAdornment>
}}
inputProps={{
step: "5",
style: {
fontSize: "2em",
padding: "10px",
textAlign: "right"
}
}}
value={weight}
onChange={handleChange}
onBlur={handleBlur}
// onStepChange={handleStepChange}
fullWidth
/>
}
What I'm hoping for is some kind of event handler specifically for when a user updates the field via the numeric step buttons or maybe a way to determine how the field is being updated during the onChange
event so I can fire the component's onChange
event only when the user is stepping the value?
CodePudding user response:
I would suggest hiding the native arrow buttons, adding custom arrow buttons like in number inputs from UI-libraries, and then adding to these custom arrow buttons whenever handler you like. There is no such event that would be only triggered by clicking native arrow buttons.
CodePudding user response:
you should move inputProps
inside InputProps
. else you will have eslint
warning, no duplicate props allowed.
You can use onInput
event handler inside inputProps
as shown in below code.
ref: https://www.w3schools.com/jsref/event_oninput.asp
<TextField
name={name}
type="number"
placeholder={placeholder}
label={label}
InputProps={{
endAdornment: <InputAdornment position="end">lbs</InputAdornment>,
inputProps:{
step: "5",
onInput:()=> console.log('input changed'),
style: {
fontSize: "2em",
padding: "10px",
textAlign: "right"
}
}
}}
value={weight}
onChange={handleChange}
onBlur={handleBlur}
// onStepChange={handleStepChange}
fullWidth
/>