1

I want to create a reusable v-dialog with vuetify, I created the BaseModal:

     <v-dialog
      v-model="inputVal"
      :hide-overlay="overlay"
      :max-width="width"
    >
      <v-card>
        <v-toolbar flat>
          <v-btn color="black" dark icon right @click="closeModal">
            <v-icon>mdi-close</v-icon>
          </v-btn>
          <v-spacer></v-spacer>
          <v-toolbar-title id="toolbar-title">{{ title }}</v-toolbar-title>
        </v-toolbar>
        <v-card-title class="headline">
          <!--Card Title-->
        </v-card-title>
        <v-card-text>
          <slot name="content"></slot>
        </v-card-text>
      </v-card>
    </v-dialog>

InputVal as computed and dataBindingName as props :

  computed: {
    inputVal: {
      get() {
        return this.dataBindingName;
      },
      set(val) {
        this.$emit("input", val);
      }
    }
  },
props: {
    dataBindingName: {
      Boolean,
      required: false
    },}

I'm calling this base component in another component like this:

<modal-simple
  :dataBindingName="dataBindingName"
  title="Nouveau"
  width="418"
>
  <template v-slot:content>
    <add-time-sheet-form />
  </template>

</modal-simple>

My problem now is how to implement correctly the closeModal and how to implement a button inside that close the modal and open a new modal

SAFSAF
  • 375
  • 1
  • 4
  • 14
  • You must use `this.$emit` to close modal, read [here](https://medium.com/@rafaelogic/a-dynamic-and-reusable-vuejs-modal-component-under-laravel-development-648041a85350) – proofzy Feb 15 '21 at 14:52

1 Answers1

3

Part 1. Modal component.

Take care that you should not use v-model="dialog". As already described in this answer, you need to replace it with :value and @input.

Moreover, you should not mutate dialog prop directly, that's why you need to emit close-dialog event when you need to close your modal.

<template>
  <v-dialog
    :value="dialog"
    @input="$emit('input', $event)"
    max-width="500px"
    persistent
  >
    <v-card>
      <v-card-title>
        ... dialog header ...
      </v-card-title>
      <v-card-text>
        ... dialog content ...
      </v-card-text>
      <v-card-actions>
        <v-spacer />
        <v-btn @click="close">
          Close
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<script>
export default {
  props: {
    editedId: Number,
    dialog: Boolean,
  },
  methods: {
    close() {
      this.$emit("close-dialog");
    },
  },
};
</script>

Part 2. Parent component.

Imagine you want to use your component when adding or editing entities.

You need to implement two methods: addItem and editItem to open your dialog. You also need to pass extra entity props (editedId in my example), dialog prop with sync modifier and close-dialog event handler that was emitted from modal component.

<template>
  <div>
    <v-toolbar flat color="white">
      <v-spacer />
      <edit-modal
        :edited-id="editedId"
        :dialog.sync="dialog"
        @close-dialog="
          editedId = null;
          dialog = false;
        "
      />
      <v-btn color="primary" dark class="mb-2" @click="addItem">
        Add entity
      </v-btn>
    </v-toolbar>
    <v-data-table :items="items" :headers="headers">
      <template v-slot:item="props">
        <tr>
          <td>{{ props.item.name }}</td>
          <td class="justify-center text-center">
            <v-icon small class="mr-2" @click="editItem(props.item)">
              edit
            </v-icon>
          </td>
        </tr>
      </template>
    </v-data-table>
  </div>
</template>

<script>
import Dialog from "./ReusableDialog";

export default {
  components: {
    "edit-modal": Dialog,
  },
  data() {
    return {
      items: [
        ... some items ...
      ],
      headers: [
        ... some headers ...
      ],
      editedId: null,
      dialog: false,
    };
  },
  methods: {
    addItem() {
      this.dialog = true;
    },
    editItem(item) {
      this.editedId = item.id;
      this.dialog = true;
    },
  },
};
</script>

Part 3. Modifying modal to reopen automatically.

In this example, modal component will reopen automatically until editedId will not be set.

In modal component:

...
close() {
  this.$emit("close-dialog");
  if (this.editedId === null) {
    this.$emit("open-dialog");
  }
},
...

In parent component:

...
<edit-modal
  ... some props ...
  @open-dialog="
    editedId = 999;
    dialog = true;
  "
/>
...

There is a codesandbox with working example.

Alexander Shkirkov
  • 3,527
  • 3
  • 17
  • 37