Cannot read properties of undefined (reading 'id') - vue.js

I'm using #storybook/vue to make my storybook and I'm trying to embed a view component in my mdx files but I get these errors:
"Cannot read properties of undefined (reading 'id')" and "The above error occurred in the component".
I've followed the documentation and searched on different forums but I can't find it.
my code :
button.docs.mdx
import { Canvas, Meta, Story } from '#storybook/addon-docs';
import Table from "#/stories/stories-component/Table.vue";
<Meta title="Bootstrap Custom Button Documentation" />
# Test
<Canvas>
<Story name="test table">
{() => {
return {
components: { Table },
template: `<Table></Table>`
};
}}
</Story>
</Canvas>
Table.vue
<template>
<p>test component </p>
</template>
<script>
export default {
name:"Table",
props: {}
}
</script>

Related

Vue 3, what can be the cause of "Failed to resolve component" error?

I am trying to include one component into another component, but I am getting the error "Failed to resolve component: applications-overview-table" in the browser console.
Parent component "src/pages/ApplicationsOverview.vue":
<template>
<q-page class="flex flex-center">
<applications-overview-table></applications-overview-table>
</q-page>
</template>
<script>
import ApplicationsOverviewTable from '../components/application/OverviewTable.vue';
export default {
name: 'ApplicationsOverviewPage',
components: [ApplicationsOverviewTable],
setup() {
console.log('loading applications overview');
return {};
},
};
</script>
<style></style>
Child component "src/applications/OverviewTable.vue":
<template>
<div class="q-pa-md">
<q-table title="Aanvragen" :rows="rows" :columns="columns" row-key="name" />
</div>
</template>
<script>
const columns = [ ... ];
const rows = [ ... ];
export default {
name: 'ApplicationsOverviewTable',
setup() {
return {
columns,
rows,
};
},
};
</script>
I can see that the parent component is being loaded, because the console message "loading applications overview" is being shown in the console.
I can also see that the path to OverviewTable.vue is correct, because if I change the path I get another error.
I tried to change <applications-overview-table> to <ApplicationsOverviewTable> but this gives me the same error (with the tag-name different of course).
It is right that I should change the CamelCase component name to dash-case in the templete, isn't it?
What am I doing wrong?
components option has an object as value not an array, it should be :
components: {ApplicationsOverviewTable},
this a shorthand of :
components: {
ApplicationsOverviewTable : ApplicationsOverviewTable
},

Why can't apollo get data in first request?

