Skip to content
Advertisement

print Component B inside component A – vue.js

Using Vue.js, How to create componentA that gets componentB as a prop, and print it inside of it?

example:

index.vue

<template>
    <div>
        <componentA :componentPlaceHolder="componentB"></componentA>
    </div>
</template>

<script>
import componentA from './compnentA.vue';
import componentB from './componentB.vue'
export default {
    name: 'index',
    components: {componentA,componentB }    
}
</script>

componentA.vue

<template>
    <div>
        {{componentPlaceHolder}}
    </div>
</template>

<script>
export default {
    name: 'componentA',
    props: {
        'componentPlaceHolder': {}
    }    
}
</script>

Advertisement

Answer

There are some issues to your implementation:

  1. You have gotten the scope wrong: componentPlaceHolder lives in the parent scope, not in that of component A. Read: Compilation Scope.

  2. Use :is (i.e. v-bind: is) for dynamic component binding. The data bound should reference the key of the component.

  3. Since you are nested additional components in another component in the same context, that means you have to interweave the content. This is done by using slots, declared in <component-a>.

  4. Avoid using case-sensitive DOM elements, use kebab case instead, i.e. <component-a> instead of <componentA>, since HTML elements are case-insensitive (<componentA> and <componenta> will be treated the same).

Here is the updated code:

<template>
    <div>
        <component-a>
            <customComponent :is="componentPlaceHolder"></customComponent>
        </component-a>
    </div>
</template>

<script>
import componentA from './componentA.vue';
import componentB from './componentB.vue'
export default {
    name: 'index',
    components: {
        'component-a': componentA,
        'component-b': componentB
    },
    data: {
        componentPlaceHolder: 'component-b'
    }
}
</script>

And then in your componentA.vue:

<template>
    <div>
        <!-- Slot will interweave whatever that is found in <componentA> -->
        <slot></slot>
    </div>
</template>

<script>
export default {
    name: 'componentA'  
}
</script>

Proof-of-concept example

If in doubt, here is a live proof-of-concept example:

var componentA = {
  template: '#component-a'
};

var componentB = {
  template: '#component-b'
};

new Vue({
  el: '#app',
  components: {
    'component-a': componentA,
    'component-b': componentB
  },
  data: {
    componentPlaceHolder: 'component-b'
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<div id="app">
  <component-a>
    <!-- DOM elements in here will be interweaved into <slot> -->
    <customComponent :is="componentPlaceHolder"></customComponent>
  </component-a>
</div>

<template id="component-a">
  <div>
    <p>I am component A</p>
    <slot></slot>
  </div>
</template>

<template id="component-b">
  <p>I am component B</p>
</template>

Footnote:

The VueJS readme is exceptionally composed, and I suggest here are some things that you can read up on that is very relevant to your use case:

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement