I am learning the Vue 3 composition API and I did a simple post list (simply creating an array of post in the setup() with tags for each posts) as below first code section. Then I have a component PostList to display those posts and a TagCloud to show all the existing tags. I am trying to filter the posts by clicking on a tag.
- I managed to emit the tag from the component TagCloud
- I try to filter filter my list of posts (tils) with a computed but... it doesn't work
Below are the 3 elements working together, can anyone spot what's wrong?
The main view
<template>
<div class="home">
<h1>Today I learned (TIL)</h1>
<div class="layout">
<TagCloud :tils="tils" @tag="filterTils" />
<PostList :tils="filterTils" />
</div>
</div>
</template>
<script>
import PostList from "../components/PostList.vue";
import TagCloud from "../components/TagCloud.vue";
import { ref, computed } from "vue";
export default {
name: "Til",
components: { PostList, TagCloud },
setup() {
const tils = ref([
{
title: "Symbol#to_proc conversion",
description: "map(&:to_i) is exactly the same as map { |x| x.to_i }",
tags: ["ruby"],
},
{
title: "Symbol#to_proc conversion",
description:
"Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum ",
tags: ["lorem"],
},
{
title: "Symbol#to_proc conversion",
description: "map(&:to_i) is exactly the same as map { |x| x.to_i }",
tags: ["ruby"],
},
]);
const filterTils = computed((tag) => {
return tils.value.filter((til) => til.tags.includes(tag));
});
return { tils, filterTils };
}
};
</script>
The tag cloud component
<template>
<div class="tag-cloud">
<h3>Tags</h3>
<div v-for="tag in tags" :key="tag">
<div @click="filterTag(tag)" class="uniq-tag">#{{ tag }}</div>
</div>
</div>
</template>
<script>
import useTags from "../composables/useTags";
export default {
props: ["tils"],
setup(props, context) {
const { tags } = useTags(props.tils);
const filterTag = (tag) => {
context.emit("tag", tag);
};
return { tags, filterTag };
},
};
</script>
the post list component
<template>
<div class="til-list">
<div v-for="til in tils" :key="til">
<div class="til">
<h3>{{ til.title }}</h3>
<p>{{ til.description }}</p>
<span v-for="tag in til.tags" :key="tag"> #{{ tag }} </span>
</div>
</div>
</div>
</template>
<script>
export default {
props: ["tils"],
};
</script>