I am using props to get the Id of birds.
When I first start the app and click to enter the second-page, data won't load.
It gives the following error;
JS: [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined"
JS:
JS: found in
JS:
JS: ---> <Detail> at components/Detail.vue
JS: <Frame>
JS: <Root>
But after I click on button second time it loads properly.
I have created a repo showing the problem. Please check it here:
github repo
Working graphql playground
<template>
<Page>
<StackLayout>
<Label :text="bird.name" textWrap="true" />
<Button text="get data" #tap="getData" />
</StackLayout>
</Page>
</template>
<script>
import { gql } from "apollo-boost";
export default {
props: ["birdID"],
apollo: {
bird: {
query: gql`
query($id: ID!) {
bird(id: $id) {
id
name
}
}
`,
variables() {
return {
id: this.birdID,
};
},
},
},
methods: {
getData() {
console.log("bird data: ", this.bird);
},
},
mounted() {},
};
</script>
<style></style>
Is there a better way to get data?
Answer was correct
I have updated github repo with solution.
https://github.com/kaanguru/query-data-from-prop
The issue is that your template
<Label :text="bird.name" textWrap="true" />
attempts to display bird.name before your query has completed.
The Vue Apollo documentation shows a simple work-around by defining some initial defaults
You can initialize the property in your vue component's data hook
data: () => ({
bird: {
name: null
}
}),
Alternately, make use of the Loading state feature to conditionally render your components
<Label v-if="$apollo.loading" text="loading" textWrap="true" />
<StackLayout v-else>
<Label :text="bird.name" textWrap="true" />
<Button text="get data" #tap="getData" />
</StackLayout>

Accessing element within a component

I'm trying to access the root element a component with this.$children.$el, however, I'm getting undefined in the console. I can see the $el property on the object when I console.log(this.$children), so I'm not quite sure where I'm going wrong, any help would be greatly appreciated.
<template>
<div>
<Project
v-for="project in projects"
:key="project.sys.id"
:title="project.fields.title"
:images="project.fields.images"
/>
</div>
</template>
<script>
import Project from '~/components/Project'
export default {
mounted() {
const projects = this.$children.$el
},
components: {
Project
}
}
</script>
As stated in the vue.js documentation this.$children returns an array of children components. You could see your child component by printing this.$children[0] and its root element by priting this.$children[0].$el.
If you have many children components and want to target a specific one, you can tag your component with a ref attribute like below :
<template>
<div>
<Project
v-for="project in projects"
:key="project.sys.id"
:title="project.fields.title"
:images="project.fields.images"
ref="project"
/>
</div>
</template>
<script>
import Project from '~/components/Project'
export default {
mounted() {
console.log(this.$refs.project)
},
components: {
Project
}
}
</script>

How to use Onsen UI tabbar with Vue single file components

I'm using Vue Onsen UI and trying to render a Vue single file component for each tab.
In the documentation here, they make use of template in a single page. Which is not very reusable. I want to be able to import custom component and render that.
Here is something that I'm trying to do which doesn't seem to work.
<template lang="html">
<v-ons-page>
<!-- top tab bar -->
<v-ons-tabbar position="top" :index="0">
<v-ons-tab label="Browse" page="TaskList">
</v-ons-tab>
<v-ons-tab label="Second">
</v-ons-tab>
</v-ons-tabbar>
</v-ons-page>
</template>
<script>
import TaskList from './TaskList';
export default {
template: '#main',
components: {
'task-list': TaskList,
},
};
</script>
<style lang="scss">
</style>
Can you suggest anything that I should try?
Instead of using tab objects that reference the components directly, use the :tabs property of the tabbar to set up the pages:
<template lang="html">
<v-ons-page>
<v-ons-tabbar position="top" :index="0" :tabs="tabs">
</v-ons-tabbar>
</v-ons-page>
</template>
<script>
import TaskList from './TaskList';
import SecondPage from './SecondPage';
export default {
template: '#main',
data: function () {
return {
tabs: [
{label: 'Browse', page: TaskList},
{label: 'Second', page: SecondPage}
]
}
}
};
</script>
Also, make sure the root element of the components you reference in the page property are <v-ons-page> elements.
I was having the same difficulty with the following syptoms:
Tabs were not appearing at all
No errors in CLI or in console
Note that I was also using the "Hello World" app that is generated from the CLI (vue init OnsenUI/vue-pwa-webpack hello-world)
Resolution
It was pretty simple in the end: there is a file in the root of the folder called vue-onsen-components.js which has all of the components and some of them are commented out. I had to uncomment the following lines and then the tabs appeared:
export { default as VOnsTab } from 'vue-onsenui/esm/components/VOnsTab'
export { default as VOnsTabbar } from 'vue-onsenui/esm/components/VOnsTabbar'

VueJS Unknown custom element with nested template in single file components

I have a nested structure with vue:
<app>
<column> : [array]
<task> : [array]
<resource> : [array]
I'm also using single file components.
For <app> component it looks like this (/App.vue file)
<template>
<div id="app">
<column v-for=""></column>
</div>
</template>
<script>
import column from './components/Column'
export default {
name: 'project',
components: {
column
},
data () {
return {
}
}
}
</script>
The <column> component (/components/Column.vue file):
<template>
<div>
<task v-for=""></task>
</div>
</template>
<script>
import task from './Task'
export default {
name: 'column',
components: {
task
},
data () {
return {
}
}
}
</script>
The <task> component (/components/Task.vue file):
<template>
<div>
<resources></resources>
</div>
</template>
<script>
import { resources } from './Init-resource'
export default {
name: 'task',
components: {
resources
},
data () {
return {
}
}
}
</script>
Up until this point everything works flawlessly. The app renders a bunch of columns, and inside the columns it renders tasks.
But then comes another layer <resource>, that looks like this (/components/Init-resource.vue file):
<template>
<div>
<select>
<option v-for=""></option>
</select>
</div>
</template>
<script>
export default {
name: 'resources',
data () {
return {
}
}
}
</script>
I get this error:
vue.common.js?e881:509 [Vue warn]: Unknown custom element: <resources> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
(found in component <task>
It doesn't recognize the last <resource> component. But everything looks fine, imports are correct, components are returned for the template...
I found it. I used named import, so instead of this:
import { resources } from './Init-resource'
it should be this:
import resources from './Init-resource'