Show the component
Inertia react file upload error
hi guys when i try to upload file with inertia and react using inertia doc https://inertiajs.com/file-uploads i get this error Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.
function Create({ categories }) {
const { data, setData, post, processing,progress , errors } = useForm({
name: ''",
categorie_id: '"',
url: ''"
})
const [file, setFile] = useState();
function handleChange(e) {
console.log(e.target.files);
setFile(URL.createObjectURL(e.target.files[0]));
setData('url', e.target.files[0])
}
function handleSubmit(e) {
e.preventDefault()
post('/dashboard/categories')
}
return (
<div>
<section className='content-header'>
<div className="container-fluid">
<div className="row mb-2">
<div className="col-sm-6">
<h1>Categories</h1>
</div>
<div className="col-sm-6">
<ol className="breadcrumb float-sm-right">
<li className="breadcrumb-item"><a href="#">Home</a></li>
<li className="breadcrumb-item active">Flot</li>
</ol>
</div>
</div>
</div>
</section>
<section className='content'>
<div className='container-fluid'>
<div className='row'>
<div className='col-12'>
<div className='card card-primary card-outline'>
<div className="card-header">
<h3 className="card-title">
<FontAwesomeIcon icon={faChartBar} />
Create Category
</h3>
</div>
<form onSubmit={handleSubmit}>
<div className='card-body'>
<div className='row'>
<div className='col-md-6'>
<FormGroup value={data.name} onChange={e => setData('name', e.target.value)} label="Name" type="text" placeholder="Enter Name" />
</div>
<div className='col-md-6'>
<div className="form-group">
<label >Parent Categorie</label>
{/* setData('menu', e.target.value) */}
<Select options={categories} getOptionLabel={(option) => `${option.name}`} getOptionValue={(option) => `${option.id}`} defaultValue={data.categorie_id} onChange={e => setData('categorie_id', e.id)} />
</div>
</div>
<div className='col-md-6'>
<div className='categorie-image'>
<h5 className='font-weight-bold'>Categorie Image</h5>
<input type="file" value={data.url} onChange={handleChange} />
<img src={file} />
</div>
{progress && (
<progress value={progress.percentage} max="100">
{progress.percentage}%
</progress>
)}
</div>
</div>
</div>
<div className='card-footer'>
<button type="submit" className="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
</div>
)
}
@kaiserkais What is this for? I dont see that in their example.
setFile(URL.createObjectURL(e.target.files[0]));
Is it to populate the img?
<img src={file} />
Does it work if you remove that part?
You can also try setting url: null like in the example
Could be wrong but try this, I don't think you need to set the file in state.
function Create({ categories }) {
const { data, setData, post, processing,progress , errors } = useForm({
name: ''",
categorie_id: '"',
url: ''"
})
const handleFile = () => {
if (e.currentTarget.files) {
setData("url", e.currentTarget.files[0]);
}
};
function handleSubmit(e) {
e.preventDefault()
post('/dashboard/categories')
}
return (
<div>
<section className='content-header'>
<div className="container-fluid">
<div className="row mb-2">
<div className="col-sm-6">
<h1>Categories</h1>
</div>
<div className="col-sm-6">
<ol className="breadcrumb float-sm-right">
<li className="breadcrumb-item"><a href="#">Home</a></li>
<li className="breadcrumb-item active">Flot</li>
</ol>
</div>
</div>
</div>
</section>
<section className='content'>
<div className='container-fluid'>
<div className='row'>
<div className='col-12'>
<div className='card card-primary card-outline'>
<div className="card-header">
<h3 className="card-title">
<FontAwesomeIcon icon={faChartBar} />
Create Category
</h3>
</div>
<form onSubmit={handleSubmit}>
<div className='card-body'>
<div className='row'>
<div className='col-md-6'>
<FormGroup value={data.name} onChange={e => setData('name', e.target.value)} label="Name" type="text" placeholder="Enter Name" />
</div>
<div className='col-md-6'>
<div className="form-group">
<label >Parent Categorie</label>
{/* setData('menu', e.target.value) */}
<Select options={categories} getOptionLabel={(option) => `${option.name}`} getOptionValue={(option) => `${option.id}`} defaultValue={data.categorie_id} onChange={e => setData('categorie_id', e.id)} />
</div>
</div>
<div className='col-md-6'>
<div className='categorie-image'>
<h5 className='font-weight-bold'>Categorie Image</h5>
<input type="file" value={Image} onChange={handleFile}/>
<img src={file} />
</div>
{progress && (
<progress value={progress.percentage} max="100">
{progress.percentage}%
</progress>
)}
</div>
</div>
</div>
<div className='card-footer'>
<button type="submit" className="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
</div>
)
}
I had the same issue... I solved removing the value attribute from the input type="file".
<input type="file" onChange={handleFile}/>
(If you see in the documentation the same example for svelte or vue, you will not see the value attribute there).
@javdome Hi I have same issue I'm trying to send avatar image for the user but when I submit the form the avatar doesn't been send only name and email
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import FileInput from '@/Components/FileInput';
import { Link, useForm, usePage } from '@inertiajs/inertia-react';
import { Transition } from '@headlessui/react';
import { useState } from 'react';
export default function UpdateProfileInformation({ mustVerifyEmail, status, className }) {
const user = usePage().props.auth.user;
const [avatar, setAvatar] = useState("https://ui-avatars.com/api/?name="+user.name+user.surname+"?rounded=true");
const { data, setData, post, errors, processing, recentlySuccessful } = useForm({
name: user.name,
email: user.email,
avatar: null
});
const submit = (e) => {
e.preventDefault();
post(route('profile.update'));
};
const changeAvatar = (e) => {
setAvatar(URL.createObjectURL(e.target.files[0]));
setData('avatar', e.target.files[0]);
}
return (
<section className={className}>
<header>
<h2 className="text-lg font-medium text-gray-900">Profile Information</h2>
<p className="mt-1 text-sm text-gray-600">
Update your account's profile information and email address.
</p>
</header>
<form onSubmit={submit} className="mt-6 space-y-6">
<div>
<InputLabel for="name" value="Name" />
<TextInput
id="name"
className="mt-1 block w-full"
value={data.name}
handleChange={(e) => setData('name', e.target.value)}
required
autofocus
autocomplete="name"
/>
<InputError className="mt-2" message={errors.name} />
</div>
<div>
<InputLabel for="email" value="Email" />
<TextInput
id="email"
type="email"
className="mt-1 block w-full"
value={data.email}
handleChange={(e) => setData('email', e.target.value)}
required
autocomplete="email"
/>
<InputError className="mt-2" message={errors.email} />
</div>
<div className='flex flex-col md:flex-row items-center'>
<div>
<InputLabel value="Avatar" />
<FileInput
id="avatar"
name="avatar"
type="file"
className="mt-1 block w-full"
handleChange={(e) => changeAvatar(e)}
required
/>
<InputError className="mt-2" message={errors.email} />
</div>
<div className="avatar-cont mt-6 md:mt-0 py-2">
<img
className="h-20 w-20 rounded-full"
src={avatar}
alt=""
/>
</div>
</div>
{mustVerifyEmail && user.email_verified_at === null && (
<div>
<p className="text-sm mt-2 text-gray-800">
Your email address is unverified.
<Link
href={route('verification.send')}
method="post"
as="button"
className="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Click here to re-send the verification email.
</Link>
</p>
{status === 'verification-link-sent' && (
<div className="mt-2 font-medium text-sm text-green-600">
A new verification link has been sent to your email address.
</div>
)}
</div>
)}
<div className="flex items-center gap-4">
<PrimaryButton processing={processing}>Save</PrimaryButton>
<Transition
show={recentlySuccessful}
enterFrom="opacity-0"
leaveTo="opacity-0"
className="transition ease-in-out"
>
<p className="text-sm text-gray-600">Saved.</p>
</Transition>
</div>
</form>
</section>
);
}
@MrRobot993 please may I know brother if you where Able to resolve this issue, or is this code you posted correct and working well ?
Please or to participate in this conversation.