How can I Upload files and JSON data in the same request with AlpineJS

Viewed 53

I need to Add data & image file in a same post request using alpine js.

1 Answers

I think it is a little bit late. But, someone else might need take benefit from this answer in the future. You can use Javascript's FormData to handle both data and file.

Bellow, I am copying a part from my application to show the full process of actually uploading image with Alpine JS and sending it as part of Form Data to your API end.

HTML Part:

<form method="post" enctype="multipart/form-data" @submit.prevent="$store.app.submitData()">
    <div class="row mb-4">
        <div class="form-group col-md-4">
            <label>App Name</label>
            <input type="text" name="name" class="form-control" x-model="$store.app.form.name">
        </div>
        <div class="form-group col-md-4">
            <label>Slug</label>
            <input type="text" name="name" class="form-control" x-model="$store.app.form.slug">
        </div>
        <div class="form-group col-md-4">
            <label>Icon/Logo</label>
            <input type="file" name="image_icon" class="form-control" x-on:change="$store.app.selectFile($event)" accept="image/png, image/jpg, image/jpeg">
        </div>
    </div>
    <div class="row">
        <div class="col-md-12 text-end mt-3">
            <button type="submit" class="btn btn-lg btn-primary mb-5" :disabled="$store.app.loading">
                <span class="indicator-label">Save</span>
            </button>
        </div>
    </div>
</form>

Alpine JS Part:

<script>
    document.addEventListener('alpine:init', () => {
        Alpine.store('app', {
            loading: false,
            form: {
                name: '',
                image_icon: '',
                slug: ''
            },
            selectFile(event) {
                this.form.image_icon = event.target.files[0]
            },
            submitData() {
                //Create an instance of FormData
                const data = new FormData()
                let url = '/application'
                
                // Append the form object data by mapping through them
                Object.keys(this.form).map((key, index) => {
                    data.append(key, this. Form[key])
                });

                this.loading = true
                
                fetch(url, {
                        method: 'POST',
                        headers: {
                            'Accept': 'application/json',
                            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                        },
                        body: data
                    })
                    .then(response => {
                        //...
                    })
                    .finally(() => {
                        this. Loading = false
                    });
            }
        })
    })
</script>

Please note that I have used store in this example, you can use Alpine Data, function or inline x-data as you please.

Appending to the form data just requires a key and value pair, for example;

const data = new FormData();
data.append('name', 'John');
data.append('surname', 'Doe');

I hope this helps.

Related