HighChart.js : How to group nodes in organization chart - javascript

I want to make a family tree using Highchart.js organization chart. For a married couple, I want to display either:
(1) the nodes connected to each other (as seen in the below image between nodes at the top) or
(2) group them together.
Is there a function in Highchart.js that I can achieve this?
I have tried to use some functions as written in https://api.highcharts.com/highcharts/series.organization but haven't found what I needed.
https://jsfiddle.net/k4ped9fj/
<script>
Highcharts.chart('container', {
chart: {
height: 400,
inverted: true
},
title: {
text: ""
},
series: [{
type: 'organization',
name: 'Family Tree',
keys: ['from', 'to'],
data: [
['1','2'],['3','1'],['3','4'],['3','8'],['3','16'],['3','22'],['16','10'],['16','25']
],
levels: [{
color: '#008fd5',
dataLabels: {
color: 'white'
},
height: 25
}],
linkColor: "#ccc",
linkLineWidth: 1,
linkRadius: 0,
nodes: [
{ name: "Sarah Collin", description: "7/5/1990", tags: ["T1and4"], id: "1", pid: 3, FirstName: "Sarah", LastName: "Collin", Birthdate: "7/5/1990", Alive: "1", SpouseID: "4", image: "photo.png" },
{ name: "Sofia Collin", description: "1/1/2017", id: "2", pid: 1, FirstName: "Sofia", LastName: "Collin", Birthdate: "1/1/2017", Alive: "1", image: "photo.png" },
{ name: "Richard Dolson", description: "7/7/1953-1/1/2016", id: "3", FirstName: "Richard", LastName: "Dolson", Birthdate: "7/7/1953", Alive: "0", DeathDate: "1/1/2016", image: "photo.png" },
{ name: "Adam Collin", description: "2/1/1990", tags: ["T1and4"], id: "4", pid: 3, FirstName: "Adam", LastName: "Collin", Birthdate: "2/1/1990", Alive: "0", Allergy: "Medicine", SpouseID: "1", image: "photo.png" },
{ name: "Jennifer Dolson", description: "1/2/1996", id: "8", pid: 3, FirstName: "Jennifer", LastName: "Dolson", Birthdate: "1/2/1996", Alive: "1", image: "photo.png" },
{ name: "Elias Wittek", description: "", id: "10", pid: 16, FirstName: "Elias", LastName: "Wittek", Alive: "1", image: "photo.png" },
{ name: "David Wittek", description: "2/1/1999", tags: ["T16and26"], id: "16", pid: 3, FirstName: "David", LastName: "Wittek", Birthdate: "2/1/1999", Alive: "1", SpouseID: "26", image: "photo.png" },
{ name: "Jeff Dolson", description: "2/1/2000", id: "22", pid: 3, FirstName: "Jeff", LastName: "Dolson", Birthdate: "2/1/2000", Alive: "0", image: "photo.png",layout:'hanging' , offset: '50%' },
{ name: "Will Wittek", description: "", id: "25", pid: 16, FirstName: "Will", LastName: "Wittek", Alive: "1", image: "photo.png" },
{ name: "Tracy Dolson", description: "2/1/2000", tags: ["T16and26"], id: "26", FirstName: "Tracy", LastName: "Dolson", Birthdate: "2/1/2000", Alive: "1", SpouseID: "16", image: "photo.png" }
],
colorByPoint: false,
color: '#007ad0',
dataLabels: {
color: 'white'
},
shadow: {
color: '#ccc',
width: 15,
offsetX: 0,
offsetY: 0
},
hangingIndent: 10,
borderColor: '#ccc',
nodePadding: 5,
nodeWidth: 80
}],
credits: {
enabled: false
},
tooltip: {
outside: true,
formatter: function () {
return '<b>' + this.point.name.toUpperCase() + '</b><br/>' +
'<span>' + this.point.description.toUpperCase() + '</span><br/>'
}
},
exporting: {
allowHTML: true,
sourceWidth: 800,
sourceHeight: 400
}
});
</script>

