1<template> 2 <div class="table-filter d-inline-block"> 3 <p class="d-inline-block mb-0"> 4 <b-badge v-for="(tag, index) in tags" :key="index" pill> 5 {{ tag }} 6 <b-button-close 7 :disabled="dropdownVisible" 8 :aria-hidden="true" 9 @click="removeTag(tag)" 10 /> 11 </b-badge> 12 </p> 13 <b-dropdown 14 variant="link" 15 no-caret 16 right 17 data-test-id="tableFilter-dropdown-options" 18 @hide="dropdownVisible = false" 19 @show="dropdownVisible = true" 20 > 21 <template #button-content> 22 <icon-filter /> 23 {{ $t('global.action.filter') }} 24 </template> 25 <b-dropdown-form> 26 <b-form-group 27 v-for="(filter, index) of filters" 28 :key="index" 29 :label="filter.label" 30 > 31 <b-form-checkbox-group v-model="tags"> 32 <b-form-checkbox 33 v-for="value in filter.values" 34 :key="value" 35 :value="value" 36 :data-test-id="`tableFilter-checkbox-${value}`" 37 @change="onChange($event, { filter, value })" 38 > 39 {{ value }} 40 </b-form-checkbox> 41 </b-form-checkbox-group> 42 </b-form-group> 43 </b-dropdown-form> 44 <b-dropdown-item-button 45 variant="primary" 46 data-test-id="tableFilter-button-clearAll" 47 @click="clearAllTags" 48 > 49 {{ $t('global.action.clearAll') }} 50 </b-dropdown-item-button> 51 </b-dropdown> 52 </div> 53</template> 54 55<script> 56import IconFilter from '@carbon/icons-vue/es/settings--adjust/20'; 57 58export default { 59 name: 'TableFilter', 60 components: { IconFilter }, 61 props: { 62 filters: { 63 type: Array, 64 default: () => [], 65 validator: (prop) => { 66 return prop.every( 67 (filter) => 'label' in filter && 'values' in filter && 'key' in filter 68 ); 69 }, 70 }, 71 }, 72 data() { 73 return { 74 dropdownVisible: false, 75 activeFilters: this.filters.map(({ key }) => { 76 return { 77 key, 78 values: [], 79 }; 80 }), 81 }; 82 }, 83 computed: { 84 tags: { 85 get() { 86 return this.activeFilters.reduce((arr, filter) => { 87 return [...arr, ...filter.values]; 88 }, []); 89 }, 90 set(value) { 91 return value; 92 }, 93 }, 94 }, 95 methods: { 96 removeTag(tag) { 97 this.activeFilters.forEach((filter) => { 98 filter.values = filter.values.filter((val) => val !== tag); 99 }); 100 this.emitChange(); 101 }, 102 clearAllTags() { 103 this.activeFilters.forEach((filter) => { 104 filter.values = []; 105 }); 106 this.emitChange(); 107 }, 108 emitChange() { 109 this.$emit('filter-change', { 110 activeFilters: this.activeFilters, 111 }); 112 }, 113 onChange(checked, { filter: { key }, value }) { 114 this.activeFilters.forEach((filter) => { 115 if (filter.key === key) { 116 checked 117 ? filter.values.push(value) 118 : (filter.values = filter.values.filter((val) => val !== value)); 119 } 120 }); 121 this.emitChange(); 122 }, 123 }, 124}; 125</script> 126 127<style lang="scss" scoped> 128.badge { 129 margin-right: $spacer / 2; 130} 131</style> 132