0
votes

I have one app with one major root component, the Editor. This Editor allows adding, editing and removing rows and columns. Rows have names but columns have name and limit (number).

Row(name:string)
Column(name:string, limit:number)

When adding or editing a row or a column I have to open the form in a modal. When remove one, I have to display a confirmation dialog.

+-- Editor ---------------------------------------------------------------+
|                                                                         |
|  +-- {{Add|Edit}} row ----+                                             |
|  |                        |                                             |
|  | name: [..............] |    +-- Confirm delete of {{row|column}} -+  |
|  |         [Cancel][Save] |    | Confirm deletion of {{row|column}}? |  |
|  +------------------------+    |                           [No][Yes] |  |
|                                +-------------------------------------+  |
|  +-- {{Add|Edit}} column -+                                             |
|  |                        |                                             |
|  |  name: [.............] |                                             |
|  | limit: [...]           |                                             |
|  |         [Cancel][Save] |                                             |
|  +------------------------+                                             |
|                                                                         |
+-------------------------------------------------------------------------+

--

Actually I have a ModalManager that is too generic and compute the model and title of the modal (or confirmation dialog) based on the subject (row or column) and action (add, edit, delete).

Two Modal components with custom form and one Confirmation component are driven by the ModalManager:

<Confirmation v-if="manager.mode==='CONFIRM'" 
    title="manager.title"></Confirmation>
<Modal v-if="manager.model='ROW' && manager.mode!=='CONFIRM'
    title="manager.title">
  <!-- form for row with v-model="manager.model" -->
</Modal>
<Modal v-if="manager.model='COLUMN' && manager.mode!=='CONFIRM'
    title="manager.title">
  <!-- form for column with v-model="manager.model" -->
</Modal>

As you can imagine, this is a mess and I would like to refactor that to something better. But I do not have enough experience with Vue to have a good view on the possibilities.

I can have a separate model/controler for each modal OR use my Vuex store OR use the vue-router. But, again, I have no clue on how to do it.

--

What can I do to improve my code and manage which modal is shown and the actions linked to them ?

Edit: I am afraid, I was not asking on "how to create a modal". But how to manage complex state inside one root component.

1
I would recommend using one of these nice components rather than reinventing the wheel. They have quite a variety of selections to choose from. You could add your form/contents in the modal as well.Yom T.

1 Answers

0
votes

You could create a component for your specific needs. Something like this should get you started.

<template>
   <div class="modal" v-if="show">
      <h3>{{title}}</h3>
      <div class="content" v-html="content">
         <!-- Remove this if you don't need complex content -->
         <slot></slot>
      </div>

      <div role="group">
         <button @click="submit">Save</button>
         <button @click="close">Cancel</button>
      </div>
   </div>
</template>

<script>
   export default {
      name: 'Modal',

      data() {
         return {
            show: false,
            title: '',
            content: '' // <- Accepts both HTML and plain text (as message)
         }
      },

      methods: {
         toggle(state) {
            this.show = state;  
         },

         open(title, content) {
            this.title = title;
            this.content = content;

            this.toggle(true);
         },

         close() {
            this.toggle(false);
         },

         submit() {
            // Handle form submission here
            this.close();
         }
      }
   }
</script>

JS

import Modal from './components/Modal.vue';

const vm = new Vue({
   methods: {
      editItem() {
         this.$refs.modal.open('Title', 'Content here');
      }
   },

   components: {
      Modal
   }
})

HTML

<table>
   <!-- rows and stuff -->
</table>

<!-- Add a `ref` so that it can be referenced later -->
<modal ref="modal"></modal>

<button @click.prevent="editItem">Edit item</button>