select all checkbox specific id - javascript

I am working on a menu permission project using vue.js. I have some submenus which are child of different menus. I want to select all submenus of selected menu if I click on "select All". this is the code I am trying--
// New VueJS instance
var app = new Vue({
el: "#app",
data: {
menus: [
{ id: 1, menuName: "Tech 1" },
{ id: 2, menuName: "Tech 2" },
{ id: 3, menuName: "Tech 3" }
],
selectedAllSubMenu:[],
selectedMenu: [],
selectedSubMenu: [],
submenus: [
{ id: 1, menuId: 1, subMenuName: "architecture" },
{ id: 2, menuId: 1, subMenuName: "Electrical" },
{ id: 3, menuId: 1, subMenuName: "Electronics" },
{ id: 4, menuId: 2, subMenuName: "IEM" },
{ id: 5, menuId: 3, subMenuName: "CIVIL" }
]
},
computed: {
isUserInPreviousUsers() {
return this.previousUsers.indexOf(this.userId) >= 0;
},
filteredProduct: function () {
const app = this,
menu = app.selectedMenu;
if (menu.includes("0")) {
return app.submenus;
} else {
return app.submenus.filter(function (item) {
return menu.indexOf(item.menuId) >= 0;
});
}
}
},
methods: {
selectAllSubMenu(event) {
for (let i = 0; i < this.submenus.length; i++) {
if (event.target.checked) {
if (this.submenus[i].menuId == event.target.value) {
this.selectedSubMenu.push(this.submenus[i].id);
}
} else {
if (this.submenus[i].menuId == event.target.value) {
var index = this.selectedSubMenu.indexOf(event.target.value);
this.selectedSubMenu.splice(index, 1);
}
}
}
},
}
});
<!-- Include the library in the page -->
<script src="https://unpkg.com/vue#2.2.0-beta.1/dist/vue.js"></script>
<!-- App -->
<div id="app">
<h4>Click on any menu. Then the submenus will appear. I want to select all submenus of selected menu if I click on "select All"</h4>
<table class="table">
<thead>
<tr>
<th>Menu</th>
<th>Submenu</th>
</tr>
</thead>
<tbody>
<tr v-for="(menu,index) in menus" :key="menu.id">
<td>
<label>
<input type="checkbox" :value="menu.id" v-model="selectedMenu" />{{ menu.menuName }}
</label>
</td>
<td v-if="selectedMenu.length != 0">
<ul>
<label >
<input
type="checkbox"
:value="menu.id"
v-model="selectedAllSubMenu"
#change="selectAllSubMenu"
/>
Select all
</label>
<li v-for="submenu in filteredProduct" :key="submenu.id" v-if="menu.id == submenu.menuId">
<input type="checkbox" :value="submenu.id" v-model="selectedSubMenu" />
<label>{{ submenu.subMenuName }} </label>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
Here are some menus. every menu has some submenus. Now if I click on any submenu & then click on select all, all the submenus get selected. But the problem is, If I uncheck "select all" the previously selected submenus still got selected. How Do I solve this?

