Reputation: 464
I'm trying to create a dynamic component and pass a prop to it. I'm getting the warning:
Component is missing template or render function.
The component is being rendered, but i'm still getting the warning and the prop is not being passed to it.
Parent:
<template lang="pug">
q-page
component(:is="detailsComponent" v-bind="selectedRule")
</template>
<script lang="ts">
import { defineComponent, ref, shallowRef, onMounted } from 'vue'
import { useStore } from 'vuex'
import { storeKey } from '../store'
import { useRoute, useRouter } from 'vue-router'
import { RuleList } from '../components/models'
export default defineComponent({
name: 'CodeDetails',
setup() {
const store = useStore(storeKey)
const route = useRoute()
const router = useRouter()
const detailsComponent = shallowRef({})
const selectedRule = ref({} as RuleList)
const selectComponent = async (ruleName: string) => {
let fileName = ''
switch (ruleName) {
case 'retailFoodRules': fileName = 'FoodDetails'
break
case 'generalRules': fileName = 'GeneralDetails'
break
case 'poolRules': fileName = 'PoolDetails'
break
default: fileName = 'OtherDetails'
}
const component = await import(`../components/${fileName}`) as unknown
detailsComponent.value = component.default as RuleList
}
onMounted(() => {
const selected = JSON.parse(route.params.ruleString as string) as RuleList
const ruleName = route.params.rule
if (route.params) {
selectedRule.value = selected as unknown as RuleList
void store.dispatch('searchResults/saveSelectedRule', selected)
// void store.dispatch('searchResults/saveRuleName', ruleName)
void selectComponent(ruleName as string)
} else if (!route.params && store.state.searchResults.selectedRule) {
selectedRule.value = store.state.searchResults.selectedRule
// selectComponent(store.state.searchResults.ruleName)
} else {
router.go(-1)
}
})
return { detailsComponent, selectedRule }
},
})
</script>
Child (the other dynamic child components are similar):
<template lang="pug">
q-card(flat)
q-card-section
q-item-label.text-caption.text-grey-9 Description
q-item-label.text-subtitle1(v-html="selectedRule.Description")
q-separator
q-card-section
q-item-label.text-caption.text-grey-9 Classification
q-item-label.text-subtitle1(v-html="selectedRule.Classification" :class="{'text-negative': selectedRule.Classification === 'Priority', 'text-orange-9': selectedRule.Classification === 'Priority Foundation'}")
q-separator
q-card-section
q-item-label.text-caption.text-grey-9 Section
q-item-label.text-subtitle1(v-html="selectedRule.Section")
q-separator
q-card-section
q-item-label.text-caption.text-grey-9 Category
q-item-label.text-subtitle1(v-html="selectedRule.Category")
q-separator
q-card-section
q-item-label.text-caption.text-grey-9 Compliance Categories
q-item-label.text-subtitle1(v-html="selectedRule.Compliance")
q-separator
q-card-section
q-item-label.text-caption.text-grey-9 Rule Text
q-item-label.text-subtitle1(v-html="selectedRule.FullText")
</template>
<script lang="ts">
import { defineComponent, toRefs } from 'vue'
import { RuleList } from '../components/models'
export default defineComponent({
name: 'FoodDetails',
setup(props) {
// console.log(Object.assign({}, props))
const selectedRule = toRefs(props.selectedRule as RuleList)
return { selectedRule }
}
})
</script>
In the child component I get the error: Property 'selectedRule' does not exist on type '{}'.
on the line const selectedRule = toRefs(props.selectedRule as RuleList)
so it's not seeing the prop that was passed. The odd thing is that if I examine the child component with the Vue devtools it shows selectedRule
as an attr but not as a prop. Am I doing something wrong or is this a Quasar quirk?
Upvotes: 1
Views: 1797
Reputation: 464
I changed this line in the parent component from:
component(:is="detailsComponent" v-bind="selectedRule")
back to:
component(:is="detailsComponent" :selectedRule="selectedRule")
In the child key I added a prop key, used Object.assign() to get the prop value, since it comes in as a proxy, and removed toRef(), since it's not reactive anyway.
export default defineComponent({
name: 'FoodDetails',
props: {
selectedRule: {
type: Object,
required: true
}
},
setup(props) {
const ruleObject = Object.assign({}, props.selectedRule) as RuleList
return { ruleObject }
}
})
</script>
The Component is missing template or render function.
warning is still there, even though the component is rendering and displaying the data from the prop.
Upvotes: 0
Reputation: 1
For the parent component it looks fine, but for the child one you add the props
option :
<script lang="ts">
import { defineComponent, toRefs } from 'vue'
import { RuleList } from '../components/models'
export default defineComponent({
name: 'FoodDetails',
props:{
selectedRule : {
type : Object as PropType<RuleList >
}
},
setup(props) {
// console.log(Object.assign({}, props))
const selectedRule = toRefs(props.selectedRule)
return { selectedRule }
}
})
</script>
Upvotes: 1