vue 🚀
laravel 🚀
VueJS and sharing modelValue state with a Component

Thanks to the code that comes with Laravel Jetstream we have examples of components that can be easily used in multiple forms.

For example I can use the shared Label, Input, InputError

<!--more-->
<div class="col-span-6">
  <Label for="password" value="Password"/>
	<Input id="password" type="text"
	  class="mt-1 block w-full"
	  v-model="form.user.password"
	  autofocus
	  placeholder="leave empty to not update"
	  autocomplete="off"/>
  <InputError class="mt-2" :message="form.errors['user.password']"/>
</div>

And get all the updates in the component I am using it in. Looking into the shared component, Input in this example.

<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-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm"
        :value="modelValue"
        @input="$emit('update:modelValue', $event.target.value)"
    >
</template>

Which means my component Edit.vue which has form.user.password will get updated as the person types into the field of the child component.

Here is another example of a select list:

<template>
    <select
        v-model="modelValue"
        @change="$emit('update:modelValue', $event.target.value)"
        class="w-full">
        <option v-for="option in options" :for="option.id"
                :value="option.id">
            {{ option.name }}
        </option>
    </select>
</template>

<script>
export default {
    name: "TeamSelect",
    props: {
        modelValue: String,
        options: Object
    },

}
</script>

<style scoped>

</style>

It is using the modelValue shared state that can then be emitted on change. This is seen in the VueJs docs here and in a good Laracast Videos here