Try like following snippet:
// New VueJS instance
var app = new Vue({
el: "#app",
data(){
return {
menus: [{ id: 1, menuName: "Tech 1" }, { id: 2, menuName: "Tech 2" }, { id: 3, menuName: "Tech 3" }],
selectedMenu: [],
selectedSubMenu: [],
selectedAllSubMenu: [],
submenus: [{ id: 1, menuId: 1, subMenuName: "architecture" }, { id: 2, menuId: 1, subMenuName: "Electrical" }, { id: 3, menuId: 1, subMenuName: "Electronics" }, { id: 4, menuId: 2, subMenuName: "IEM" }, { id: 5, menuId: 3, subMenuName: "CIVIL" }]
}
},
computed: {
isUserInPreviousUsers() {
return this.previousUsers.indexOf(this.userId) >= 0;
},
},
methods: {
filteredProduct (id) {
return this.submenus.filter(s => s.menuId === id)
},
selectSubMenu(id) {
if (this.selectedSubMenu.filter(s => s.menuId === id).length === this.submenus.filter(s => s.menuId === id).length) {
this.selectedAllSubMenu.push(id)
} else {
this.selectedAllSubMenu = this.selectedAllSubMenu.filter(s => s !== id)
}
},
selectAllSubMenu(id){
const checked = this.selectedAllSubMenu.some(s => s === id)
if (this.selectedSubMenu.filter(s => s.menuId === id).length === this.submenus.filter(s => s.menuId === id).length && !checked) {
this.selectedSubMenu = this.selectedSubMenu.filter(s => s.menuId !== id)
} else if (checked) {
this.selectedSubMenu = [... new Set([...this.selectedSubMenu].concat(this.submenus.filter(s => s.menuId === id)))]
}
},
}
});
<script src="https://unpkg.com/vue#2.2.0-beta.1/dist/vue.js"></script>
<div id="app">
<table class="table">
<thead>
<tr>
<th>Menu</th>
<th>Submenu</th>
</tr>
</thead>
<tbody>
<tr v-for="(menu,index) in menus" :key="menu.id">
<td>
<label>
<input type="checkbox" :value="menu" v-model="selectedMenu" />{{ menu.menuName }}
</label>
</td>
<td v-if="selectedMenu.filter(s => filteredProduct(menu.id).some(i => i.menuId === s.id)).length">
<ul >
<label >
<input
type="checkbox"
:value="menu.id"
v-model="selectedAllSubMenu"
#change="selectAllSubMenu(menu.id)"
/>
Select all
</label>
<li v-for="submenu in filteredProduct(menu.id)" :key="submenu.id">
<input type="checkbox" :value="submenu" v-model="selectedSubMenu" #change="selectSubMenu(menu.id)" />
<label>{{ submenu.subMenuName }} </label>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>

After spending an hour on this requirement to find the root cause, I am here with a solution :
In your selectAllSubMenu method, splicing of the elements was not working properly as it was not able to remove the duplicate values from an array. Hence, I just changed a approach a bit. I am filtering the selectedSubMenu based on submenu ids of the selected menu.
selectAllSubMenu(event) {
if (event.target.checked) {
for (let i = 0; i < this.submenus.length; i++) {
if (this.submenus[i].menuId == event.target.value) {
this.selectedSubMenu.push(this.submenus[i].id);
}
}
} else {
const filteredMenu = this.submenus.filter(obj => obj.menuId == event.target.value).map(({id}) => id);
this.selectedSubMenu = this.selectedSubMenu.filter(el => filteredMenu.indexOf(el) === -1);
}
}

Related

Filter nested v-for list