Unfortunately, this feature is not supported. However, you can achieve it using Highcharts.SVGRenderer.path and plotting custom link between two nodes. Check the code and demo posted below.
Code:
chart: {
height: 400,
inverted: true,
events: {
render: function() {
var chart = this,
node1,
node2,
graphic;
if (chart.customLink) {
chart.customLink.destroy();
}
chart.series[0].nodes.forEach(function (node) {
if (node.id === "3") {
node1 = node;
} else if (node.id === "31") {
node2 = node;
}
});
graphic = chart.renderer.path([
'M',
node1.shapeArgs.y + node1.shapeArgs.height / 2,
chart.plotHeight - node1.shapeArgs.x - node1.shapeArgs.width / 2 + 10,
'L',
node2.shapeArgs.y + node2.shapeArgs.height / 2,
chart.plotHeight - node2.shapeArgs.x - node1.shapeArgs.width / 2 + 10,
'Z'
]).attr({
'stroke-width': 1,
stroke: '#ccc'
}).add();
chart.customLink = graphic;
}
}
}
Demo:
https://jsfiddle.net/BlackLabel/tjr5gue2/1/
API reference:
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#path

Related

How to filter items in Fluent UI groupedList component

I want to use Fluent UI groupedList, but there are 2 things I didn't understand.
1st) I always see items have a parent group/s. Is it possible to write items in groups level?
-- Group 1
--- Group 2
---- Group 3
--- Item
As seen above, Item is on the level of Group 2. How can I implement something like this?
2nd) I couldn't filter items by groups. For example, I want some items to belong to Group 2, and some other to Group 3. But as I see on the component examples, we have counts and whatever count we give, the component shows us that much item.
Fluent UI groupedList component:
https://developer.microsoft.com/en-us/fluentui#/controls/web/groupedlist
I also have this codepen:
https://codepen.io/ozan-bilgi/pen/mdKZqNG?editors=0010
const { GroupedList, IGroup, IColumn, DetailsRow, Selection, SelectionMode, SelectionZone, Toggle, IToggleStyles, ThemeProvider, initializeIcons } = window.FluentUIReact;
const { useBoolean, useConst } = window.FluentUIReactHooks;
const { createListItems, createGroups, IExampleItem } = window.FluentUIExampleData;
// Initialize icons in case this example uses them
initializeIcons();
const toggleStyles: Partial<IToggleStyles> = { root: { marginBottom: '20px' } };
const items = [
{
color: "red",
description: "Lorem ipsum",
height: 212,
key: "group0",
location: "portland",
name: "www",
shape: "square",
thumbnail: "AAAA",
width: 212
},
{
color: "red",
description: "Lorem ipsum",
height: 212,
key: "group1",
location: "portland",
name: "eee",
shape: "square",
thumbnail: "AAAA",
width: 212
},{
color: "red",
description: "Lorem ipsum",
height: 212,
key: "group2",
location: "portland",
name: "rrr",
shape: "square",
thumbnail: "AAAA",
width: 212
},{
color: "red",
description: "Lorem ipsum",
height: 212,
key: "group3",
location: "portland",
name: "nnn",
shape: "square",
thumbnail: "AAAA",
width: 212
},{
color: "red",
description: "Lorem ipsum",
height: 212,
key: "group4",
location: "portland",
name: "bbb",
shape: "square",
thumbnail: "AAAA",
width: 212
},{
color: "red",
description: "Lorem ipsum",
height: 212,
key: "group5",
location: "portland",
name: "vvv",
shape: "square",
thumbnail: "AAAA",
width: 212
},{
color: "red",
description: "Lorem ipsum",
height: 212,
key: "group6",
location: "portland",
name: "lorem",
shape: "square",
thumbnail: "AAAA",
width: 212
},{
color: "red",
description: "Lorem ipsum",
height: 212,
key: "group7",
location: "portland",
name: "aaa",
shape: "square",
thumbnail: "AAAA",
width: 212
},
]
const columns = [
{ key: 'group0', name: 'Title', fieldName: 'name', minWidth: 100, maxWidth: 200, isResizable: true },
{ key: 'business', name: 'Business', fieldName: 'business', minWidth: 100, maxWidth: 200, isResizable: true },
{ key: 'initialAssessment', name: 'Initial Assessment', fieldName: 'initialAssessment', minWidth: 100, maxWidth: 200, isResizable: true },
];
//const groups = createGroups(groupCount, groupDepth, 0, groupCount);
const groups = [
{
children: [{
children: [],
count: 3,
isCollapsed: undefined,
key: "group0-0-0",
level: 1,
name: "group0-0-0",
startIndex: 0
}],
count: 2,
isCollapsed: undefined,
key: "group0",
level: 0,
name: "First Group",
startIndex: 0
},
{
children: [{
children: [],
count: 2,
isCollapsed: undefined,
key: "group1",
level: 1,
name: "group0-0-0",
startIndex: 0
}],
count: 1,
isCollapsed: undefined,
key: "group2",
level: 0,
name: "Second Group",
startIndex: 0
}
]
const GroupedListBasicExample: React.FunctionComponent = () => {
const onRenderCell = (
nestingDepth?: number,
item?: IExampleItem,
itemIndex?: number,
group?: IGroup,
): React.ReactNode => {
return item && typeof itemIndex === 'number' && itemIndex > -1 ? (
<DetailsRow
columns={columns}
groupNestingDepth={nestingDepth}
item={item}
itemIndex={itemIndex}
selectionMode={SelectionMode.multiple}
group={group}
/>
) : null;
};
return (
<div>
<GroupedList
items={items}
// eslint-disable-next-line react/jsx-no-bind
onRenderCell={onRenderCell}
selectionMode={SelectionMode.multiple}
groups={groups}
/>
</div>
);
};
const GroupedListBasicExampleWrapper = () => <ThemeProvider><GroupedListBasicExample /></ThemeProvider>;
ReactDOM.render(<GroupedListBasicExampleWrapper />, document.getElementById('content'))

