Tag.vue
<template>
<div class="tag">
Tag: {{ tag }}<br>
<div v-if="error">{{ error }}</div>
# {{ posts.length }}<br>
# {{ computedFilteredList.length }}<br>
<br>
============# {{ computedFilteredList.length }} computedFilteredList=================
<div v-if="computedFilteredList.length">
<PostList :posts="computedFilteredList"/>
</div>
<div v-else><Spinner/></div>
</div>
</template>
<script>
import getPosts from "@/composables/getPosts";
import PostList from "@/components/PostList.vue";
import Spinner from "@/composables/Spinner.vue";
import {computed, ref} from "vue";
import {useRoute} from "vue-router";
export default {
components: { Spinner, PostList },
props: ['tag'],
setup(){
const { posts, error, load } = getPosts()
load()
const route = useRoute()
console.log(posts.value.length)
const computedFilteredList = computed(() => {
return posts.value.filter((post) => {
console.log(post)
post.tags.includes(route.params.tag)
})
})
return { posts, error, computedFilteredList }
}
}
</script>
<style>
</style>
PostList.vue
<template>
<div class="post-list">
<div v-for="post in posts" :key="post.id">
<SinglePost :post="post"/>
</div>
</div>
</template>
<script>
import SinglePost from "@/components/SinglePost.vue";
import {computed, onMounted, onUnmounted, onUpdated} from "vue";
export default {
components: { SinglePost },
props: ['posts'],
}
</script>
<style>
</style>
getPost.js
import {ref} from "vue";
const getPosts = () => {
const posts = ref([])
const error = ref(null)
const load = async () => {
try{
// simulate delay
// await new Promise(resolve => {
// setTimeout(resolve, 2000)
// })
let data = await fetch('http://localhost:3000/posts')
if(!data.ok){
throw Error('no data available')
}
posts.value = await data.json()
}
catch(err){
error.value = err.message
console.log(error.value)
}
}
return { posts, error, load }
}
export default getPosts
db.json
{
"posts": [
{
"id": 1,
"title": "welcome to the new blog",
"body": "rolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsum",
"tags": [
"webdev",
"coding",
"news"
]
},
{
"id": 2,
"title": "top 5 CSS tips",
"body": "rolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsum",
"tags": [
"css",
"webdev",
"coding"
]
},
{
"title": "test",
"body": "test",
"tags": [
"rtet"
],
"id": 3
},
{
"title": "afdsa",
"body": "asfads",
"tags": [
"fddsf",
"asdf"
],
"id": 4
}
]
}
Update:
When I try create project with > npm create vue@latest
I got new problem.
Uncaught ReferenceError: Cannot access 'PostList' before initialization at Tag.vue:26:26
Warning: Failed to resolve component: PostList If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.
Problem: Computed property has no result.
Question: Where am I wrong. I got this code from Udemy class. Some of the student got the same question 2 years ago and no one answer to them.
Array.filter callback function should return a true/false value. This boolean tells the filter whether or not to include the object in the resulting filtered array. If you don't return a boolean, the filter won't do any filtering at all. In summary, add a return statement to your filter:
const computedFilteredList = computed(() => {
return posts.value.filter(post => {
console.log(post)
return post.tags.includes(route.params.tag) // return this result
})
})
If you can write your filter function as one line, without function braces {}
, the return value can be implied. This would involve removing the console log:
const computedFilteredList = computed(() => {
return posts.value.filter(post => post.tags.includes(route.params.tag))
})