Why do you use $tmp variable?
The use of a $tmp
variable was a design choice. It was a simple and convenient way of keeping track of the existing image URL and the temporary image. It’s not required.
Should I use imgUrl, like avatarUrl?
Yes, you can use imgUrl()
to obtain your image rather than avatarUrl()
. In your imgUrl()
function you can return the image path and then use some conditional to show the image if an image was returned.
Something along the lines of
public function imgUrl()
{
return $this->img;
}
@if ($img)
<img src="Storage::disk('local')->url($img)" alt="post image">
@endif
Regarding attributes and props. I tried to add $attributes and props, laravel gave me an error, that properties weren’t passed to a component.
You only need to define custom key value pairs in the @props([])
directive. Take a look a the Blade Components Cookbook screencasts on Laracasts.
If I use $filename to store the name of the image. I got a very strange path to the image in the db, like /private/var/tmp/phpsLUXa6
That is to be expected, the filename will be a hash of the image.
Call to a member function temporaryUrl() on string (View: /Applications/MAMP/htdocs/lemma-auto/resources/views/admin/posts/create.blade.php)
This is because when you first load the component, your $img
variable is a string, the path to the image previously uploaded. Once you upload a file it becomes a File Upload object.
Change your @if($img)
to something like @if(method_exists($img, 'temporaryUrl'))
. There is possibly a nicer way of doing it but that works for me.
I see what you are trying to do, you want to load the image back into the FilePond
input when you are editing a Post
.
I had a tinker and came up with the following working example which will hopefully get you in the right direction. I also simplified it a little removing the $tmp
variable and some other stuff.
<?php
namespace App\Http\Livewire;
use App\Models\User;
use Livewire\Component;
use Livewire\WithFileUploads;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
class Uploader extends Component
{
use WithFileUploads;
/**
* The full path to the uploaded avatar
*/
public $avatar;
/**
* Just setting up some stuff here
*
* @return void
*/
public function mount()
{
// I am not using any auth scaffolding so, force a manual user login
Auth::login(User::find(1));
// Display the current avatar for the user
$this->avatar = $this->avatarUrl();
}
/**
* Save some stuff
*
* @return void
*/
public function save()
{
// Add the new avatar filename to the avatar user attribute
$attributes['avatar'] = $this->avatar->store('/', 'uploads');;
// If updating the user was successful
if (auth()->user()->update($attributes)) {
// Get the new avatar for the user
$this->avatar = $this->avatarUrl();
// Clear the FilePond input after submission,
// Uncomment this if you want to clear the FilePond input after upload
// $this->dispatchBrowserEvent('pondReset');
// Fire an event to show success message
$this->emitSelf('notify-saved');
}
}
/**
* If the user has an avatar defined, get if from storage,
* otherwise use a gravatar.
*
* @return void
*/
public function avatarUrl()
{
return auth()->user()->avatar ?
Storage::disk('uploads')->url(auth()->user()->avatar) :
'https://gravatar.com/avatar/' . md5(strtolower(trim(auth()->user()->email)));
}
public function render()
{
return view('livewire.uploader');
}
}
<div>
<div>
@if (method_exists($avatar ,'temporaryUrl'))
<img src="{{ $avatar->temporaryUrl() }}" alt="Avatar">
@else
<img src="{{ $avatar }}" alt="Avatar">
@endif
</div>
<form wire:submit.prevent="save">
<x-input.filepond wire:model="avatar" :avatar="$avatar" image-preview />
<span x-data="{ open: false }" x-init="
@this.on('notify-saved', () => { if (open === false) setTimeout(() => { open = false }, 2500); open = true})
" x-show.transition.out.duration.1000ms="open" style="display: none">
{{ __('Saved') }}
</span>
<button type="submit">
{{ __('Save') }}
</button>
</form>
</div>
@props([
'avatar' => '',
// this is so you can turn the image preview on and off
'imagePreview' => false,
])
<div x-data="{}"
x-init="
FilePond.setOptions({
server: {
process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
@this.upload('{{ $attributes["wire:model"] }}', file, load, error, progress)
},
revert: (uniqueFileId, load, error) => {
@this.removeUpload('{{ $attributes["wire:model"] }}', uniqueFileId, load)
},
load: (source, load, error, progress, abort, headers) => {
var request = new Request(source);
fetch(request).then(function(response) {
response.blob().then(function(myBlob) {
load(myBlob)
});
});
},
},
});
@if($imagePreview)
FilePond.registerPlugin(FilePondPluginImagePreview);
@endif
var Pond = FilePond.create($refs.input, {
files: [
{
source: '{{ $avatar }}',
options: {
type: 'local',
},
},
],
});
this.addEventListener('pondReset', e => {
Pond.removeFiles();
});
"
wire:ignore>
<input type="file" x-ref="input" />
</div>