change the position of object in array inside other object

in given data every ingredient have its substitute option while I can
select any substitute option for example if I want to change masala
with its substitute output will change the position of substitute with
it's option and output should be given below
i want to replace masala with normal masala
i have to create a function who replace ingredient with it's substitute and interchange the position of both *
input
const oData = [
{ CurryName: 'Chiken', id: 0 },
{
ingredients: [
{
id: 1,
name: 'onion',
property: { color: 'yellow', Quantity: 'half KG', price: 120 },
subOption: [
{
id: 11,
name: 'redOnion',
property: { color: 'red', Quantity: '1 KG', price: 120 },
},
{
id: 12,
name: 'whiteOnion',
property: { color: 'white', Quantity: '2 KG', price: 120 },
},
],
},
{
id: 2,
name: 'oil',
property: { color: 'green', Quantity: 'half LT', price: 120 },
subOption: [
{
id: 21,
name: 'yellowOil',
property: { color: 'yellow', Quantity: '1 LT', price: 120 },
},
{
id: 22,
name: 'olivoOil',
property: { color: 'golden', Quantity: '2 LT', price: 120 },
},
{
id: 22,
name: 'CastrolOil',
property: { color: 'silk', Quantity: '2 LT', price: 170 },
},
],
},
{
id: 3,
name: 'masala',
property: { color: 'gray', Quantity: '1Tspoon', price: 30 },
subOption: [
{
id: 31,
name: 'garamMasala',
property: { color: 'Garam', Quantity: '2Tspoon', price: 30 },
},
{
id: 32,
name: 'chikenMasala',
property: { color: 'green', Quantity: ' 3Tspoon', price: 30 },
},
{
id: 33,
name: 'normalMasala',
property: { color: 'red', Quantity: '5Tspoon', price: 30 },
},
],
},
],
},
];
// in given data every ingredient have it's substitute option while i can select any supstitute option for example if i want to change masala with its substitute output will change the position of substitue with it's option and output should be given below
//i want to replace masala with normal masala
const output = [
{ CurryName: 'Chiken', id: 0 },
{
ingredients: [
{
id: 1,
name: 'onion',
property: { color: 'yellow', Quantity: 'half KG', price: 120 },
subOption: [
{
id: 11,
name: 'redOnion',
property: { color: 'red', Quantity: '1 KG', price: 120 },
},
{
id: 12,
name: 'whiteOnion',
property: { color: 'white', Quantity: '2 KG', price: 120 },
},
],
},
{
id: 2,
name: 'oil',
property: { color: 'green', Quantity: 'half LT', price: 120 },
subOption: [
{
id: 21,
name: 'yellowOil',
property: { color: 'yellow', Quantity: '1 LT', price: 120 },
},
{
id: 22,
name: 'olivoOil',
property: { color: 'golden', Quantity: '2 LT', price: 120 },
},
{
id: 22,
name: 'CastrolOil',
property: { color: 'silk', Quantity: '2 LT', price: 170 },
},
],
},
{
id: 33,
name: 'normalMasala',
property: { color: 'red', Quantity: '5Tspoon', price: 30 },
subOption: [
{
id: 31,
name: 'garamMasala',
property: { color: 'Garam', Quantity: '2Tspoon', price: 30 },
},
{
id: 32,
name: 'chikenMasala',
property: { color: 'green', Quantity: ' 3Tspoon', price: 30 },
},
{
id: 3,
name: 'masala',
property: { color: 'gray', Quantity: '1Tspoon', price: 30 },
}
],
},
],
},
];
console.log(output)
I suggest that define an element before 'subOption' like 'selectedOption' so you can change it more easily between them
{
selectedOption:{id: 33,
name: 'normalMasala',
property: { color: 'red', Quantity: '5Tspoon', price: 30 }},
subOption: [
{
id: 31,
name: 'garamMasala',
property: { color: 'Garam', Quantity: '2Tspoon', price: 30 },
},
{
id: 32,
name: 'chikenMasala',
property: { color: 'green', Quantity: ' 3Tspoon', price: 30 },
},
{
id: 3,
name: 'masala',
property: { color: 'gray', Quantity: '1Tspoon', price: 30 },
}
],
}
if you able to add 'selectedOption' you can use this code
let temp = oData[1].ingredients[3].subOption[3]
oData[1].ingredients[3].subOption[3].splice(3,1,oData[1].ingredients[3].selectedOption)
oData[1].ingredients[3].selectedOption=temp;
This solution may not be ideal because it changes the original data. But if you don't mind changing the original data, use this.
function swapIngredientMainSub(data, mainID, subID) {
const { ingredients } = data[1];
const targetIndex = ingredients.findIndex(({ id }) => id === mainID);
const { subOption, ...main } = ingredients[targetIndex];
const subIndex = subOption.findIndex(({ id }) => id === subID);
const sub = subOption[subIndex];
subOption[subIndex] = main;
ingredients[targetIndex] = { ...sub, subOption };
}
swapIngredientMainSub(oData, 3, 33);
console.log(JSON.stringify(oData) === JSON.stringify(output)); // true
Option 2:
function swapIngredientMainSub(data, subID) {
const { ingredients } = data[1];
const targetIndex = ingredients.findIndex(({ subOption }) =>
subOption.find(({ id }) => id === subID)
);
const { subOption, ...main } = ingredients[targetIndex];
const subIndex = subOption.findIndex(({ id }) => id === subID);
const sub = subOption[subIndex];
subOption[subIndex] = main;
ingredients[targetIndex] = { ...sub, subOption };
}
swapIngredientMainSub(oData, 33);
console.log(JSON.stringify(oData) === JSON.stringify(output)); // true
I don't know about d3 library that you have included in the tags, but you can use something like this:
const oData = [{
CurryName: 'Chiken',
id: 0
},
{
ingredients: [{
id: 1,
name: 'onion',
property: {
color: 'yellow',
Quantity: 'half KG',
price: 120
},
subOption: [{
id: 11,
name: 'redOnion',
property: {
color: 'red',
Quantity: '1 KG',
price: 120
},
},
{
id: 12,
name: 'whiteOnion',
property: {
color: 'white',
Quantity: '2 KG',
price: 120
},
},
],
},
{
id: 2,
name: 'oil',
property: {
color: 'green',
Quantity: 'half LT',
price: 120
},
subOption: [{
id: 21,
name: 'yellowOil',
property: {
color: 'yellow',
Quantity: '1 LT',
price: 120
},
},
{
id: 22,
name: 'olivoOil',
property: {
color: 'golden',
Quantity: '2 LT',
price: 120
},
},
{
id: 22,
name: 'CastrolOil',
property: {
color: 'silk',
Quantity: '2 LT',
price: 170
},
},
],
},
{
id: 3,
name: 'masala',
property: {
color: 'gray',
Quantity: '1Tspoon',
price: 30
},
subOption: [{
id: 31,
name: 'garamMasala',
property: {
color: 'Garam',
Quantity: '2Tspoon',
price: 30
},
},
{
id: 32,
name: 'chikenMasala',
property: {
color: 'green',
Quantity: ' 3Tspoon',
price: 30
},
},
{
id: 33,
name: 'normalMasala',
property: {
color: 'red',
Quantity: '5Tspoon',
price: 30
},
},
],
},
],
},
];
const selectIngredients = (obj, mainName, subName) => {
obj[1].ingredients.map(ingredient => {
if (ingredient.name === mainName) {
const optionIndex = ingredient.subOption.findIndex(element => element.name === subName);
if (optionIndex !== undefined) {
const {
id,
name,
property
} = ingredient;
ingredient.id = ingredient.subOption[optionIndex].id;
ingredient.name = ingredient.subOption[optionIndex].name;
ingredient.property = ingredient.subOption[optionIndex].property;
ingredient.subOption[optionIndex].id = id;
ingredient.subOption[optionIndex].name = name;
ingredient.subOption[optionIndex].property = property;
}
}
});
return obj;
};
console.log(selectIngredients(oData, "masala", "normalMasala"));

