# FileUpload

![](https://user-images.githubusercontent.com/21239634/91079382-43548a80-e644-11ea-9782-78709b0eda5d.gif)

### Requirements

* This field requires you to configure Livewire file uploads according to the main documentation. \
  Setup [**storage disk** and **default file validation**](https://laravel-livewire.com/docs/file-uploads). This component 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

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

class someForm extends Component
{
    use WithFileUploads, UploadsFiles;
}
```

### Add required properties

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

```php
//properties used in this example
//Do NOT add type declaration = Livewire error...
public $image;
public $files;
```

### Validation messages

#### 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 language files**.\
This component tries to minimize unwanted files in the temp folder, by forcing the user to delete uploaded files before they can upload new ones.

```
//languange files
'file-upload' => [
    'upload-file-error' => '...',
]
```

### Cleanup old uploads

* Not using s3: Livewire will handle the file cleanup automatically.
* Using s3: You must schedule the cleanup&#x20;

```
php artisan livewire:configure-s3-upload-cleanup
```

### Saving the files

#### 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](https://laravel-livewire.com/docs/2.x/file-uploads#storing-files))
* (Read more about [Lifecycle Hooks](https://tina-hammar.gitbook.io/tall-forms/form/lifecycle-hooks) to understand `saveFoo()`)

The FileUpload data is never available in the `form_data` property, you access it with `$this->foo` because Livewire requires you to define the property on the component.

{% tabs %}
{% tab title="Preview" %}
![](https://3246461946-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQWt7hBSh108moAc0Al%2F-Mf45FW8ePniX6S36o1U%2F-Mf4M1ISxGiWOxAFsPgE%2Ffile-upload-animated.gif?alt=media\&token=5e901c01-12af-493f-9d60-5587687ebc6f)

![](https://3246461946-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQWt7hBSh108moAc0Al%2F-Mf45FW8ePniX6S36o1U%2F-Mf4MHghHW3koZROu_Uc%2Ffile-upload-input.png?alt=media\&token=396843f9-bc80-4ee4-ba22-e54b80a407a7)

![](https://3246461946-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQWt7hBSh108moAc0Al%2F-Mf45FW8ePniX6S36o1U%2F-Mf4MRMIWBt6k1wZ-krd%2Ffile-upload.png?alt=media\&token=a9fe25f1-edd2-4299-aa53-0dcf2b838d37)
{% endtab %}

{% tab title="Component" %}

### Single file upload example

```php
public $image;

protected function fields()
{
    return [
        $this->fileUpload(),
    ];
}

protected 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;
}

// saving single file upload example
protected 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();
    }
}
```

#### Multiple file uploads example

```php
public $files;

protected function fields()
{
    return [
        $this->fileUploads()
    ];
}


protected 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;
}


//saving multiple file uploads example
protected 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();
    }
}
```

{% endtab %}

{% tab title="Headless" %}

* This field requires Livewire.
* **See the "Component" tab**, on how to setup your Livewire component to interact with this code example.
* Apart from the earlier mentioned traits, you must use the `HandlesArrays` trait if you are **not** extending the `TallForms` component.

### Livewire component example

```php
use Livewire\Component;
use Livewire\WithFileUploads;
use Tanthammar\TallForms\Traits\HandlesArrays;
use Tanthammar\TallForms\Traits\UploadsFiles;

class Foo extends Component
{
    use WithFileUploads, UploadsFiles, HandlesArrays;

    public $images;
}

//saving multiple image uploads example
public function saveImages($validated_files)
{
    $paths = [];
    if (filled($validated_files)) {
        foreach ($this->files as $file) {
            if (filled($file)) array_push($paths, $file->store('files'));
        }
    }
    //attach to a model?
}
```

### Blade file

```markup
<x-tall-file-upload :field="FileUpload::blade('images')
    ->multiple()
    ->help('Max 1024kb, pdf, png, jpeg, gif or tiff')
    ->rules('nullable|mimes:pdf,png,jpg,jpeg,gif,tiff|max:1024')
    ->accept('image/*,.pdf')"
    :field-value="$images"
    {{-- these props updates in UploadsFiles trait if there are multiple file upload fields on the page --}}
    :show-file-upload-error="$showFileUploadError"
    :show-file-upload-error-for="$showFileUploadErrorFor"
/>
```

{% endtab %}

{% tab title="Styles" %}
The classes are applied differently on this field.

| Attribute    | Comment                                       |
| ------------ | --------------------------------------------- |
| wrapperClass | Applied to the blade component root div       |
| class        | Applied to the div that wraps the input       |
| errorClass   | Applied t the div that wraps the input @error |
| inputClass   | Applied to the input                          |

Search for `File upload` in tall-theme.css
{% endtab %}
{% endtabs %}
