Skip to content

FileUpload

tanthammar edited this page Nov 18, 2020 · 4 revisions

Tall-form-file-upload

image image

Requirements

  • read configuration instruction in the main Livewire docs about storage disk and default file validation. This package handles the rest.
  • read livewire docs about scheduling cleanup of the temporary storage folder
  • read livewire docs about saving the files

Add required traits to your component

use Tanthammar\TallForms\Traits\UploadsFiles;
use Livewire\WithFileUploads;

class someForm extends Component
{
    use WithFileUploads, UploadsFiles;
}

Livewire requires you to add the property for file-upload fields, to the form component

//properties used in this example
public $image;
public $files;

Set default validation message in the config file

Livewire default validation rules are in its config file. This is fine until you want to use custom validation. The problem is that the file gets uploaded before your custom validation executes, and the file remains on the server. The FileUpload field has a workaround that deletes the temporary file if your custom validation fails. The user is presented with a general error that you define in the config file.

//File upload default validation message
'upload-file-error' => 'messages.file_upload_error', //Example: 'One or many of the uploaded files did not match the allowed filetype or size limit. Please see the fields help text, review your files and try again.'

Forcing the user to clean up after themselves

This package tries to minimize unwanted files in the temp folder, by forcing the user to delete uploaded files before they can upload new ones.

  • Not using s3: Livewire will handle the file cleanup automatically.
  • Using s3: You must schedule the cleanup
php artisan livewire:configure-s3-upload-cleanup

Extends BaseField

Additional methods

->multiple()

Add if you want to allow uploading multiple files at the same time

->accept(string $typeSpecifier)

->image()

Sets the input accept attribute to "image/*"

Icons

The FileUpload automatically selects an icon based on the file-type. If the uploaded file is an image, the field automatically displays a circular image preview. See the Icons page for which svg icons you are required to create.

Example definitions

public function fields()
{
    return [
        $this->fileUpload(),  // single file upload
        $this->fileUploads(), // multiple file uploads
    ];
}

public function fileUpload()
{
    return optional($this->model)->exists //you probably do not want to attach files if the model does not exist
        ? FileUpload::make('Upload image', 'image')
            ->help('Max 1024kb, png, jpeg, gif or tiff') //important for usability to inform about type/size limitations
            ->rules('nullable|mimes:png,jpg,jpeg,gif,tiff|max:1024') //only if you want to override livewire main config validation
            ->accept("image/*") //html5 file input accept attribute
        : null;
}
public function fileUploads()
{
    return optional($this->model)->exists //you probably do not want to attach files if the model does not exist
        ? FileUpload::make('Upload files', 'files')
            ->multiple() //remove if you want single file upload
            ->help('Max 1024kb, pdf, png, jpeg, gif or tiff') //important for usability to inform about type/size limitations
            ->rules('nullable|mimes:pdf,png,jpg,jpeg,gif,tiff|max:1024') //only if you want to override livewire main config validation
            ->accept("image/*,.pdf") //html5 file input accept attribute
        : null;
}

You must save the files yourself !!!

  • The data is accessed via the fields name property, like $this->fieldname.
  • (Read Livewire docs about various ways to store uploaded files)
  • (Read more about Lifecycle Hooks to understand saveFoo())

Example

// saving single file upload example
public function saveImage($validated_file)
{

    $path = filled($validated_file) ? $this->image->store('photos') : null;
    //do something with the model?
    if (optional($this->model)->exists && filled($path)) {
        $this->model->single_image_url = $path;
        $this->model->save();
    }
}

//saving multiple file uploads example
public function saveFiles($validated_files)
{
    $paths = [];
    if (filled($validated_files)) {
        foreach ($this->files as $file) {
            if (filled($file)) array_push($paths, $file->store('files'));
        }
    }
    //do something with the model?
    if (optional($this->model)->exists && filled($paths)) {
        //the field must be cast to array and stored in a json or text column
        $this->model->multiple_image_urls = $paths;
        $this->model->save();
    }
}

Blade component

<x-tall-file-upload 
    :field="$field"
    :show-file-upload-error="$showFileUploadError"
    :show-file-upload-error-for="$showFileUploadErrorFor"
    :field-value="${$field->name}" />

Styling

Extend Blade component (or override in config file)

Tanthammar\TallForms\Components\FileUpload::class

Handling existing files

The field is only for adding files. It is a standard html5 file input type. If you want to handle existing files you could use the Repeater field, maybe in combination with making it a custom field. Or you can make it a custom field with a custom view. Read the example in the Relationships page for ideas on how to populate an Array field with existing data.

You can handle the update of the file list in either the updatedFoo() or the saveFoo() method. Depending on if you want to save the files in realtime or when the form is submitted.

Theme

 /* File upload */
    input.tf-file-upload {
        @apply flex-1 block w-full sm:text-sm rounded-none rounded-r;
    }
    .tf-file-upload-input-wrapper {
        @apply flex rounded w-full relative;
    }
    .tf-file-upload-spinner-wrapper {
        @apply inline-flex items-center rounded-l px-3 border border-r-0 text-gray-600 sm:text-sm;
        @apply border-gray-300 bg-gray-100;
    }
    .tf-file-upload-ul {
        @apply space-y-2 my-2;
    }
    .tf-file-upload-li {
        @apply w-full flex items-center px-2 py-1 border rounded;
    }
    .tf-file-upload-thumb-wrapper {
        @apply border h-8 w-8 rounded-full;
    }
    .tf-file-upload-thumb-img {
        @apply h-8 w-full object-cover rounded-full;
    }
    svg.tf-file-upload-icon {
        @apply h-4 w-4 text-gray-600;
    }
    .tf-file-upload-icon-wrapper {
        @apply border h-8 w-8 rounded-full flex items-center justify-around;
    }
    .tf-file-upload-delete-btn {
        @apply tf-text-danger;
    }
    .tf-file-upload-btn-size {
        @apply h-6 w-6;
    }
Clone this wiki locally