Material UI Grid No row with id #undefined

Not sure what I'm doing wrong here, I'm trying the data grid from material, copy pasted the example code from their website:
const columns: GridColDef[] = [
{ field: 'id', headerName: 'ID', width: 90 },
{
field: 'firstName',
headerName: 'First name',
width: 150,
editable: true,
},
{
field: 'lastName',
headerName: 'Last name',
width: 150,
editable: true,
},
{
field: 'age',
headerName: 'Age',
type: 'number',
width: 110,
editable: true,
}
];
const rows = [
{ id: 1, lastName: 'Snow', firstName: 'Jon', age: 35 },
{ id: 2, lastName: 'Lannister', firstName: 'Cersei', age: 42 },
{ id: 3, lastName: 'Lannister', firstName: 'Jaime', age: 45 },
{ id: 4, lastName: 'Stark', firstName: 'Arya', age: 16 },
{ id: 5, lastName: 'Targaryen', firstName: 'Daenerys', age: null },
{ id: 6, lastName: 'Melisandre', firstName: null, age: 150 },
{ id: 7, lastName: 'Clifford', firstName: 'Ferrara', age: 44 },
{ id: 8, lastName: 'Frances', firstName: 'Rossini', age: 36 },
{ id: 9, lastName: 'Roxie', firstName: 'Harvey', age: 65 },
];
const NFTSalesGrid: FunctionalComponent = () => {
return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
rows={rows}
columns={columns}
pageSize={10}
rowsPerPageOptions={[5]}
/>
</div>
)
}
export default NFTSalesGrid;
And I'm receiving this error:
An unexpected error occurred. Error: No row with id #undefined found. Error: No row with id #undefined found

