vic
vic

Reputation: 2816

Component Declaration And Communication

I have added a component declaration to the default main.js file which is generated during the Webpack project creation process as

import Modal from '@/components/Modal'
Vue.component('modal', Modal)

And in the App.vue, I have

<modal v-show="showModal"></modal>
<button id="show-modal" v-on:click="showModal = true">Click to have a modal</button>

And they work fine. Now, I need to setup a "props down, events up" communication channel between the parent and a child. To do so, I need to add a property, called 'isActive', the Modal component so that the root component can send a message to the child component, that is

<modal isActive="showModal"></modal>
<button id="show-modal" v-on:click="showModal = true">Click to have a modal</button>

I guess the component declaration should be something like:

Vue.component('modal', {
  props: ['isActive'],
  Modal
})

It doesn't work, however, due to

Failed to mount component: template or render function not defined.

I have tried different variants without a luck.

My second question is that how a child event changes its parent data. For example, in the child component

<button class="modal-close is-large" v-on:click="closeModal"></button>

the closeModal event is handled in the following javacript code in the child component.

export default {
  method: {
    closeModal: function(event) {
      ...
    }
 }
}

How can I set its parent data showModal to false?

Update:

The code segment of Modal:

<template>
<div class="signin">
    <div class="modal" v-bind:class="{ 'is-active': isActive }">
        ...
    </div>
    <button class="modal-close is-large" v-on:click="isActive = false"></button>
        </div>
   </div>
</template>

<script>
import axios from 'axios'
import _ from 'lodash'
import Notification from '@/components/Notification'
import { required, email } from 'vuelidate/lib/validators'

export default {
  name: 'signin',
  components: {
    Notification
  },
  data: () => ({
    isActive: true,
    email: '',
    ...
  }),
  ...
}
</script>

Bulma is used for styling. And the isActive is defined in the Modal. I think it needs to be changed to achieve "props down".

Upvotes: 0

Views: 432

Answers (1)

cello
cello

Reputation: 5486

As it looks, your file /components/Modal contains a full definition of a component: the template, and the script parts for it. So you can just bind the component to the tag-name you want to use in your markup:

import Modal from '@/components/Modal'
Vue.component('modal', Modal)

This is basically what you had in the beginning. To pass properties to this component, add the props-line directly to your component, that is into /components/Modal:

...
export default {
  name: 'signin',
  components: {
    Notification
  },
  props: ['isActive'],
  data: () => ({
    ...

As for the second question, how to communicate back to the parent, have a look at Vue's Custom Events. Basically, your Modal component could issue a "close"-event like this:

methods: {
  closeModal: function(event) {
    this.$emit('modalClose')
  }
}

and when you use the component, you could listen to it like this:

<modal v-bind:isActive="showModal" v-on:modalClose="showModal = false"></modal>

Note that you should use v-bind for providing the value to isActive. If you don't use v-bind, the value is just passed once when the component is created. This means, the component would never see a change to this prop when it is changed by the parent. By using v-bind, changes by the parent to this attribute are pushed down to the child-component, so the Modal actually sees the updated value and can react to it.

Upvotes: 1

Related Questions