Form with FileInput and required fields


it seems like using a form with both, file input and different required input fields, where an additional submit button for uploading is provided, can’t work?!

What I’m trying to do:
I have a file input in my form, where the user can upload an image to a newly created record, but without finally saving the record.
He can also choose a file and just click the save button, and then in one step the image gets uploaded, its filename assigned to the “image_filename” attribute and the whole form/records gets saved to the DB.

What I’ve done so far:
I tried solving it over scenarios (see code below), which switch depending on the clicked button.
It partly works, but it’s difficult if an image is already uploaded and if required fields of the rest of the form are empty.
If then the save submit button is pressed, the image is gone, the assigned “image_filename” too.
If I use a hidden field in the form for the “image_filename”,

<input type=“hidden” name=“uploaded” value="<?= $model->uploaded ?>">
<?= $form->field($model, “image_filename”)->hiddenInput()->label(false) ?>

it gets transported over state after clicking the save button without providing required fields.
But after fill out required fields and pressing save submit button again, I always land in the if-condition on line 74 in the controller, that wants to upload again (an empty image!).
I do know that with this uploaded flag, I can only upload one image if set to true.
Not sure if the whole way how I do this, is “good”. :woozy_face:

My code:
Controller (create function)
View (_form)

I’ve already searched the web and here, where I found this similar cases:

Seems the problem is common but no real solution. Maybe most just switch to an AJAX based solution or implement an extra step/form for just uploading the file. Hm.

Do I something wrong or not grasp a concept?
How do you guys handle this or are you doing completely different things?

Thanks in advance

Hi @Androphin and all,

The image file uploading has also been a bone in my throat for a long time.

The example code in the guide (Guide > Uploading Files) works perfectly, but it’s too simplified for a real world scenario. For one thing, you can not enable AJAX validation in the example code, because fileInput field will always send null when it is AJAX. (please correct me if I’m wrong)

And usually we would need much more for the uploaded image - previewing, resizing, cropping, rotating, etc.

So, I’m very interested in what others are doing to conquer this challenge.

One practical solution may be using a client side JavaScript library. I used yii2-cropper for one of my projects.

Hi @softark,

I don’t use AJAX validation. Only with Yii’s basic client side validation in my starting post.
Yeah, it seems a problem for a lot, because many factors like basic file-input, client side validation/AJAX, upload logic all together play a role.
It would be nice to find one clean way that fits the needs from all of us.
In my linked code you can see, that I started with the code snippet from the guide you linked and built up on that. I did disable client side validation, but it seems that ActiveForm.js may take scenarios into account. Haven’t finally found out yet.
Thanks for the link to this cropper widget! Didn’t know about it. So the use of ImagineExt on server side could be neglected.

Rethinking the whole process, I came up with the following:
If a POST is fired to the controller’s create function, I first do need to distinguish between what button has been fired.
I have two: UPLOAD and SAVE button.
UPLOAD is fired:

  1. Validate only SCENARIO_UPLOAD
  2. Store the uploaded image on disk
  3. Get the filename and inject it to the unsaved form in a hidden field, so that the SAVE routine can use this image_filename, if no new imagefile is in the file-input

SAVE is fired:

  1. Check, if in POST data is new imagedata, that’s proof the user has selected an image in the file input field.
    If he uploaded one previously can be detected through image_filename in POST data isn’t empty, because it was set in the hidden input field by the UPLOAD action.
    Now the old image needs to be deleted and the upload routine gets invoked again and the image_filename that was sent with the hidden input field gets replaced with the filename of the new image.
  2. Validate SCENARIO_SAVE
  3. Save the record to the DB.

That looks like a solution to me and I’m currently implementing and testing it. Hope it works out and I didn’t make any logical errors. Let’s see how it turns out with client side validation.

1 Like