1

I'm building simple modal component with Vue. I want to use this component in a parent components and to be able to toggle it from the parent.

This is my code now of the modal component:

<script>
export default {
	name: 'Modal',
	data() {
		return {
			modalOpen: true,
		}
	},
	methods: {
		modalToggle() {
			this.modalOpen = !this.modalOpen
		},
	},
}
</script>
<template>
	<div v-if="modalOpen" class="modal">
		<div class="body">
			body
		</div>
		<div class="btn_cancel" @click="modalToggle">
			<i class="icon icon-cancel" />
		</div>
	</div>
</template>

I use the v-if to toggle the rendering and it works with the button i created inside my modal component.

However my problem is: I don't know how to toggle it with simple button from parent component. I don't know how to access the modalOpen data from the modal component

3 Answers 3

2

Ok, let's try to do it right. I propose to make a full-fledged component and control the opening and closing of a modal window using the v-model in parent components or in other includes.

1) We need declare prop - "value" in "props" for child component.

<script>
export default {
    name: 'Modal',
    props: ["value"],
    data() {
        return {
            modalOpen: true,
        }
    },
    methods: {
        modalToggle() {
            this.modalOpen = !this.modalOpen
        },
    },
}
</script>

2) Replace your "modalToggle" that:

modalToggle() {
  this.$emit('input', !this.value);
}

3) In parent components or other includes declare "modal=false" var and use on component v-model="modal" and any control buttons for modal var.

summary

<template>
    <div v-if="value" class="modal">
        <div class="body">
            body
        </div>
        <div class="btn_cancel" @click="modalToggle">
            <i class="icon icon-cancel" />
        </div>
    </div>
</template>

<script>
export default {
  name: "Modal",
  props: ["value"],
  methods: {
    modalToggle() {
      this.$emit("input", !this.value);
    }
  }
};
</script>

Example:

Vue.component('modal', {
  template: '<div v-if="value" class="modal"><div class="body">modal body</div><div class="btn_cancel" @click="modalToggle">close modal<i class="icon icon-cancel" /></div></div>',
  props: ["value"],
	methods: {
		modalToggle() {
      this.$emit('input', !this.value);
		}
	}
});

// create a new Vue instance and mount it to our div element above with the id of app
var vm = new Vue({
  el: '#app',
  data:() =>({
  modal: false
  }),
  methods: {
  openModal() {
  this.modal = !this.modal;
  }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div @click="openModal">Btn modal</div>
  
  <modal v-model="modal"></modal>
</div>

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your detailed answer. Now it works as desired. I have one side question. What's a proper way to open the modal after short delay ? Is using a function like setInterval() or something similar ?
Depending on the purpose. What is your purpose with setInterval()?
I want after my landing page loads, after short delay (5sec for example) my modal component to pop up, I also want to pop up once and not on every page reloading
I think you can use setTimeout (developer.mozilla.org/en-US/docs/Web/API/…) instand of setInterval for one launch. After it you needs store state, you can use localStorage (developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). Also you can use hook created() on page and detect state after reload page.
1

With your current implementation I would suggest you to use refs https://v2.vuejs.org/v2/guide/components-edge-cases.html#Accessing-Child-Component-Instances-amp-Child-Elements

So in your parent component add ref="child" to modal (child) component and then open your modal by calling this.$refs.child.modalToggle()

Comments

0
  1. You can use an "activator" slot

  2. You can use ref="xxx" on the child and access it from the parent

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.