<div>
<q-card
v-for="box in boxes"
:key="box.id">
<q-item>
<q-item-section>
<span> {{ box.name }} </span>
</q-item-section>
</q-item>
<q-list>
<q-item
v-for="tool in box.tools"
:key="tool.id"
clickable
<q-item-section>
<span> {{ tool.name }} </span>
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
Form input filter value
inputFilterValue = "box A"
Filter boxes
Edited with return.
computed: {
boxes(){
return boxes.filter(box => {
return box.name.toLowerCase().match(inputFilterValue.toLowerCase())
});
}
}
This works
How to filter too nested v-for box-tools list?
EDITED:
CODEPEN: https://codepen.io/ijose/pen/NWyoRMX
You can use JavaScript filter() along with some() method. some() method checks if any of the elements in an array pass the function.
Demo :
new Vue({
el: '#app',
data: {
value: null,
boxes: [],
dataObj: [{
id: 1,
name: 'Box A',
tools: [{
id: 1,
name: 'Tool A'
}, {
id: 2,
name: 'Tool D2'
}]
}, {
id: 2,
name: 'Box B',
tools: [{
id: 1,
name: 'Tool B'
}]
}, {
id: 3,
name: 'Box C',
tools: [{
id: 1,
name: 'Tool C'
}]
}]
},
mounted() {
this.boxes = structuredClone(this.dataObj);
},
methods: {
inputFilterValue(filterField) {
if (filterField === 'box') {
this.boxes = this.dataObj.filter(box => box.name.toLowerCase().match(this.value.toLowerCase()))
} else {
const filteredToolsArr = this.dataObj.map(box => {
const filteredTool = box.tools.filter((
{ name }) => name.toLowerCase().match(this.value.toLowerCase()));
return { ...box, tools: filteredTool }
})
this.boxes = filteredToolsArr.filter(obj => obj.tools.length);
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
Filter : <input type="text" v-model="value" #keyup="inputFilterValue('tool')"/>
<ul v-for="box in boxes" :key="box.id">
<li>{{ box.name }}</li>
<ul v-for="tool in box.tools" :key="tool.id">
<li>{{ tool.name }}</li>
</ul>
</ul>
</div>
In the filter callback of boxes add a condition if the tool name matches the inputFilterValue
computed: {
boxes(){
return boxes.filter(box => {
return box.name.toLowerCase().match(inputFilterValue.toLowerCase()) ||
box.tools.filter(tool=>tool.name.toLowerCase().match(inputFilterValue.toLowerCase())
});
}
}

Vue Survey not indexing questions

I have to build a quiz/survey app in vue.js, I'm pretty new to vue and still trying to learn it. I have a quiz/survey that asks different questions depending on what the user answers in the initial question.
so if the user picks yes it will display question 2 if the user picks no it will display question 3 etc.
I'm not sure what the best way of going around it but so far I have this.
Is there anyway i can use the value of my answer as the questionIndex after a person clicks next?
JS file:
"use strict";
let quiz = {
title: "Asbestos Quiz",
questions: [
{
text: 'Do you need help with an Asbestos Survey?',
answers: [
{
text: "Yes",
value: '2'`enter code here`
},
{
text: "No",
value: '3'
},
]
},
{
text: 'Was your property constructed pre 2000',
answers: [
{
text: "Yes",
value: '4'
},
{
text: "No",
value: '5'
},
]
},
{
text: 'Do you need an Asbestos Management plan?',
answers: [
{
text: "Yes",
value: '6'
},
{
text: "No",
value: '7'
},
]
}
]
};
var app = new Vue({
el: "#app",
data: {
quiz: quiz,
questionIndex: 0,
responses: [],
errors: [],
error: ''
},
methods: {
prev: function() {
this.questionIndex--;
},
next: function() {
if (this.responses[this.questionIndex] === undefined) {
this.errors[this.questionIndex] = 1;
this.error = 'Please select your answer';
}
else {
this.errors[this.questionIndex] = 0;
this.questionIndex++;
}
},
score: function() {
},
playAgain: function() {
this.questionIndex = 0;
}
}
});
HTML:
<html lang="en">
<head>
<title>Vue quiz/survey</title>
<meta name="viewport" content="width=device-width"/>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- <link rel="stylesheet" href="index.css"> -->
</head>
<body>
<div id="app">
<div class="container">
<div class="jumbotron mt-3">
<h1 class="mb-5">{{ quiz.title }}</h1>
<hr>
<p v-if="errors[questionIndex]" class="alert alert-danger">
{{ error }}
</p>
<div v-for="(question, index) in quiz.questions">
<div v-show="index === questionIndex">
<h4 class="mt-5 mb-3">{{ question.text }}</h4>
<div v-for="answer in question.answers" class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio"
:value="answer.value"
:name="index"
v-model="responses[index]">
{{answer.text}}
</label>
</div>
<div class="mt-5">
<button
class="btn btn-primary"
v-if="questionIndex > 0"
#click="prev">
prev
</button>
<button class="btn btn-secondary" #click="next">
next
</button>
</div>
</div>
</div>
<div v-show="questionIndex === quiz.questions.length">
<h3>Your Results</h3>
<p>
You are: {{ score() }}
</p>
<button class="btn btn-success" #click="playAgain">
Play Again!
</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
I thought that this sounded like a potentially interesting exercise, so I spent some time creating an implementation in a Vue CLI sandbox app that I built and use for trying out various ideas.
I learned a few things, and hopefully you will get something out of it. I left the 'Previous' functionality as a TODO if you decide you like it and want implement that yourself.
QuizQuestions.vue
<template>
<div class="quiz-questions">
<div class="jumbotron mt-3">
<h1 class="mb-5">{{ quiz.title }}</h1>
<hr>
<question v-if="!showResults" :question="currentQuestion" #answer-selected="processAnswer" />
<div class="mt-5">
<button class="btn btn-primary" v-if="currentQuestionId > 1 && !showResults" #click="getPreviousQuestion">
prev
</button>
<button v-if="!showResults" class="btn btn-secondary" #click="getNextQuestion">
{{ nextButtonLabel }}
</button>
</div>
<div v-if="showResults">
<h3>Your Results</h3>
<table class="table table-bordered">
<thead>
<tr>
<th>QUESTION</th>
<th>ANSWER</th>
</tr>
</thead>
<tbody>
<tr v-for="(response, index) in responses" :key="index">
<td>{{ getQuestionText(response.questionId) }}</td>
<td>{{ getAnswerText(response.answerId) }}</td>
</tr>
</tbody>
</table>
<button class="btn btn-success" #click="playAgain">
Play Again!
</button>
</div>
</div>
</div>
</template>
<script>
import quiz from './quiz.js';
import Question from '#/components/stackoverflow/Question'
export default {
components: {
Question
},
data() {
return {
quiz: quiz,
currentQuestionId: 1,
currentAnswerId: 1,
previousQuestionId: 0,
responses: [],
showResults: false,
errors: [],
error: ''
}
},
computed: {
currentQuestion() {
return this.quiz.questions.find( question => {
return question.id === this.currentQuestionId;
})
},
nextQuestionId() {
let retVal = 0;
if (this.currentAnswerId > 0) {
let tempAnswer = this.currentQuestion.answers.find( answer => {
return answer.id === this.currentAnswerId;
});
retVal = tempAnswer.nextQuestionId;
}
return retVal;
},
lastQuestion() {
return this.currentQuestion.answers[0].nextQuestionId === 0;
},
nextButtonLabel() {
return this.lastQuestion ? 'Finish' : 'Next';
}
},
methods: {
getPreviousQuestion() {
this.currentQuestionId = this.previousQuestionId;
},
getNextQuestion() {
// TODO: Look for existing response for this question in case the 'Previous' button was pressed
// If found, update answer
// Store current question id and answer id in responses
let response = { questionId: this.currentQuestionId, answerId: this.currentAnswerId };
this.responses.push(response);
if (this.lastQuestion) {
this.showResults = true;
return;
}
this.previousQuestionId = this.currentQuestionId;
this.currentQuestionId = this.nextQuestionId;
//console.log(this.responses);
},
getQuestionText(id) {
let result = this.quiz.questions.find( question => {
return question.id === id;
});
return result.text;
},
getAnswerText(id) {
// NOTE: Since answers are currently limited to '1 = Yes' and '2 = No',
// this method does not need to involve any look up
return id === 1 ? 'Yes' : 'No';
},
processAnswer(selectedAnswerId) {
this.currentAnswerId = selectedAnswerId;
},
score() {
return 'TODO'
},
playAgain() {
this.currentQuestionId = 1;
this.showResults = false;
this.responses = [];
}
}
}
</script>
Question.vue
<template>
<div class="question">
<h4 class="mt-5 mb-3">{{ question.text }}</h4>
<div class="form-check" v-for="(answer, idx) in question.answers" :key="idx">
<input class="form-check-input" type="radio"
:value="answer.id" v-model="answerId" #change="answerSelected">
<label class="form-check-label">
{{answer.text}}
</label>
</div>
</div>
</template>
<script>
export default {
props: {
question: {
type: Object,
required: true
}
},
data() {
return {
answerId: 1
}
},
watch:{
question() {
// Reset on new question
this.answerId = 1;
}
},
methods: {
answerSelected() {
this.$emit('answer-selected', this.answerId);
}
}
}
</script>
I also modified your test data by adding various ID properties to help with tracking, as well as created a few more placeholder questions.
quiz.js
const quiz = {
title: "Asbestos Quiz",
questions: [
{
id: 1,
text: 'Do you need help with an Asbestos Survey?',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 2
},
{
id: 2,
text: "No",
nextQuestionId: 3
},
]
},
{
id: 2,
text: 'Was your property constructed pre 2000',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 4
},
{
id: 2,
text: "No",
nextQuestionId: 5
},
]
},
{
id: 3,
text: 'Do you need an Asbestos Management plan?',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 6
},
{
id: 2,
text: "No",
nextQuestionId: 7
},
]
},
{
id: 4,
text: 'Question 4',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 0
},
{
id: 2,
text: "No",
nextQuestionId: 0
},
]
},
{
id: 5,
text: 'Question 5',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 0
},
{
id: 2,
text: "No",
nextQuestionId: 0
},
]
},
{
id: 6,
text: 'Question 6',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 0
},
{
id: 2,
text: "No",
nextQuestionId: 0
},
]
},
{
id: 7,
text: 'Question 7',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 0
},
{
id: 2,
text: "No",
nextQuestionId: 0
},
]
}
]
};
export default quiz;

