Dan
Dan

Reputation: 946

Failed to resolve a component in vue

In Content.vue I have the line: let html = this.html.replace('[BuyHere]', '<buy-button :label="label"></buy-button>'); which is causing a 'failed to resolve component: buy-button' warning. The replace works if I take out reference to but I don't understand why I am getting this warning, as I believe I have imported and declared it correctly.

main.js

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

App.vue

<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <ContentView/>
</template>

<script>
import ContentView from './components/ContentView.vue'

export default {
  name: 'App',
  components: {
    ContentView
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
}
</style>

Content.vue

<template>

    <component v-bind:is="processedHtml"></component>

</template>
<script>

    import BuyButton from "./BuyButton.vue"

    export default {
        name: 'ContentView',
        components: {
            BuyButton
        },        
        data () {
            return {
                html: '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>[BuyHere]<p>Donec tellus arcu, rhoncus eget leo sit amet, blandit aliquam sapien.</p><p>Aenean leo ligula, ultricies non nisi non, laoreet mattis arcu.</p>',
                label: 'Buy Here! -10% Off',
            }
        },
        computed: {

            processedHtml () {
                let html = this.html.replace('[BuyHere]', '<buy-button :label="label"></buy-button>');
                return {
                    template: '<div>' + html + '</div>',
                    props: {
                        label: {
                            type: null,
                            default: () => { return this.label }
                        },
                    }
                }
            }
        }
    }

</script>

BuyButton.vue

<template>

    <input type="button" :value="label">

</template>
<script>

    export default {
        name: 'BuyButton',
        props: ['label']
    }

</script>

Upvotes: 1

Views: 1361

Answers (1)

Michal Lev&#253;
Michal Lev&#253;

Reputation: 37753

components: {
  BuyButton
},

is local registration. Local means that the component is recognized in ContentView components template only

By passing the object (return value of processedHtml - component’s options object) into v-bind:is you are basically creating a new "unnamed" component and using the BuyButton component inside it's template but it is not registered there...

Fix:

processedHtml () {
                let html = this.html.replace('[BuyHere]', '<buy-button :label="label"></buy-button>');
                return {
                    components: {
                      BuyButton
                    },
                    template: '<div>' + html + '</div>',
                    props: {
                        label: {
                            type: null,
                            default: () => { return this.label }
                        },
                    }
                }
            }

https://v3.vuejs.org/api/special-attributes.html#is

Upvotes: 1

Related Questions