Onclick event on q-table stop working after passing props to template

I got this table I want to color each row in a color depending on my data.
This works but seems to disable my onclick event in q-table for some reason.
#row-click="onRowClick"
I cannot figure out why this is happening. Im new to quasar and to be honest Im not 100% sure how this referens works
v-slot:body="props"
Eventually I want this to be a router event taking me to a different page on click.
<div id="q-app">
<div class="q-pa-md">
<q-table
:data="data"
:columns="columns"
row-key="id"
:filter="filter"
:loading="loading"
:rows-per-page-options="[5]"
#row-click="onRowClick"
>
<!-- If I remove the template here the onRowClick works -->
<template v-slot:body="props">
<q-tr :props="props" :class="tableFormat(props.row)">
<q-td v-for="col in props.cols" :key="col.name" :props="props">{{
col.value
}}</q-td>
</q-tr>
</template>
</q-table>
</div>
</div>
CSS:
.marked-row {
background-color: green;
}
.unmarked-row {
background-color: blue;
}
new Vue({
el: '#q-app',
data () {
return {
loading: false,
filter: "",
rowCount: 10,
columns: [
{
name: "name",
required: true,
label: "Name",
align: "left",
field: "name",
// format: val => `${val}`,
sortable: true
// style: 'width: 500px'
},
{
name: "age",
required: true,
label: "Age",
align: "left",
field: "age",
format: val => `${val}`,
sortable: true
},
{
name: "location",
required: true,
label: "Location",
align: "left",
field: "location",
format: val => `${val}`,
sortable: true
}
],
data: [
{
id: 1,
name: "Diana",
age: 5,
location: "Mumbai",
color: "blue"
},
{
id: 2,
name: "Billy",
age: 4,
location: "Detroit",
color: "green"
},
{
id: 3,
name: "Mimmi",
age: 3,
location: "New York",
color: "green"
},
{
id: 4,
name: "Bengan",
age: 4,
location: "Dubai",
color: "blue"
},
{
id: 5,
name: "Chloe",
age: 7,
location: "Paris",
color: "green"
},
{
id: 6,
name: "Ben",
age: 6,
location: "Los Angeles",
color: "blue"
}
]
}
},
methods: {
tableFormat(val) {
console.log(val)
if (val.color === "blue") {
return "marked-row";
} else {
return "unmarked-row";
}
},
onRowClick(evt, row) {
console.log("clicked on ", row );
}
}
})
Here is my pen:
https://codepen.io/haangglide/pen/MWeRaJW
Doc says
Emitted when user clicks/taps on a row; Is not emitted when using body/row/item scoped slots
So you can use #click event on q-tr
codepen - https://codepen.io/Pratik__007/pen/oNLOogY

