I am implementing Vue.js dynamic ponents but I can't seem to figure out how to show the ponent only when it has fetched it's data. Until then it should show the old ponent.
The scenario is this. When the page is loaded it should show the Home ponent. Then I click on "Show posts". Nothing should happen until the Posts ponent has fetched it's posts. Then it should show the Posts ponent. I don't want any loading to show.
I could fetch posts in my Home poent but I think the Posts ponent should be responsible for that. Also if I have many ponents I don't want to fetch all their data in my Home ponent. They should fetch their own data (I think). Is this possible to do?
home.js
import Home from './home.js'
import Posts from './posts.js'
export default {
template: `
<div>
<a @click="showPosts">Show posts</a>
<ponent :is="currentComponent" />
</div>
`,
methods:
{
showPosts()
{
// Do this ONLY after the Posts ponent has fetched it's data... not immediately...
this.currentComponent = Posts
}
},
data:
{
currentComponent: Home
},
}
posts.js
export default {
template: `
<div>
<div v-for="post in posts">{{ post.body }}</div>
</div>
`,
data:
{
posts: [],
},
created()
{
axios.get('/posts').then(({ data } => {
this.posts = data
})
},
}
I am implementing Vue.js dynamic ponents but I can't seem to figure out how to show the ponent only when it has fetched it's data. Until then it should show the old ponent.
The scenario is this. When the page is loaded it should show the Home ponent. Then I click on "Show posts". Nothing should happen until the Posts ponent has fetched it's posts. Then it should show the Posts ponent. I don't want any loading to show.
I could fetch posts in my Home poent but I think the Posts ponent should be responsible for that. Also if I have many ponents I don't want to fetch all their data in my Home ponent. They should fetch their own data (I think). Is this possible to do?
home.js
import Home from './home.js'
import Posts from './posts.js'
export default {
template: `
<div>
<a @click="showPosts">Show posts</a>
<ponent :is="currentComponent" />
</div>
`,
methods:
{
showPosts()
{
// Do this ONLY after the Posts ponent has fetched it's data... not immediately...
this.currentComponent = Posts
}
},
data:
{
currentComponent: Home
},
}
posts.js
export default {
template: `
<div>
<div v-for="post in posts">{{ post.body }}</div>
</div>
`,
data:
{
posts: [],
},
created()
{
axios.get('/posts').then(({ data } => {
this.posts = data
})
},
}
Share
Improve this question
edited Sep 6, 2019 at 9:03
oshell
9,1231 gold badge30 silver badges50 bronze badges
asked Sep 6, 2019 at 7:23
LigaLiga
3,4396 gold badges38 silver badges67 bronze badges
2 Answers
Reset to default 2You can use the async created
hook in bination with a v-if
statement.
So you basically wrap your template in a v-if
template: '<div v-if="dataloaded">This is ponent xlr</div>
Inside the async created you load your data and set the flag to true once it is finished
async created() {
await loadData(3000);
this.dataloaded = true;},
See a working fiddle here: https://jsfiddle/Postlagerkarte/yomb5qv6/
If you want to show posts ponent only when posts are fetched, the only way is to fetch data in the parent ponent. To do this you normally decouple the fetching from the ponent. You have something like a apiService
, which fetches posts and the Posts
ponent really is only the view and its only purpose is displaying data. This way your code also bees much more re-usable, since many api requests probably share a lot of logic.
Here is how your ponent could look like:
home.js
import Home from './home.js'
import Posts from './posts.js'
import apiService from '../services/apiService.js'
export default {
template: `
<div>
<a @click="showPosts">Show posts</a>
<ponent :posts="posts" :is="currentComponent" />
</div>
`,
methods:
{
showPosts()
{
apiService.fetchPosts().then((response) => {
this.posts = response.data.posts
this.currentComponent = Posts
});
}
},
data:
{
posts: []
currentComponent: Home
},
}