I'm having this list of blogposts called articles
that I call from the content folder.
async asyncData ({ $content }) {
const articles = await $content('', { deep: true })
// .where({ cat: 'A' })
.only(['title', 'description', 'img', 'slug', 'cat'])
.sortBy('createdAt', 'asc')
.fetch()
return { articles }
}
This fetches all of my articles and returns a list of them.
Now, I would like to populate my different categories in my website following this structure :
<template>
<div >
<div v-for="article in articles" :key="article">
{{ article.title }}
</div>
<pre> {{ articles }}</pre>
<div v-for="accordion in accordions" :key="accordion.title" >
<Item>
<template #title>
{{ accordion.title }}
</template>
<template #content>
<div> {{ accordion.text }}</div>
</template>
</Item>
</div>
<!-- here goes R -->
<div />
</div>
</template>
<script>
import Item from '../components/List-item.vue'
export default {
components: { Item },
async asyncData ({ $content }) {
const articles = await $content('', { deep: true })
// .where({ cat: 'A' })
.only(['title', 'description', 'img', 'slug', 'cat'])
.sortBy('createdAt', 'asc')
.fetch()
return { articles }
},
data () {
return {
accordions: [
{
title: 'A',
text: 'Projects from content/A'
},
{
title: 'B',
text: 'Projects from content/B'
},
{
title: 'C',
text: 'Projects from content/C'
}
]
}
</script>
It's using slots from a componenent :
<template>
<div >
<div
:
@click="toggle"
>
<a >
<slot name="title" />
</a>
<div v-show="show" : >
<slot name="content" />
</div>
</div>
</div>
</template>
I've nested my array into a v-for, but I don't know how to dynamically group that array by URL or by category.
CodePudding user response:
If the intent is to see the list of articles queried in an accordion that divides them by "cat", you can augment the accordion data structure in data to include the articles found in the query...
async asyncData ({ $content }) {
const articles = await $content('', { deep: true })
.only(['title', 'description', 'img', 'slug', 'cat'])
.sortBy('createdAt', 'asc')
.fetch()
// set accordions as an array of grouped articles
const groups = articles.reduce((acc, article) => {
if (!acc[article.cat]) acc[article.cat] = {
title: article.cat,
text: `Articles about ${article.cat}`,
articles: [] // <-- gather the articles for this cat here
};
acc[article.cat].articles.push(article);
return acc;
}, {});
this.accordions = Object.values(groups);
}
The markup should iterate the accordion
in data (which are really categories), and then nest iteration of the articles in each category...
<div v-for="accordion in accordions" :key="accordion.title" >
<Item>
<template #title>
{{ accordion.title }}
</template>
<template #content>
<div> {{ accordion.text }}</div>
<ul>
<li v-for="(article, i) in accordion.articles" :key="i">
{{article.title}}
</li>
</ul>
</template>
</Item>
</div>
CodePudding user response:
This is how I would achieve that while keeping it fully dynamic and less error prone.
<template>
<div >
<div v-for="(filteredArticles, categoryKey) in groupedCategories" :key="categoryKey">
<h2>{{ categoryKey }}</h2>
<list-item v-for="article in filteredArticles" :key="article.slug">
<template #title>
{{ article.title }}
</template>
<template #content>
<div> {{ article.description }}</div>
</template>
<br>
</list-item>
<hr>
</div>
</div>
</template>
<script>
export default {
async asyncData ({ $content }) {
const articles = await $content('', { deep: true })
.only(['title', 'description', 'img', 'slug', 'cat', 'dir'])
.sortBy('createdAt', 'asc')
.fetch()
return { articles }
},
computed: {
groupedCategories () {
return this.articles.reduce((finalObject, obj) => {
const directory = obj.dir
finalObject[directory] ?? (finalObject[directory] = [])
finalObject[directory].push(obj)
return finalObject
}, {})
}
}
}
</script>
The .only(['dir'])
gives us all the directories aka /A
, /B
etc, so that it's fully dynamic and not relying on OP's needing to remember to put a cat
in the .md
file.
It is generated for any kind of content as
A github repo can be found here: https://github.com/kissu/AppPortfolio
Useful since it's a bit cumbersome to mock all kind of .md
files.
A deployed version can be found here: https://papaya-truffle-df823c.netlify.app/
CodePudding user response:
You can use conditional queries with @nuxt-content
module:
{
async asyncData ({ $content }) {
const articlesC = await $content('', { deep: true })
.where({ cat: { $contains: 'C' } })
// Or .where({ cat: { $eq: 'C' } })
.only(['title', 'description', 'img', 'slug', 'cat'])
.sortBy('createdAt', 'asc')
.fetch()
return { articles }
}
}
And the create an array for each category.
If you do not want to create a query for each category you can use the Array.filter
(or Array.reduce
) method to group your articles big query.