8

I have two component a Card component and a modal component, the modal component contains the modal Elements, in my Card component I would like to have a button which opens the modal Window of my modal component. How do I manage that, so far I have done this:

My Card component:

<template>
    <v-layout v-if="visible">
        <v-flex xs12 sm6 offset-sm3>
            <v-card>
                <v-card-title primary-title>
                    <div>
                        <h3 class="headline mb-0">test</h3>
                        <div>test</div>
                    </div>
                </v-card-title>

                <v-divider light></v-divider>

                <v-card-actions>
                <v-btn
                    color="primary"
                    dark
                    @click="dialog = true"
                >
                Open Dialog
                </v-btn> <!-- open modal dialog of modal component? -->

                    <tenant-number-modal></tenant-number-modal>
                </v-card-actions>

                <input type="hidden" id="tenant-id" :value=tenantId>
            </v-card>
        </v-flex>
    </v-layout>
</template>

<script>
    export default {
        data () {
            return {
                visible: true,
                dialog: false,
                uniqueTenantNumber: ''
            }
        },
    }
</script>

My Modal component:

<template>
    <v-layout row justify-center>
        <v-btn
            color="primary"
            dark
            @click="dialog = true"
        > <!-- this calls the modal but only in this component -->
        Open Dialog
        </v-btn>

        <v-dialog
            v-model="dialog"
            max-width="290"
        >
            <v-card>
                <v-card-title class="headline">test</v-card-title>
            </v-card>
        </v-dialog>
    </v-layout>
</template>

<script>
  export default {
    data () {
      return {
        dialog: false
      }
    }
  }
</script>
0

4 Answers 4

11

You can call a method of another component by using a ref.

    <v-card-actions>
      <v-btn
       color="primary"
       dark
       @click="openModal">
      Open Dialog
      </v-btn> <!-- open modal dialog of modal component? -->
      <tenant-number-modal ref="modal"></tenant-number-modal>
    </v-card-actions>
...
<script>
   export default {
      data () {
         return {
            //visible: true,
            //dialog: false,
            //uniqueTenantNumber: ''
         }
      },
      methods: {
         openModal() {
            this.$refs.modal.showModal();
         }
      }
   }
</script>

Your modal component:

<template>
    <v-layout row justify-center>
    ...
        <v-dialog
            v-model="dialog"
            max-width="290">
            <v-card>
                <v-card-title class="headline">test</v-card-title>
            </v-card>
        </v-dialog>
    </v-layout>
</template>

<script>
  export default {
    data () {
      return {
        dialog: false
      }
    },
    methods: {
       showModal() {
       this.dialog = true;
       }
    }
  }
</script>
Sign up to request clarification or add additional context in comments.

1 Comment

Nice this worked but there is no modal fade in Animation, how can I fix that?
7

What you can do is create an event bus. This will allow you to send messages to 1+ components at once. Once you emit the message, then all components that are listening will execute.

First you need to create the bus:

bus.js

import Vue from 'vue';
export const EventBus = new Vue();

Next in the component that will emit the message you call EventBus.$emit(name, data)

componentA.js

import { EventBus } from './bus.js';

export default {
  methods: {
    emitGlobalClickEvent() {
      EventBus.$emit('i-got-clicked', 'extra data');
    }
  }
}

Then in your other components, you just need to listen for the event. The following can be added to the component and you just need to use EventBus.$on(name, handle) or if you only want to listen once use EventBus.$once(name, handle).

componentB.js

import { EventBus } from './bus.js';

export default {
  created() {
    EventBus.$on('i-got-clicked', data => {
      console.log(data)
      // You can then call your method attached to this component here
      this.openModal()
    });
  },
  methods: {
    openModal() {
      console.log('I am opening')
    }
  }
}

2 Comments

Was stuck on this for 3 days, finally! Only this works for independent components.
@HariHarker I would now recommend using Vuex to handle this.
2

For call any method of a component from any other component

Add a $on function to the $root instance from mounted section. then call form any other component accessing the $root and calling $emit function.

On first component:

    mounted() {
        this.$root.$on('mySpecialName', () => {
            // your code goes here
        }
    }

on second component:

    someComponent2Method: function(){
     // your code here
     this.$root.$emit('mySpecialName') //like this
    },

Comments

1

TestModal.vue:

<template>
  <v-dialog v-model="modalState" max-width="500px">
    <v-card>
      <v-card-title>
        This is a modal in another component.
      </v-card-title>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn color="primary" @click="modalState = false">
          Close
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<script>
export default {
  data() {
    return {
      modalState: false,
    }
  },
  methods: {
    showModal() {
      this.modalState = true
    },
  },
}
</script>

in your parent file (index.vue):

<template>
  <v-layout column justify-center align-center>
    <v-flex xs12 sm8 md6>
      <test-modal ref="customModal" />
      <v-btn large color="primary" @click.stop="runModal">
        Run Modal
      </v-btn>
    </v-flex>
  </v-layout>
</template>

<script>
import TestModal from '~/components/TestModal.vue'

export default {
  components: {
    TestModal,
  },
  methods: {
    runModal() {
      this.$refs.customModal.showModal()
    },
  },
}
</script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.