I am new to view, so perhaps this is by design, but just in case. I have a component that takes a list of facets and then splits them up for a nice display. The code looks like this:
import { getFacets } from "@/logic/get-facets";
import {
defineComponent,
getCurrentInstance,
ref,
toRefs,
} from "@vue/composition-api";
import Filters from "@/components/filters/filters.component.vue";
export default defineComponent({
name: "Chooser",
components: { Filters },
emits: ["onFilter"],
props: {
categoryName: {
type: String,
required: true,
},
facets: {
type: Array,
required: true,
},
loading: {
type: Boolean,
default: () => false,
},
},
setup(props) {
const instance = getCurrentInstance();
const expanded = ref(false);
const filters = ref([]);
const scenarios = ref([]);
const { facets } = toRefs(props);
const { criteria } = getFacets(facets.value);
const expand = () => {
expanded.value = !expanded.value;
};
const addFilter = (attribute: any) => {
let index = -1;
for (let i = filters.value.length - 1; i >= 0; i--) {
const filter = filters.value[i];
if (filter.facetName !== attribute.facetName) continue;
index = i;
filters.value.splice(i, 1);
}
if (index === -1) filters.value.push(attribute);
instance.proxy.$emit("onFilter", filters.value);
};
return { expanded, criteria, filters, scenarios, expand, addFilter };
},
});
The getFacets method looks like this:
import { ref } from "@vue/composition-api";
class Facet {
key: string;
value: FacetItem[];
}
class FacetItem {
facetName: string;
count: number;
value: string;
from: string;
to: string;
}
export function getFacets(facets: any) {
const criteria = ref([]);
const facet = facets.find((item: Facet) => item.key === "Criteria/Attribute");
let currentCriterionName = "";
let criterion: any = {};
let count = 0;
(<Facet>facet).value
.sort((a, b) => a.value.localeCompare(b.value))
.forEach((item: FacetItem) => {
const value = item.value;
const [c, a] = value.split(":");
if (c !== currentCriterionName) {
if (criterion.name) criteria.value.push(criterion);
criterion = {
name: c,
attributes: [],
active: false,
};
currentCriterionName = c;
}
criterion.attributes.push({
name: a,
facetName: value,
to: item.to,
from: item.from,
count: item.count,
});
count++;
});
if (count === facet.value.length) criteria.value.push(criterion);
return { criteria };
}
As you can see, my component expects a facets array that is required (along with a categoryName and optional loading boolean). The initial array looks like this:
[
{
"key":"Criteria/Attribute",
"value":[
{
"count":5,
"value":"Capacity:Extra Small",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":11,
"value":"Capacity:Large",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":13,
"value":"Capacity:Medium",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":19,
"value":"Capacity:Small",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":8,
"value":"Coffee at the press of a button?:Yes",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":13,
"value":"Extraction Quality:Amazing",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":5,
"value":"Extraction Quality:Exceptional",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":24,
"value":"Extraction Quality:Good",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":6,
"value":"Extraction Quality:Very Good",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":16,
"value":"Milk Frother:Automatic",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":10,
"value":"Milk Frother:None",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":22,
"value":"Milk Frother:Steam Wand",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":10,
"value":"Noise:Buzzing",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":10,
"value":"Noise:Loud",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":23,
"value":"Noise:Quiet",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":5,
"value":"Noise:Silent",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":3,
"value":"Size:Extra Small",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":6,
"value":"Size:Large",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":31,
"value":"Size:Medium",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":8,
"value":"Size:Small",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":2,
"value":"Speed:Instant",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":28,
"value":"Speed:Quick Heat",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":5,
"value":"Speed:Slow",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":13,
"value":"Speed:Standard",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":7,
"value":"Style:Designer",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":8,
"value":"Style:Minimalist",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":20,
"value":"Style:Modern",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":13,
"value":"Style:Professional",
"from":null,
"to":null,
"__typename":"FacetModel"
}
],
"__typename":"KeyValuePairOfStringAndListOfFacetModel"
}
]
In this component, when one of the items is clicked, it performs a search which returns a new set of facets. Here is an example of the new array:
[
{
"key":"Criteria/Attribute",
"value":[
{
"count":5,
"value":"Capacity:Extra Small",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":5,
"value":"Extraction Quality:Good",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":5,
"value":"Milk Frother:None",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":5,
"value":"Noise:Silent",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":5,
"value":"Speed:Slow",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":5,
"value":"Style:Minimalist",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":3,
"value":"Size:Extra Small",
"from":null,
"to":null,
"__typename":"FacetModel"
},
{
"count":2,
"value":"Size:Medium",
"from":null,
"to":null,
"__typename":"FacetModel"
}
],
"__typename":"KeyValuePairOfStringAndListOfFacetModel"
}
]
This is all served from a parent component. The initial array is produced when the page loads, when the filter is clicked above, it then calls a method that updates the array which the Chooser component uses.
<chooser
:categoryName="category.name"
:facets="result.search.facets"
:loading="loading"
@onFilter="search($event)"
>
</chooser>
The problem is, even though I can do this {{ result.search.facets }} in the parent component and see the array change, the Chooser remains exactly the same.
Is there something I must do in order for the Chooser to update when the array changes?
result.search.facetsarray or completely replacing it?criteriashould be computed so it is rebuild (by executinggetFacetsfunction) each time thefasetsprop changes.