Reputation: 1114
I am trying to filter an Array that contains nested array of Objects. I would like for the v-for to only show those objects that meet certain condition. I have created a JSfiddle Click Here
The part that confuses me is that each enagagement could have 1 object or 3 objects, and I don't know how to check value conditions for each nested object.
I want to only show Engagements with questions that are not answered. I am using a boolean value to represent whether the question is answered or not.
This is the v-for
<div id="app">
<h2>Engagements:</h2>
<div>
<div v-for="(engagment, index) in filteredQuestions" :key="index">
<li v-for="question in engagment.questions" :key="question.id">
<span>{{ question.id }},</span>
<span> {{ question.question}} </span>
<span><input type="checkbox" v-model="question.answered"></span>
</li>
</div>
</div>
</div>
This is the Script and Data
new Vue({
el: "#app",
data: {
engagements: [
{
id: 1,
text: "1040",
questions: [
{
id: 1,
question: 'this is a question',
answered: 0
},
{
id: 2,
question: 'this is a question',
answered: 1
},
]
},
{
id: 2,
text: "1040",
questions: [
{
id: 3,
question: 'this is a question',
answered: 0
},
]
},
]
},
computed: {
filteredQuestions() {
const engagement = this.engagements.filter((engagement) => {
return engagement.questions.filter((question) => question.answered === 0)
})
return engagement
}
}
})
Currently no matter how I format the filteredQuestions
method it will either render the entire list or show nothing. Please view the jsfiddle I included at the top of this post!
Upvotes: 3
Views: 4004
Reputation: 438
The above option not work if you are trying to find the first level's array and nested item in array
For example engagements's name and questions sub item name because the filter will do the last match
If you are trying to find matches on nested array for example on names should do the next code
return this.content.filter((sub) => {
//for save the status
let show = false
//find in nested: themes
sub.Themes = sub.Themes.filter((theme) => {
if (reg.test(theme.name)) {
show = true
return true
}
return false
})
//if was finded match in themes show the subject or if the subject name match too
if (show === true || reg.test(sub.name)) {
return true
}
return false
})
Upvotes: 0
Reputation: 2988
You're filtering the engagements
based on them having 1 or more unanswered questions, but the v-for
is still rendering all questions inside those engagements.
WRONG: Add v-if="question.answered==0"
to the <li>
element to only show unanswered questions. (This is wrong practice, I found out: see lint error here. You should not use v-if
and v-for
on the same element.)
CORRECT:
In this case extend your filteredQuestions
computed value function to only return questions
without answers. (Now you are just filtering the engagements based on that, but still returning all of the questions.)
Your computed value function could be:
filteredQuestions() {
return this.engagements
// Return a modified copy of engagements..
.map((engagement) => {
// ..with all answered questions filtered out..
engagement.questions = engagement.questions.filter((question) => question.answered === 0);
return engagement;
})
// ..and only return engagements that have (unanswered) questions left
.filter((engagement) => engagement.questions.length !== 0);
}
Upvotes: 6