Dynamically filtering an array of objects with n filter criteria

I have an array of objects (data), and I need to filter this array based on filter criteria (criteria) where each criteria can have multiple values.
var data = [
{ ID: 1, Name: "John", Color: "Blue", Location: "Up" },
{ ID: 2, Name: "Pauline", Color: "Green", Location: "Up" },
{ ID: 3, Name: "Ahmed", Color: "Orange", Location: "Left" },
{ ID: 4, Name: "Diego", Color: "Pink", Location: "Up" },
{ ID: 5, Name: "Maria", Color: "Black", Location: "Down" },
{ ID: 6, Name: "Gus", Color: "Green", Location: "Up" },
{ ID: 7, Name: "Brian", Color: "Pink", Location: "Left" },
{ ID: 8, Name: "Shelley", Color: "Green", Location: "Right" },
{ ID: 9, Name: "Leonardo", Color: "Blue", Location: "Right" },
{ ID: 10, Name: "Big Daddy", Color: "Green", Location: "Down" }
];
var criteria = [
{ Field: "Color", Values: ["Green"] },
{ Field: "Location", Values: ["Up", "Down"] }
];
I need an array of object (filtered) in such a way that
1. each filter criteria is treated as "AND"
2. multiple filter values in a filter field are treated as "OR". So this is how the output should be:
var filtered = [
{ ID: 2, Name: "Pauline", Color: "Green", Location: "Up" },
{ ID: 6, Name: "Gus", Color: "Green", Location: "Up" },
{ ID: 10, Name: "Big Daddy", Color: "Green", Location: "Down" }
];
You can use Array.every for AND condition and array.indexOf for OR condition.
Note, indexOf is case sensitive. If you want make it case insensitive, you can transform both values to lower case and compare
var data = [
{ ID: 1, Name: "John", Color: "Blue", Location: "Up" },
{ ID: 2, Name: "Pauline", Color: "Green", Location: "Up" },
{ ID: 3, Name: "Ahmed", Color: "Orange", Location: "Left" },
{ ID: 4, Name: "Diego", Color: "Pink", Location: "Up" },
{ ID: 5, Name: "Maria", Color: "Black", Location: "Down" },
{ ID: 6, Name: "Gus", Color: "Green", Location: "Up" },
{ ID: 7, Name: "Brian", Color: "Pink", Location: "Left" },
{ ID: 8, Name: "Shelley", Color: "Green", Location: "Right" },
{ ID: 9, Name: "Leonardo", Color: "Blue", Location: "Right" },
{ ID: 10, Name: "Big Daddy", Color: "Green", Location: "Down" },
{ ID: 11, Name: "Dummy", Color: ["Green", "Orange"], Location: "Down" }
];
var criteria = [
{ Field: "Color", Values: ["Green"] },
{ Field: "Location", Values: ["Up", "Down"] }
];
var result = data.filter(function(obj){
return criteria.every(function(c){
var value = obj[c.Field];
if(typeof value === 'object') {
return Object.keys(value).some(function(key){
return c.Values.indexOf(value[key]) > -1
})
}
else
return c.Values.indexOf(value) > -1
})
})
console.log(result)
Array.some provides true for any match , and false for every mismatch. We expect a false and then negate it, so that our filter criteria for the original data is correct.
filteredData = data.filter(d =>
!(criteria.some(criterion =>
criterion.Values.indexOf(d[criterion.Field]) === -1
))
)

Categories