Using Inertia Js with React opens up all manner of challenges as I found out with one use case recently.
On one project I have a Task model. A task has various props such as a progress measure and a status of the task being completed or not. To improve the UX I wanted the status checkbox to be checked were the progress dragged to 100% maximum.
On the other hand, if a task was already completed prior to a decision to revive the task (and its parent Project) the progress may be dragged down to less than 100% maximum. In which case I wanted the checkbox to automatically uncheck.
The solution I arrived at is below. First of all, a fragment of the form.
export default function Form() {
const { task } = usePage().props;
const { data, setData, post, processing, errors } = useForm({
progress: task.progress,
completed: task.completed,
id: task.id,
_method: "put",
});
// etc,...
function submit(e) {
e.preventDefault();
post(route("tasks.progress.update"), {
preserveState: false,
onStart: () => {},
onSuccess: (response) => {},
onError: () => {},
onFinish: () => {},
});
}
return (
<>
<form onSubmit={ submit }>
<div className="mt-4">
<InputLabel htmlFor="progress" value={`Progress (${data?.progress}%)`} />
<RangeInput
name="progress"
min="0"
max="100"
step="1"
value={ data?.progress }
title={ data?.progress }
className="mt-1 block w-full"
autoComplete="off"
onChange={ handleRangeChange }
/>
<InputError message={ errors?.progress } className="mt-2" />
</div>
<div className="block mt-4">
<label className="flex items-center">
<Checkbox
name="completed"
checked={ data?.completed || false }
onChange={ handleCheckboxChange }
/>
<span className="ms-2 text-sm text-gray-600">Check, if this Task has been completed</span>
</label>
</div>
<div className="flex items-center justify-end mt-4">
<PrimaryButton className="ms-4" disabled={ processing }>
Edit
</PrimaryButton>
<Cancel route={ route("tasks.index") } />
</div>
</form>
</>
);
}
Next, the following completes the implementation in full, using two event handlers. The handleCheckboxChange
manages the checkbox, whilst the handleRangeChange
handler manges the range.
const handleCheckboxChange = (e) => {
const isChecked = e.target.checked;
setData((prev) => ({
...prev,
completed: isChecked,
progress: isChecked ? 100 : 0
}));
};
const handleRangeChange = (e) => {
const newProgress = Number(e.target.value);
setData((prev) => ({
...prev,
progress: newProgress,
completed: newProgress === 100
}));
};
Now whenever the progress reaches 100% maximum the checkbox is automatically checked. And when the progress is dragged down the checkbox automatically is unchecked.
And likewise, when you check the checkbox, the range automatically goes to 100% and vice versa. User experience is much improved with the overall use feeling smoother.
Content on this site is licensed under a Creative Commons Attribution 4.0 International License. You are encouraged to link to, and share but with attribution.
Copyright ©2024 Leslie Quinn.