Skip to content
Brew

Example — File upload

Avatar upload with loading/progress affordances.

class AvatarForm : Component(), WithFileUploads {
var photo: TemporaryUploadedFile? = null
var path: String? = null
fun save() {
validate()
path = photo?.store("avatars")
photo = null
}
override fun rules() = mapOf(
"photo" to listOf("required", "file", "max:2048"),
)
override fun template() = """
<form wire:submit="save">
<input type="file" accept="image/*" wire:model="photo" />
<div
x-data="{ progress: 0 }"
x-on:brew-upload-progress="progress = ${'$'}event.detail.progress"
>
<progress max="100" x-bind:value="progress"></progress>
</div>
<span wire:loading wire:target="photo">Uploading…</span>
@if(errors['photo'])
<em>{{ errors['photo'][0] }}</em>
@endif
@if(path)
<p>Stored at {{ path }}</p>
@endif
<button type="submit" wire:loading.attr="disabled">Save</button>
</form>
""".trimIndent()
}

JS helpers when you drive uploads from Alpine: $wire.$upload, $uploadMultiple, $cancelUpload, $removeUpload. Full config: File uploads.