Reputation: 53
Could you explain why Vue tells me, that Unknown custom element: <MyComponent> - did you register the component correctly?
here:
const CustomComponent = Vue.component('CustomComponent', {
template: '<div>test</div>'
})
const RenderComponent = Vue.component('RenderComponent', {
props: {
component: {
type: [Function, String]
}
},
template: '<component :is="component"></component>'
})
new Vue({
el: '#app',
components: {
MyComponent: CustomComponent,
RenderComponent
},
template: '<render-component component="MyComponent"></render-component>'
})
https://jsfiddle.net/2qobuj4y/1/
How to pass components to a prop properly here? Are there some examples?
Upvotes: 2
Views: 174
Reputation: 63059
MyComponent
doesn't exist so you don't want to list it in your app's components
. Change your app code to:
new Vue({
el: '#app',
components: {
CustomComponent, // Not actually being used, the template passes a string
RenderComponent
},
template: '<render-component component="CustomComponent"></render-component>'
})
Explanation
You have properly registered CustomComponent
as MyComponent
in the main app
component, and you could use it directly in its template. But then you are also passing a string with the value "MyComponent" to the RenderComponent
component. RenderComponent
then tries to instantiate a MyComponent
component, but none exists in the global scope where it is looking for it. (It only exists with that name within the main app
component where you registered it.)
Alternatively, if you were to use a binding instead when you pass MyComponent
(i.e. :component
instead of component
) it still would not work because you can't pass components
as props.
(EDIT: You can but not the traditional way. This works: :foo="$options.components.foo"
. See this comment from Evan You)
Interesting Alternative
You mentioned trying to pass it from data
instead, and while I can't say if it's a good practice, it does work. It could get uglier if you ever migrated to single-file components where you wouldn't have access to a global scope, and it's a little confusing, but it does work:
new Vue({
el: '#app',
data: {
MyComponent: CustomComponent // Taken from global scope
},
components: {
// CustomComponent, // No need in this version
RenderComponent
},
template: '<render-component :component="MyComponent"></render-component>'
})
Upvotes: 1