Filling a model with a list from Textarea

Now I do not really understand you. Sorry, I just started this whole study not so long ago. I’ll try to explain again what I can’t do.
I have an empty object and an object with data with the same structure.
data: [
{id: 1, title: "title1"},
{id: 2, title: "title1"},
{id: 3, title: "title3"},
{id: 4, title: "title4"},
{id: 5, title: "title3"}
],
item: [
{
itemId: "",
itemname: ""
}
]
And I have select and textarear. Select have data, textarear empty. Textarear displays title.
I want to press a button. Selected item from select. copied to textarear (title only), and also itemId - this selected element id: 5 and itemname - the same title: "title3" element, was recorded in item [].
https://codesandbox.io/s/priceless-hermann-g9flw
Please do check now
import React from "react";
class App extends React.Component {
constructor() {
super();
this.state = {
id: null,
title: "",
filmItem: "",
listFilms: [],
data: [
{ id: 1, title: "title1" },
{ id: 2, title: "title2" },
{ id: 3, title: "title3" },
{ id: 4, title: "title4" }
],
item: []
};
this.onChange = this.onChange.bind(this);
this.onChangeArea = this.onChangeArea.bind(this);
this.addFilm = this.addFilm.bind(this);
this.choice = this.choice.bind(this);
}
addFilm(film) {
const selectedData = this.state.data.find(item => item.id == film);
console.log(selectedData);
this.setState({
listFilms: [...this.state.listFilms, selectedData.title],
item: [
...this.state.item,
{ itemId: selectedData.id, itemname: selectedData.title }
]
});
}
onChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
onChangeArea = e => {
this.setState({ [e.target.name]: e.target.value.split("\n") });
};
choice(title) {
this.setState({ filmItem: title });
}
render() {
return (
<div className="App">
<div className="row App-main">
<div>
<select name="filmItem" size="4" onChange={e => this.onChange(e)}>
{this.state.data.map(film => (
<option key={film.title} value={film.id}>
{film.title}
</option>
))}
</select>
</div>
<div>
<button
className="editButton"
onClick={() => this.addFilm(this.state.filmItem)}
>
button
</button>
</div>
<div>
<textarea
name="films"
onChange={this.onChangeArea}
value={this.state.listFilms.map(r => r).join("\n")}
/>
</div>
<div>
<input type="text" name="text-input" onChange={this.onChange} />
</div>
</div>
<pre style={{ whiteSpace: "pre-wrap" }}>
{JSON.stringify(this.state)}
</pre>
</div>
);
}
}
export default App;

