I am trying to filter an array that is being reindexed on-the-fly.
I would like to have a single input field that matches strings on multiple properties.
<paper-input value="{{val}}" placeholder="Filter Cards"></paper-input>
<template is="dom-repeat" items="[[restructure(data)]]" initial-count="2" filter="{{filter(val, data)}}">
<card-items data="[[item]]" items="[[item.items]]" links="false"></card-items>
</template>
...
This function restructures the data to be formatted for a card layout.
returnInvoices(data) {
let newData = [];
for (let i = 0; i < data.length; i++) {
let noOrder = data[i].noOrder;
if (!newData[noOrder]) {
newData[noOrder] = {
idMaster: data[i].idMaster,
itemId: data[i].itemId,
description: data[i].description,
noOrder: noOrder,
items: []
};
}
newData[noOrder].items.push('{' +
'"idMaster":"' + data[i].idMaster + '",' +
'"itemId":"' + data[i].itemId + '"}');
}
return newData.filter(val => val).sort((a, b) => {return b.noInvoice - a.noInvoice}) // reindex array
}
I would like this function to return objects in the array whom have properties that match a string.
filter(val, data) {
if (!val) return null;
else {
val = val.toLowerCase();
// not sure what to do here
// would like to filter on all object properties (from data)
return data[0];
}
}
...
Example
if(val == 1) return data[0] & data[1];
if(val == 'Item') return data[0] & data[2];
For data array
let data = [
{"itemId": "1", "description": "Nice Item", "noOrder": 123},
{"itemId": "2", "description": "Good Product", "noOrder": 123},
{"itemId": "3", "description": "Fine Item", "noOrder": 444}
}
...
How can I filter strings on all 3 properties?
How can I use the filter as an intermediate function to the restructuring?
The documentation for dom-repeat's filter property includes following statements:
The function should match the sort function passed to Array.filter. Using a filter function has no effect on the underlying items array.
And the Array.filter is documented as
Function is a predicate, to test each element of the array. Return true to keep the element, false otherwise.
So from your filter func just return true
if any of the properties matches input and false
otherwise, something like
filter(item) {
let val = this.val;
// if the filter is empty show everything
if (!val) return true;
// otherwise see is there a match
val = val.toLowerCase();
return // for the "description" use "contains" logic
(item.description.toLowerCase().includes(val)) ||
// for the "noOrder" use "starting" logic
(item.noOrder.toString().indexOf(val) == 0)
// add matching conditions here ...
}
Now to trigger the filtering you must observe the properties which trigger filtering, ie your html would be like
<paper-input value="{{val}}" placeholder="Filter Cards"></paper-input>
<template is="dom-repeat" filter="[[filter]]" observe="val" items="[[restructure(data)]]" initial-count="2">
<card-items data="[[item]]" items="[[item.items]]" links="false"></card-items>
</template>
BTW why do you push items into newData as strings? Why not as objects, ie
newData[noOrder].items.push({
idMaster: data[i].idMaster,
itemId: data[i].itemId
});
and I think you can lose the newData.filter(val => val)
step...