DEV Community

vimuth
vimuth

Posted on • Edited on

Create custom image upload component for Jetstream InertiaJS vue3 Laravel

First let's install laravel with inertia JS and vue 3.

composer create-project laravel/laravel appname

cd appname

composer require laravel/jetstream

php artisan jetstream:install inertia

npm install

npm run build

php artisan migrate
Enter fullscreen mode Exit fullscreen mode

These instructions are taken from official Jetstream installation page.

And after that got to this directory, resources\js\Components

You will see lot of components. Check on TextInput.vue.

<script setup>
import { onMounted, ref } from 'vue';

defineProps({
    modelValue: String,
});

defineEmits(['update:modelValue']);

const input = ref(null);

onMounted(() => {
    if (input.value.hasAttribute('autofocus')) {
        input.value.focus();
    }
});

defineExpose({ focus: () => input.value.focus() });
</script>

<template>
    <input
        ref="input"
        class="border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm"
        :value="modelValue"
        @input="$emit('update:modelValue', $event.target.value)"
    >
</template>
Enter fullscreen mode Exit fullscreen mode

This is how we call it.

<TextInput id="title" class="w-full" v-model="form.title" placeholder="Give it a great title…" />

const form = useForm({
    title: ''
});

Enter fullscreen mode Exit fullscreen mode

This is the explanation of it. This is common input with useForm. This useForm is a helper function from inertiajs. And v-model is associated with two way data binding.

<input type="text" v-model="form.title">

const form = useForm({
    title: '',
});
Enter fullscreen mode Exit fullscreen mode

Now let's got to inertia component.

defineProps({
    modelValue: String,
});
Enter fullscreen mode Exit fullscreen mode

This is the way of vue 3 composition api to call v-model from sub component. Now this,

defineEmits(['update:modelValue']);
Enter fullscreen mode Exit fullscreen mode

In Vue.js, the emit function is used for child components to send custom events to their parent components. This link says more about emits,

@input="$emit('update:modelValue', $event.target.value)"
Enter fullscreen mode Exit fullscreen mode

Same as here we update parents v-model value with our child component input value.

Now with this knowledge let's create a custom component.

<script setup>
import { ref, defineProps, defineEmits } from 'vue';

const props = defineProps({
    modelValue: File,
});

const emit = defineEmits(['update:modelValue']);

const input = ref(null);

function handleChange(event) {
    const file = event.target.files[0] || null;
    emit('update:modelValue', file);
}

defineExpose({ focus: () => input.value.focus() });
</script>

<template>
    <input
        type="file"
        ref="input"
        class="border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm"
        @change="handleChange"
    >
</template>

And this is how we use it

<ImageUpload id="image" v-model="form.image" />

const form = useForm({
    image: null 
});
Enter fullscreen mode Exit fullscreen mode

Top comments (0)