VueJS How to filter array data when using dropdown select

In my vue-app I have an array of job-postings, which have different states, such as "active", "rejected", "draft", "not_active" etc. Now I have a TabMenu: All Jobs, Drafts and To Be Approved. Each of those MenuTabs, have their own Dropdown menu, where you are supposed to filter the jobpostings. I've realized that this feature is more complex than expected, or maybe I have spend too much time with the issues, but for some reason, I cannot manage, to show "all" for the individual MenuTab. For example, when I click on the "To Be Approved" MenuTab, I want to see all the jobpostings, with the status "Not approved" and "Rejected" (See data below in the code).
So my question is, how to solve this properly? Does the job-posting data object need to have a category too?
Any help is most welcome!
So, here is my component:
<template>
<div>
<div class="tabs">
<ul>
<li v-for="(tab, index) in menuTabs” :key="tab.id" :class="{ 'active': activeTab === index }"
#click="toggleList(tab, index)” >
<span>{{tab.label}}</span>
</li>
</ul>
</div>
<div class="dropdown has-prepend col-8" :class="{ active: isOpen }">
<div :class="{ active: isOpen }" class="dropdown-select" #click="toggle">
{{ selectedOption }}
<i class="icon-chevron_down" />
</div>
<div class="dropdown-options" v-show="isOpen">
<div class="option" v-for="tab in dropDownTabs" #click="select(tab)" :key="tab.id">
<span>{{ tab.status }}</span>
</div>
</div>
</div>
<div class="block">
<DataTable :data="filteredData" :columns="tableColumns" :filter="search" />
</div>
</div>
</template>
import DataTable from '../../snippets/DataTable';
export default {
components: { DataTable },
data() {
return {
isOpen: false,
search: "",
tableData: [
{
id: 1,
title: "Salesperson",
publish_date: "2019-07-10",
status: "active",
applicants: 23,
expiration_date: "2020-02-21"
},
{
id: 2,
title: "Developer",
publish_date: "2019-11-12",
status: "not_active",
applicants: 111,
expiration_date: "2020-02-21"
},
{
id: 3,
title: "Freelanceer",
publish_date: "2019-06-10",
status: "need_approval",
applicants: 222,
expiration_date: "2020-01-10"
},
{
id: 4,
title: "Construction worker",
publish_date: "2019-12-06",
status: "active",
applicants: 76,
expiration_date: "2020-03-15"
},
{
id: 5,
title: "IT support”
publish_date: "2019-11-20",
status: "draft",
applicants: 103,
expiration_date: "2020-04-31"
},
],
menuTabs: [
{
label: "All jobs",
options: [
{
status: "all",
},
{
status: "active",
},
{
status: "not_active"
}
]
},
{
label: "Drafts",
options: [
{
status: "all"
},
{
status: "draft"
}
]
},
{
label: "To Be Approved",
options: [
{
status: "all",
},
{
status: "need_approval",
},
{
status: "rejected"
}
]
},
],
dropDownTabs: [],
selectedOption: "",
selectedTabCategory: "",
category: "",
activeTab: "",
tableColumns: [
"id",
"title",
"publish_date",
"status",
"applicants",
"expiration_date"
]
}
},
computed: {
filteredData() {
let status = this.selectedOption;
let category = this.category;
let filtered = this.tableData.filter(data => {
if (status == "all") {
return data;
}
return data.status === status;
});
return filtered;
}
},
methods: {
toggleList(tab, index) {
this.category = tab.options[0].category;
this.selectedTabCategory = tab;
let currentTabOptions = this.selectedTabCategory.options;
this.clearDropDown();
this.selectedOption = currentTabOptions[0].status;
currentTabOptions.forEach(option => {
this.dropDownTabs.push(option);
});
this.activeTab = index;
},
toggle() {
this.isOpen = !this.isOpen;
},
select(tab) {
this.selectedOption = tab.status;
let category = tab.category;
let filtered = this.tableData.filter(data => {
return data.status === this.selectedOption;
});
this.isOpen = false;
return filtered;
},
clearDropDown() {
this.dropDownTabs = [];
}
},
created() {},
mounted() {
this.selectedOption = this.menuTabs[0].options[0].status;
this.selectedTabCategory = this.menuTabs[0].label;
this.category = this.menuTabs[0].options[0].category;
let defaultOptions = this.menuTabs[0].options;
defaultOptions.forEach(option => {
this.dropDownTabs.push(option);
});
this.activeTab = 0;
}
};
I am not sure if it will help you at all. However I will try anyway.
You should store the selected tab when you click on it. Then filter the this.tableData based on the selected tab options. Also you will need map the tab option options to array of strings, so you can check if the posting status is in there.
methods: {
toggleList (tab, index) {
this.selectedTabObject = tab
// rest of your code...
}
},
computed: {
filteredData () {
return this.tableData.filter(data => {
const states = this.selectedTabObject.options.map(opt => opt.status)
return states.includes(data.status)
})
}
}
Also I have created simple fiddle to mimic your problem.
https://jsfiddle.net/3hqnp7u2/7/

