Vue.js multiple search with checkboxes - vue.js

I'm trying to create a search form with input text fields and checkboxes.
Right now I have the search working for text fields but I can't make it work for checkboxes.
I'm totally new with vue.js so probably I'm missing some basic stuff.
The problem is in the computed part in the last filter, with the categories checkboxes:
computed: {
filteredExperiences() {
return this.experiences.filter( item => {
return (
item.destination.toLowerCase().indexOf(this.searchDestinations.toLowerCase()) > -1
&& item.title.toLowerCase().indexOf(this.searchExperiences.toLowerCase()) > -1
&& item.categories.map(cat => cat.title.toLowerCase()).indexOf(this.checkedCategories.toLowerCase()) > -1
)
})
}
}
So searchDestinations and searchExperiences work fine but search by categories doesn't.
Any idea why? What am I doing wrong?
This is the full code:
var app = new Vue({
el: '#app',
data: {
destinations: [{
title: 'Madrid',
slug: 'madrid'
},
{
title: 'London',
slug: 'london'
},
{
title: 'Chicago',
slug: 'chicago'
},
{
title: 'Los Angeles',
slug: 'los-angeles'
}
],
categories: [{
title: 'Concerts',
slug: 'concerts'
},
{
title: 'Museums',
slug: 'museums'
},
{
title: 'Theaters',
slug: 'theaters'
},
{
title: 'Cinemas',
slug: 'cinemas'
}
],
experiences: [{
id: 1,
title: 'Bruce Springsteen Live Madrid',
destination: 'Madrid',
categories: ['concerts', 'theaters'],
duration: '2h'
},
{
id: 2,
title: 'Mulan 2 the movie',
destination: 'London',
categories: ['cinemas', 'theaters'],
duration: '2h'
},
{
id: 3,
title: 'British Museum',
destination: 'London',
categories: ['museums'],
duration: '3h'
}
],
checkedCategories: [],
searchDestinations: '',
searchExperiences: ''
},
computed: {
filteredExperiences() {
return this.experiences.filter(item => {
return (item.destination.toLowerCase().indexOf(this.searchDestinations.toLowerCase()) > -1 && item.title.toLowerCase().indexOf(this.searchExperiences.toLowerCase()) > -1)
})
}
}
});
Here is the codepen:
See the Pen
vue.js filtered multi-search by Javier (#oterox)
on CodePen.

the problem is here:
&& item.categories.map(cat => cat.title.toLowerCase()).indexOf(this.checkedCategories.toLowerCase()) > -1
like this it should work:
computed: {
filteredExperiences() {
return this.experiences.filter( item => {
if(item.destination.indexOf(this.searchDestinations) < 0) { return false }
if (item.title.indexOf(this.searchExperiences) < 0 ) { return false }
let matchedCats = item.categories.filter(cat => {
let hasCat = this.checkedCategories.findIndex(checkCat => cat.toLowerCase() === checkCat.toLowerCase());
return hasCat > -1;
})
if(this.checkedCategories.length > 0 && matchedCats.length < 1)
{
return false;
}
return true;
})
}
}

Related

TreeGrid extension for DataTables - how to get a checkbox added after name?

I found a TreeGrid extension for DataTables:
https://homfen.github.io/dataTables.treeGrid.js/
but instead of the name I would like to add a column between name and position and place a checkbox here.
However when I do this e.g.:
var columns = [
{
title: '',
target: 0,
className: 'treegrid-control',
data: function (item) {
if (item.children) {
return '<span>+<\/span>';
}
return '';
}
},
{
title: 'Name',
target: 1,
data: function (item) {
return item.name;
}
},
{
defaultContent: '',
target: 2,
className: 'select-checkbox',
function(item) {
return item;
}
},
{
title: 'Position',
target: 3,
data: function (item) {
return item.position;
}
},
{
title: 'Office',
target: 4,
data: function (item) {
return item.office;
}
},
{
title: 'Extn.',
target: 5,
data: function (item) {
return item.extn;
}
},
{
title: 'Start date',
target: 6,
data: function (item) {
return item.start;
}
},
{
title: 'Salary',
target:7,
data: function (item) {
return item.salary;
}
}
];
I get an extra column but when checking the parent does not select all underlying children rows.
Anyone have an idea how to establish this?
Edit: updated the columns definition.
When I add a button to read the selected values e.g.:
dom: 'Bfrtip',
select:true,
buttons: [
{
text: 'Alert selected',
action: function(e, dt, node, config) {
var data = table.rows({
selected: true
}).data().toArray();
var i;
var text = new Array();
for (i = 0; i < data.length; i++) {
text.push(data[i].name);
}
alert("you selected: " + text.join(",") );
console.log("text---" + text.join(","));
}
}
]
the table starts to behave oddly for example: the selection of underlying children stops.

Set filter options on vue-good-table programmatically

How can one change the value that is displayed in the UI filter elements(input, dropdown etc) in vue-good-table programmatically?
For example if I call:
this.$set(this.table.columnsFilters, 'name', 'bob')
I want the value in the HTML input field 'name' to display bob.
Unfortunatly the settting the values as i described above does not work
Edit If you are using version 2.16.0 or above, you'll need to do this:
CodePen for v2.16.0 +
// v2.16.0 or higher
...
changeFilter(field, newFilter) {
let newCols = JSON.parse(JSON.stringify(this.columns));
let found = newCols.find(c => {
return c.field == field;
});
console.log(found);
if (found) {
if (found.hasOwnProperty("filterOptions")) {
found.filterOptions.filterValue = newFilter;
this.columns = newCols;
} else {
alert(`Column '${field}' does not have filtering configured!`);
}
} else {
alert(`Field '${field}' does not exist!`);
}
}
Original Answer
If I am understanding this correctly you want to set the filter for a field programmatially... Something like this should work.. Click the button to change the filter programamaticlly... If you change this line to any valid name, it will filter by that name... Change 'Bob' to a valid name...(like Dan)...
<button
style="width:200px;"
#click.stop="changeFilter('name', 'Bob')"
>Click To Change Name Filter</button>
CodePen Mirror
const vm = new Vue({
el: "#app",
name: "my-component",
data: {
columns: [
{
label: "Name",
field: "name",
filterOptions: {
enabled: true, // enable filter for this column
placeholder: "Filter Name", // placeholder for filter input
filterValue: "", // initial populated value for this filter
filterDropdownItems: [], // dropdown (with selected values) instead of text input
filterFn: this.columnFilterFn, //custom filter function that
trigger: "enter" //only trigger on enter not on keyup
}
},
{
label: "Age",
field: "age",
type: "number"
},
{
label: "Created On",
field: "createdAt",
type: "date",
dateInputFormat: "YYYY-MM-DD",
dateOutputFormat: "MMM Do YY"
},
{
label: "Percent",
field: "score",
type: "percentage"
}
],
rows: [
{
id: 1,
name: "John",
age: 20,
createdAt: "201-10-31:9: 35 am",
score: 0.03343
},
{
id: 2,
name: "Jane",
age: 24,
createdAt: "2011-10-31",
score: 0.03343
},
{
id: 3,
name: "Susan",
age: 16,
createdAt: "2011-10-30",
score: 0.03343
},
{
id: 4,
name: "Bob",
age: 55,
createdAt: "2011-10-11",
score: 0.03343
},
{
id: 5,
name: "Dan",
age: 40,
createdAt: "2011-10-21",
score: 0.03343
},
{
id: 6,
name: "John",
age: 20,
createdAt: "2011-10-31",
score: 0.03343
}
]
},
methods: {
clearFilter(field) {
try {
let found = this.columns.find((c) => {
return c.field == field
});
found.filterOptions.filterValue = "";
} catch {
alert(`Unable to clear ${field} filter`)
}
},
changeFilter(field, newFilter) {
let found = this.columns.find((c) => {
return c.field == field
});
if(found) {
if(found.hasOwnProperty("filterOptions")) {
if(found.filterOptions.hasOwnProperty("filterValue")) {
found.filterOptions.filterValue = newFilter;
} else {
alert(`Column '${field}' does not have filterValue property!`)
}
} else {
alert(`Column '${field}' does not have filtering configured!`)
}
} else {
alert(`Field '${field}' does not exist!`)
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-good-table#2.15.3/dist/vue-good-table.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vue-good-table#2.12.2/dist/vue-good-table.css" rel="stylesheet"/>
<div id="app">
<div>
<div style="margin:10px 10px 10px 10px;">
<button
style="width:200px;"
#click.stop="changeFilter('name', 'Bob')"
>Click To Change Name Filter</button>
<button
style="width:200px;"
#click.stop="clearFilter('name')"
>Clear Name Filter</button>
</div>
<vue-good-table :columns="columns" :rows="rows" />
</div>
</div>
See: https://github.com/xaksis/vue-good-table/issues/475
Official recommended method of doing this for version >= 2.17.5:
this.$set(this.columns[foundIndex].filterOptions, 'filterValue', value);
If you want to have it done using $route query params:
for (var key in this.$route.query){
var field = key;
let foundIndex = this.columns.findIndex((c) => {
return c.field == field
});
if (foundIndex !== -1 ){
this.$set(this.columns[foundIndex].filterOptions, 'filterValue', this.$route.query[key]);
}
}
Vue cannot detect normal property additions (e.g. this.myObject.newProperty = 'hi')
Therefore, using this.$set(this.table.columnsFilters, 'name', 'bob') instead of your code.
More information about $set

Validating a non existent field error when trying to use vee-validate

I am trying to make a multistep form. For that I made some Input, Dropdown Components.
FormInput.vue
<template>
<div class="field">
<label class="label has-text-left"
:for="fieldId">
{{ labelText }}
</label>
<div class="control">
<input
v-model="inputValue"
v-bind="$attrs"
class="input"
:id="fieldId"
#input="event => {$emit('input', event.target.value)}"
:class="{'is-danger': error,
'is-success': !error && instance && instance!==''}" >
</div>
<p class="help has-text-left danger"
v-show="error">
{{ error }}
</p>
</div>
</template>
<script>
export default {
name: 'FormInput',
props: {
labelText: String,
instance: [Number, String],
fieldId: String,
error: String
},
data () {
return {
inputValue: null
}
},
mounted () {
this.inputValue = this.instance
},
$_veeValidate: {
name () {
this.fieldId
},
value () {
this.instance
}
},
watch: {
instance: function(newValue) {
this.inputValue = newValue
}
}
}
</script>
I am using this FormInput components in many forms. Eg.
QuerySportsFitnessForm.vue
<div class="modal-form" v-if="step === 5">
<FormDropdown
v-if="form.standard !== 'dietician'"
labelText="What is the gender of the student??"
v-model="form.gender"
:options="genderArray"
:instance="form.gender"
ref="gender"></FormDropdown>
<FormInput
type="text"
labelText="Your locality"
v-model="form.location"
:instance="form.location"
fieldId="location"
v-validate="'required'"
name="location"
:error="errors.first('location')"
placeholder="eg.Heerapura"></FormInput>
<FormInput
type="textarea"
labelText="Your full address"
v-model="form.address"
:instance="form.address"
fieldId="address"
v-validate="'required|min:10'"
name="address"
:error="errors.first('address')"
placeholder="Enter your postal address"></FormInput>
<FormInput
type="textarea"
labelText="Anything else you would like to share with us?"
v-model="form.comment"
:instance="form.comment"
fieldId="comment"
placeholder="Comment here"></FormInput>
</div>
<script>
import axios from 'axios'
import FormInput from './FormInput'
import FormDropdown from './FormDropdown'
import FormCheckbox from './FormCheckbox'
export default {
components: {
FormDropdown,
FormInput,
FormCheckbox
},
name: 'QuerySportsFitnessForm',
props: {
},
data () {
return {
modalStatus: false,
step: 1,
progressValue: 0,
form: {
fees: 1000,
category: 'Sports and Fitness',
standard: '',
subjects: [],
level: '',
type_coaching: '',
travel: '',
number_of_student: '',
coaching_location: '',
days: '',
gender_preference: '',
location: '',
address: '',
name: '',
age: '',
contact: '',
email: '',
gender: '',
comment: ''
},
typeCoachingArray: [
{ value: "batch", text: "In a Batch"},
{ value: "1-on-1", text: "1-on-1 Sessions"},
{ value: "flexible", text: "Flexible to get best tutor"}
],
travelArray: [
{ value: "0-1", text: "0-1 Km"},
{ value: "0-3", text: "0-3 Km"},
{ value: "0-5", text: "0-5 Km"},
{ value: "more than 5", text: "More than 5 Km"}
],
coachingLocationArray: [
{ value: "at home", text: "At Home"},
{ value: "at tutor", text: "At Tutor's Location"},
{ value: "flexible", text: "Flexible to get best tutor"},
],
genderPreferenceArray: [
{ value: "male", text: "Male" },
{ value: "female", text: "Female" },
{ value: "none", text: "No preference" }
],
daysArray: [
{ value: "1", text: "1 day a week" },
{ value: "2", text: "2 days a week" },
{ value: "3", text: "3 days a week" },
{ value: "4", text: "4 days a week" },
{ value: "5", text: "5 days a week" },
{ value: "6", text: "6 days a week" },
{ value: "7", text: "7 days a week" }
],
levelArray: [
{ value: "beginner", text: "Beginner" },
{ value: "intermediate", text: "Intermediate" },
{ value: "advanced", text: "Advanced" }
],
genderArray: [
{ value: "male", text: "Male" },
{ value: "female", text: "Female" }
],
numberOfStudentArray: [
{ value: "One", text: "One" },
{ value: "Two", text: "Two" },
{ value: "Three", text: "Three" },
{ value: "More than Three", text: "More than Three" },
],
dieticianSubjects: [
"Weight Loss",
"Weight Gain",
"Health Condition",
"Sports Conditioning Diets"
],
martialArtsSubjects: [
"Karate",
"Taekwondo",
"Wing Chun",
],
trainerSubjects: [
"General Fitness",
"Intermediate Bodybuilding",
"Hardcore Bodybuilding"
],
yogaSubjects: [
"Power Yoga",
"Therapeutic Yoga",
"Yoga for Senior Citizen",
"Pregnancy Yoga",
"Yoga for Everyone"
]
}
},
mounted () {
this.form.standard = this.$route.params.standard
if (['dietician', 'trainer', 'yoga', 'martial-arts'].indexOf(this.form.standard) !== -1) {
this.step = 1
}
else {
this.step = 2
}
},
methods: {
modalToggle() {
this.modalStatus = !this.modalStatus
},
/*addToInstance method is corrosponding to checkbox component*/
addToInstance(e) {
if (this.form.subjects.indexOf(e) ===-1) {
this.form.subjects.push(e)
}
else {
this.form.subjects.splice(this.form.subjects.indexOf(e), 1)
}
},
prev() {
this.progressValue -= 25
this.step--;
},
next() {
if (this.step === 1) {
this.$validator.validate('subjects', this.form.subjects)
if (this.form.subjects.length!==0) {
this.step++
this.progressValue += 20
}
}
else if (this.step === 2) {
this.$refs.level.dropdownToggle()
this.$refs.genderPreference.dropdownToggle()
this.$refs.days.dropdownToggle()
if (['dietician', 'trainer', 'yoga', 'zumba'].indexOf(this.form.standard) === -1) {
if (this.form.level !== '' && this.form.days !== '') {
this.step++
this.progressValue += 20
}
}
else if (['dietician', 'trainer', 'yoga'].indexOf(this.form.standard) !== -1) {
if(this.form.gender_preference !== '' && this.form.days !== '') {
this.step++
this.progressValue +=20
}
}
else if (this.form.standard === 'zumba') {
if (this.form.days !== '') {
this.step++
this.progressValue += 20
}
}
}
else if (this.step === 3) {
if (this.form.standard !== 'dietician') {
this.$refs.typeCoaching.dropdownToggle()
}
if (['chess', 'skating', 'trainer', 'yoga', 'zumba'].indexOf(this.form.standard) !== -1 && this.form.type_coaching!=='batch') {
this.$refs.coachingLocation.dropdownToggle()
}
if (this.form.coaching_location !== 'at home') {
this.$refs.travel.dropdownToggle()
}
if (this.form.standard !== 'dietician') {
if (this.form.type_coaching !== '') {
if (['chess', 'skating', 'trainer', 'yoga', 'zumba'].indexOf(this.form.standard) !== -1) {
if (this.form.type_coaching !== 'batch' && this.form.coaching_location !=='') {
if (this.form.coaching_location !== 'at home' && this.form.travel !== '') {
this.step++
this.progressValue += 20
}
else if (this.form.coaching_location === 'at home' && this.form.travel === '') {
this.step++
this.progressValue += 20
}
}
else if (this.form.type_coaching === 'batch' && this.form.travel !== '') {
this.step++
this.progressValue += 20
}
}
else if (['chess', 'skating', 'trainer', 'yoga', 'zumba'].indexOf(this.form.standard) === -1) {
if (this.form.travel !== '') {
this.step++
this.progressValue += 20
}
}
}
}
else if (this.form.standard === 'dietician') {
if (this.form.coaching_location !== 'at home' && this.form.travel !== '') {
this.step++
this.progressValue += 20
}
else if (this.form.coaching_location === 'at home' && this.form.travel === '') {
this.step++
this.progressValue += 20
}
}
}
else if (this.step === 4) {
this.$validator.validate('name', this.form.name)
this.$validator.validate('contact', this.form.contact)
this.$validator.validate('email', this.form.email)
this.$validator.validate('age', this.form.age).then(() => {
if (this.errors.items.length === 0) {
this.step++
this.progressValue += 20
}
})
}
},
//Problem with this block I think
validateBeforeSubmit() {
this.$refs.gender.dropdownToggle()
this.$validator.validate('location', this.form.location)
this.$validator.validate('address', this.form.address)
if (this.form.standard === 'dietician') {
if (this.errors.items.length === 0) {
this.addQuery()
this.modalToggle()
}
}
else if (this.form.standard !== 'dietician') {
if (this.errors.items.length === 0 && this.form.gender !== '') {
this.addQuery()
this.modalToggle()
}
}
},
emptyCoachingLocation() {
this.form.coaching_location = ''
},
emptyTravel() {
this.form.travel = ''
},
addQuery() {
axios({
method: 'post',
url: 'http://127.0.0.1:8000/api/hobby-query/',
data: {
fees: this.form.fees,
category: this.form.category,
standard: this.form.standard,
subjects: this.form.subjects,
level: this.form.level,
type_coaching: this.form.type_coaching,
travel: this.form.travel,
number_of_student: this.form.number_of_student,
coaching_location: this.form.coaching_location,
days: parseInt(this.form.days),
gender_preference: this.form.gender_preference,
location: this.form.location,
address: this.form.address,
name: this.form.name,
age: parseInt(this.form.age),
contact: this.form.contact,
email: this.form.email,
student_gender: this.form.gender,
comment: this.form.comment
}
}).then(() => {
this.form.subjects = [],
this.form.level = '',
this.form.type_coaching = '',
this.form.travel = '',
this.form.number_of_student = '',
this.form.coaching_location = '',
this.form.days = '',
this.form.gender_preference = '',
this.form.location = '',
this.form.address = '',
this.form.name = '',
this.form.age = '',
this.form.contact = '',
this.form.email = '',
this.form.gender = '',
this.form.comment = ''
})
.catch((error) => {
console.log(error);
});
}
}
}
</script>
I only included one div for example. When I am click "next" button method next() works without any problem. When I click submit button it fires up validateBeforeSubmit() method. And I get this error 2 times in console of developer tools.
Uncaught (in promise) Error: [vee-validate] Validating a non-existent field: "". Use "attach()" first.
at createError (vee-validate.esm.js?00d1:297)
at Validator._handleFieldNotFound (vee-validate.esm.js?00d1:2282)
at Validator.validate (vee-validate.esm.js?00d1:1959)
at ScopedValidator.validate (vee-validate.esm.js?00d1:3276)
at VueComponent.validateBeforeSubmit (QuerySportsFitnessForm.vue?cb73:448)
at invoker (vue.esm.js?efeb:2027)
at HTMLButtonElement.fn._withTask.fn._withTask (vue.esm.js?efeb:1826)
createError # vee-validate.esm.js?00d1:297
_handleFieldNotFound # vee-validate.esm.js?00d1:2282
validate # vee-validate.esm.js?00d1:1959
validate # vee-validate.esm.js?00d1:3276
validateBeforeSubmit # QuerySportsFitnessForm.vue?cb73:448
invoker # vue.esm.js?efeb:2027
fn._withTask.fn._withTask # vue.esm.js?efeb:1826
I tried to give .then promise after validate method call also but it didn't changed anything. like this
validateBeforeSubmit() {
this.$refs.gender.dropdownToggle()
this.$validator.validate('location', this.form.location)
this.$validator.validate('address', this.form.address).then(() {
if (this.form.standard === 'dietician') {
if (this.errors.items.length === 0) {
this.addQuery()
this.modalToggle()
}
}
else if (this.form.standard !== 'dietician') {
if (this.errors.items.length === 0 && this.form.gender !== '') {
this.addQuery()
this.modalToggle()
}
}
})
}
What am i doing wrong, I am not able to figure it out myself
I think this issue is happening because either location or address is not present in html due to step === 5 condition and you still try to validate that part. You can put below condition to get rid of this error===>
if (this.$validator.fields.find({ name: 'location' })) {
this.$validator.validate('location');
}
The problem seems to be that the validation's value change listener on the input was getting fired when cleared the variable, which then tried to validate the input, but the input was no longer in the validator's field list because it was detached when it was hidden.
this.$validator.pause()
this.$nextTick(() => {
this.$validator.errors.clear()
this.$validator.fields.items.forEach(field => field.reset())
this.$validator.fields.items.forEach(field => this.errors.remove(field))
this.$validator.resume()
})
This code will solve the issue.

Vue2-Highcharts setOptions Lang

I'm trying to do a standard translation for highcharts with Vue2, but I'm having difficulty because I can not access the setOptions option. I do not find much documentation of vue2 with Highcharts, so I'm having some difficulties working with it, if anyone can also provide me with that content, thank you.
import VueHighcharts from 'vue2-highcharts'
export default{
components: {
VueHighcharts
},
props: ['title', 'subtitle', 'initoptions'],
data(){
let initOptions = JSON.parse(this.initoptions);
let tmpSeries = [];
let count = 0;
$.each(initOptions, function(key, value) {
let data = [];
$.each(value, function(key2, value2){
let date = key2.split('-');
data.push([Date.UTC(date[2], date[1], date[0]), value2]);
});
tmpSeries.push({'name': key, 'data': data});
count++;
});
return{
options: {
/* ***
I can not set this setOptions property to lang
*** */
lang: {
loading: 'Aguarde...',
months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
weekdays: ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'],
shortMonths: ['Jan', 'Feb', 'Mar', 'Abr', 'Maio', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
exportButtonTitle: "Exportar",
printButtonTitle: "Imprimir",
rangeSelectorFrom: "De",
rangeSelectorTo: "Até",
rangeSelectorZoom: "Periodo",
downloadPNG: 'Download imagem PNG',
downloadJPEG: 'Download imagem JPEG',
downloadPDF: 'Download documento PDF',
downloadSVG: 'Download imagem SVG'
},
chart: {
type: 'spline'
},
title: {
text: this.title || ''
},
subtitle: {
text: this.subtitle || ''
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
day:'%e/%m',
week:'%e/%m',
month: '%m/%y',
year: '%m'
},
title: {
text: 'Date'
}
},
yAxis: {
title: {
text: 'Total'
},
labels: {
formatter: function () {
return this.value;
}
}
},
tooltip: {
crosshairs: true,
shared: true
},
credits: {
enabled: false
},
plotOptions: {
spline: {
marker: {
radius: 8,
lineColor: '#666666',
lineWidth: 1
}
}
},
series: tmpSeries
}
}
}
}
I hope someone can help me, thank you.
I'm not sure with this package but with the Official Vue Highcharts you can set options like that :
import Highcharts from 'highcharts';
import HighchartsMore from 'highcharts/highcharts-more';
HighchartsMore(Highcharts);
Highcharts.setOptions({
lang: {
decimalPoint: '.',
drillUpText: 'Back',
noData: "Check your options please",
resetZoom: 'Reset',
thousandsSep: ' '
}
});
import HighchartsVue from 'highcharts-vue';
Vue.use(HighchartsVue);

Filter DetailsList

Can anyone please let me know how to filter a DetailsList? For instance, let’s say I have the following list:
list
How do I filter the list such that when I type “Reject”, it will only show items with Status “Reject”
Here is the code I tried (from the documentation https://developer.microsoft.com/en-us/fabric#/components/detailslist):
private _onChangeText = (text: any) => {
this.setState({ items: text ? this.state.items.filter(i =>
i.Status.indexOf(text) > -1) : this.state.items });
}
<TextField
label="Filter by name:"
onChanged={this._onChangeText}
/>
Thanks!
Here's a Codepen where I'm filtering a collection of items to see if the text is present in any of the item's values (case-insensitive). It is similar to the documentation example you linked in your original question. I hope that helps!
let COLUMNS = [
{
key: "name",
name: "Name",
fieldName: "Name",
minWidth: 20,
maxWidth: 300,
},
{
key: "status",
name: "Status",
fieldName: 'Status',
minWidth: 20,
maxWidth: 300
}
];
const ITEMS = [
{
Name: 'xyz',
Status: 'Approve'
},
{
Name: 'abc',
Status: 'Approve'
},
{
Name: 'mno',
Status: 'Reject'
},
{
Name: 'pqr',
Status: 'Reject'
}
]
const includesText = (i, text): boolean => {
return Object.values(i).some((txt) => txt.toLowerCase().indexOf(text.toLowerCase()) > -1);
}
const filter = (text: string): any[] => {
return ITEMS.filter(i => includesText(i, text)) || ITEMS;
}
class Content extends React.Component {
constructor(props: any) {
super(props);
this.state = {
items: ITEMS
}
}
private _onChange(ev: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, text: string) {
let items = filter(text);
this.setState({ items: items });
}
public render() {
const { items } = this.state;
return (
<Fabric.Fabric>
<Fabric.TextField label="Filter" onChange={this._onChange.bind(this)} />
<Fabric.DetailsList
items={ items }
columns={ COLUMNS }
/>
</Fabric.Fabric>
);
}
}
ReactDOM.render(
<Content />,
document.getElementById('content')
);