Home > Enterprise >  Pass data from component
Pass data from component

Time:07-25

I'm fairly new to Vue and I'm trying to pass data from a component to a view. I'm not sure if I'm using props right. I have a dialog and when I save, I want to insert the data to the database. I also want to reuse the addCustomer() function that's why I didn't place the function in the component.

pages/customers.vue

<template>
  <div>
    <div >
      <Heading
        title="Customers"
        desc="The list of customers or companies you work with."
      />
      <button @click="openModal" >Add New Customer</button>
    </div>

    <CustomerList  :customers="customers" />
  </div>
  <CustomerDialog
    :is-open="isOpen"
    :close-modal="closeModal"
    :open-modal="openModal"
    :name="name"
    :address="address"
    :email="email"
    :add-customer="addCustomer"
  />
</template>

<script setup>
const client = useSupabaseClient();

const name = ref("");
const address = ref("");
const email = ref("");

const isOpen = ref(false);

function closeModal() {
  isOpen.value = false;
}
function openModal() {
  isOpen.value = true;
}

const { data: customers } = await useAsyncData("customers", async () => {
  const { data } = await client.from("customers").select("*");
  return data;
});

async function addCustomer() {
  if (name.value == "" || address.value == "" || email.value == "") return;

  const { data } = await client.from("customers").upsert({
    name: name.value,
    address: address.value,
    email: email.value,
  });
  customers.value.push(data[0]);
  name.value = "";
  address.value = "";
  email.value = "";
  closeModal();
}
</script>

components/customer/Dialog.vue

<template>
    <Dialog as="div" @close="closeModal" >
        <input type="text" id="name" v-model="name" />
        <input type="text" id="address" v-model="address" />
        <input type="email" id="email" v-model="email" />
        <button type="button" @click="addCustomer">Save</button>
        <button type="button" @click="closeModal">Cancel</button>
    </Dialog>
</template>

<script setup>
defineProps([
  "name",
  "address",
  "email",
  "addCustomer",
  "isOpen",
  "closeModal",
  "openModal",
]);
</script>

EDIT: The Cancel button in the Dialog works while Save button doesn't.

CodePudding user response:

You cannot bind props directly to the v-model directive, in your case you've to use Multiple v-model bindings

<template>
    <Dialog as="div" @close="closeModal" >
        <input type="text" id="name" :value="name" @input="$emit('update:name', $event.target.value)"/>
        <input type="text" id="address" :value="adress" @input="$emit('update:address', $event.target.value)" />
        <input type="email" id="email" :value="email" @input="$emit('update:email', $event.target.value)" />
        <button type="button" @click="$emit('add-customer')">Save</button>
        <button type="button" @click="closeModal">Cancel</button>
    </Dialog>
</template>

<script setup>
defineProps([
  "name",
  "address",
  "email",
  "addCustomer",
  "isOpen",
  "closeModal",
  "openModal",
]);

defineEmits(['update:name', 'update:email','update:address','add-customer'])
</script>

in parent component :

 <CustomerDialog
    :is-open="isOpen"
    :close-modal="closeModal"
    :open-modal="openModal"
    v-model:name="name"
    v-model:address="address"
    v-model:email="email"
    @add-customer="addCustomer"
  />

CodePudding user response:

As addCustomer method is available in parent. What you can do is that emit an event on Save button click from the dialog component and then capture the event in parent and invoke addCustomer method.

I just created a below code snippet with Vue 2.* just for your understanding purpose.

Vue.component('customerdialog', {
  data() {
    return {
        customerDetailObj: {}
    } 
  },
  props: ['name', 'address', 'email'],
  mounted() {
    this.customerDetailObj = {
        name: this.name,
      address: this.address,
      email: this.email
    }
  },
  template: `<div><input type="text" id="name" v-model="customerDetailObj.name" />
        <input type="text" id="address" v-model="customerDetailObj.address" />
        <input type="email" id="email" v-model="customerDetailObj.email" />
        <button type="button" @click="$emit('add-customer', customerDetailObj)">Save</button></div>`
});

var app = new Vue({
  el: '#app',
  data: {
    name: 'Alpha',
    address: 'Street 1',
    email: '[email protected]',
    customerList: []
  },
  methods: {
    addCustomer(customerObj) {
      // Created user details
      this.customerList.push(customerObj);
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <CustomerDialog :name="name"
    :address="address"
    :email="email" @add-customer="addCustomer($event)"></CustomerDialog>
  <pre>{{ customerList }}</pre>
</div>

CodePudding user response:

You'll want to use event emitters:

In the dialog:

<button @click="$emit('addCustomer')">save</button>

In customers.vue:

<CustomerDialog
    :is-open="isOpen"
    :close-modal="closeModal"
    :open-modal="openModal"
    :name="name"
    :address="address"
    :email="email"
    @add-customer="addCustomer"
  />

CodePudding user response:

You can defineEmits

<script setup>
import {
  TransitionRoot,
  TransitionChild,
  Dialog,
  DialogPanel,
  DialogTitle,
} from "@headlessui/vue";

defineProps([
  "name",
  "address",
  "email",
  "addCustomer",
  "isOpen",
  "closeModal",
  "openModal",
]);

let emit = defineEmits(["add"])
</script>

Or better with typescript:

<script lang="ts" setup>
import {
  TransitionRoot,
  TransitionChild,
  Dialog,
  DialogPanel,
  DialogTitle,
} from "@headlessui/vue";

defineProps([
  "name",
  "address",
  "email",
  "addCustomer",
  "isOpen",
  "closeModal",
  "openModal",
]);
let emit = defineEmits<{ (name: "add"): void }>()
</script>

Now you can use it in your button:

            <button
              type="button"
              
              @click="emit('add')"
            >
              Save
            </button>

Now you can listen to this add event and trigger your addCustomer function

  <CustomerDialog
    :is-open="isOpen"
    :close-modal="closeModal"
    :open-modal="openModal"
    :name="name"
    :address="address"
    :email="email"
    @add="addCustomer"
  />
  • Related