How to search filter in vue.js based on id

I am making a Vue project. It contains a div and it loops title and
data. Inside div there is a search filter and content which renders in p tags. The p tags also
loops.
Here is the code:
<div>
<div v-for="(item) in data" :key="item.id">
<div>{{item.title}}</div>
<input type="text" v-model="search" />
<div v-for="(content, j) in filteredLists" :key="j">
<p v-for="(con, k) in content" :key="k">{{con}}</p>
</div>
</div>
</div>
here is the data
search: "",
data: [
{
id: 1,
title: "Devsrc",
content: {
id: 1,
details: ["ONE_DEV_EMP1", "ONE_DEV_EMP2"]
}
},
{
id: 2,
title: "Devsrc2",
content: {
id: 2,
details: ["TWO_DEV_EMP1", "TWO_DEV_EMP2"]
}
},
{
id: 3,
title: "Devsrc3",
content: {
id: 3,
details: ["THREE_DEV_EMP1", "THREE_DEV_EMP2"]
}
}
]
computed property
filteredLists() {
return this.data.map(item => {
return item.content.details.filter(detail => {
return detail.toLowerCase().match(this.search);
})
});
},
What I am trying to do is render details only for item id == content
id.
Make filteredLists() a method instead of computed for starters.
<div>
<div v-for="(item) in data" :key="item.id">
<div>{{item.title}}</div>
<input type="text" v-model="search" />
<div v-for="(content, j) in filteredLists(item.id)" :key="j">
<p v-for="(con, k) in content" :key="k">{{con}}</p>
</div>
</div>
</div>
function filteredLists(id) {
let term = this.search.trim().toUpperCase();
let scoped = this.data.filter(item => { return parseInt(item.content.id) === parseInt(id) });
if(term.length > 0) {
return scoped.filter(item => {
return item.content.details.find(seek => seek.match(search));
});
}
return scoped;
}
let search = 'EMP2';
let data = [{
id: 1,
title: "Devsrc",
content: {
id: 1,
details: ["ONE_DEV_EMP1", "ONE_DEV_EMP2"]
}
},
{
id: 2,
title: "Devsrc2",
content: {
id: 2,
details: ["TWO_DEV_EMP1", "TWO_DEV_EMP2"]
}
},
{
id: 3,
title: "Devsrc3",
content: {
id: 3,
details: ["THREE_DEV_EMP1", "THREE_DEV_EMP2"]
}
}
];
function filteredLists(id) {
let term = search.trim().toUpperCase();
let scoped = data.filter(item => { return parseInt(item.content.id) === parseInt(id) });
if(term.length > 0) {
return scoped.filter(item => {
return item.content.details.find(seek => seek.match(search));
});
}
return scoped;
}
console.log(filteredLists(3));
filteredLists() {
return data.filter(
function(item) {
return item.content.details.find(
function(detail) {
return detail.toLowerCase().match(this.search)
}.bind(this)
)
}.bind(this)
)
}

Categories

Resources