1

I am trying to make a visual representation of a component library. I am using dynamic <component>s to render each component. However, as I am populating the component with its slots, I am running into issues due to parent methods missing.

I want the components to be usable (demo) therefore I need to compensate for this.$parent not working.

<template>
  <component v-bind:is="'s-' + comp.name" v-bind="props" ref="comp">  <!-- this is the corrent parent-->
    <div v-if="comp.slots">
      <div
        v-for="(slot, i) in comp.slots"
        v-bind:key="i"
        v-bind:slot="slot.name"
      >
        <div v-if="slot.type == 'component'">                         <!-- childs parent -->
          <de-mo v-bind:comp="slot" />                                <!-- this is the child calling a method on the parent -->
        </div>
        <div v-html="slot.value" v-else></div>
      </div>
    </div>
  </component>
</template>

<script>
export default {
  name: 'deMo',
  computed: {
    props() {
      if (this.comp.props) {
        return this.comp.props.reduce((a, r) => {
          a[r.name] = r.value
          return a
        }, {})
      }
    }
  },
  props: {
    comp: {
      type: Object,
      required: true
    }
  },
  methods: this.$ref.comp.methods,                               //<-- this is an error
  mounted(){
    console.log(this.$ref.comp.methods)
  }
},

</script>

<style></style>

1) Is there a way to copy the methods from the parent into this "demo" component via the ref attr 2) Alternatively, is there a better method to produce the same results?

Thanks

1
  • The component library should use Inject provide, it's the recommended way, not direct tree parenting which doesn't work if the child is within an intermediate element Commented Mar 17, 2020 at 11:01

2 Answers 2

1

you can try to spread parent methods in a beforeCreate lifecycle as at this point your parent will be created and your component is going to register its all methods,

beforeCreate() {
    this.$options.methods = { ...this.$parent.$options.methods };
  },

however you can not access any refs in this as refs are only registered after mount of the component.

Note: Any library should use provide and inject to communicate with their component instead of referencing the parent component directly.

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

Comments

0

You can use an Event bus to communicate between components that aren't directly related to each other. Also, this is the recommended way of communication from child to parent in Vue.

bus.js

import Vue from 'vue'
export default new Vue()

demo.vue // child component that wants to call a method in the parent

import Bus from './bus.js'
export default {
 mounted () {
  // [1] child component will emit an event in the bus when it want to call a method of parent 
  Bus.$emit('invoke-parent-fn', 'param')
 }
}

parent.vue // parent component where you want to render other components dynamically

import Bus from './bus.js'
export default {
 methods: {
  fn (param) {
   console.log('// do something ' + param)
  }
 },
 mounted () {
  // [2] parent will be listening to the bus event, when child will emit an event, the handler passed in to the listener will be invoked
  // [3] invoke the required method in the handler
  Bus.$on('invoke-parent-fn', param => this.fn(param))
 }
}

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.