CSS class dynamicaly added based on JSON value in React - json

I have a JSON value based on percentage. Is there a way add different CSS classes based on it?
E.g. If is 10 to 20% then red. If is 20-30 then orange, till 100%.

Assuming you have a json with an array of item inside, you could do smething like this :
const json = [
{
percent: 10
},
{
percent: 35
},
{
percent: 78
}
];
let myClass = "class1";
const setClass = () => {
json.forEach(item => {
if(item.percent >=10 && item.percent <= 35) myClass = 'class2';
if(item.percent > 35 && item.percent <= 78) myClass = 'class3';
})
}
And then set your class as follow :
<input type="text" value="defaultValue" className={myClass} />

fetchFunction = ()=> {
let jsonValueList=parseInt(jsonData);
this.setState({jsonValue: jsonValueList}); }
_.map(this.state.jsonValue, (item, index) => {
<span key={index} className={ (item <= 100 && item >= 90) ? "colorBlack" : (item < 90 && item >= 80) ? "colorGreen" : "..."}></span>})

Could you maybe provide some more information about the JSON or cases (ranges of percentage) in which you need to apply a class?
I see it like that: you have a few classes that are already defined with various names, and for example you have a JSON array that's mapped in JSX — in each entry of the array you have some percentage value according to which you can apply a class. For example:
const json = {
objects: [
{
id: 1,
label: 'Foo',
percentage: 37,
},
{
id: 2,
label: 'Bar',
percentage: 68
},
{
id: 3,
label: 'Biz',
percentage: 12,
}
]
}
const getClassname = (percentage) => {
if (percentage > 0 && percentage <= 33) {
return 'red'
} else if (percentage > 33 && percentage <= 66) {
return 'yellow'
} else if (percentage > 66 && percentage <= 100) {
return 'green'
}
}
const Component = ({label, percentage}) => {
return (
<div className={getClassname(percentage)}>{label}</div>
)
}
const List = ({list}) => {
return {
list.map(entry => (
<Component
key={entry.id}
label={entry.label}
percentage={entry.percentage}
/>
)
}
}
const App = () => {
return (<List list={json.objects}/>)
}
}

Related

JSON data calculation and re-formate using Angular

I have a JSON file and I am trying to calculate the JSON file key based on the value and reformating it. My JSON file looks like below:
data=[
{
pet:'Cat',
fruit:'Apple',
fish:'Hilsha'
},
{
pet:'Dog',
fish:'Carp'
},
{
pet:'Cat',
fruit:'Orange',
fish:'Lobster'
}
];
I do like to calculate and formate it like below:
data=[
{
label:'Pet',
total:3,
list:[
{
name:'Cat',
value: 2,
},
{
name:'Dog',
value: 1,
}
]
},
{
label:'Fruit',
total:2,
list:[
{
name:'Apple',
value: 1,
},
{
name:'Orange',
value: 1,
}
]
},
{
label:'Fish',
total:3,
list:[
{
name:'Hilsha',
value: 1,
},
{
name:'Carp',
value: 1,
},
{
name:'Lobster',
value: 1,
}
]
},
];
If anybody can help me, it will be very help for me and will save a day.
I have fixed this task myself. If I have any wrong, you can put your comment fill-free :)
``
ngOnInit(): void {
this.dataService.$data.subscribe(data => {
// Create new object and calculation according to category
let petObj: any = {}
let fruitObj: any = {}
let fishObj: any = {}
data.forEach((el: any) => {
if (el.pet != undefined) {
petObj[el.pet] = (petObj[el.pet] || 0) + 1;
}
if (el.fruit != undefined) {
fruitObj[el.fruit] = (fruitObj[el.fruit] || 0) + 1;
}
if (el.fish != undefined) {
fishObj[el.fish] = (fishObj[el.fish] || 0) + 1;
}
});
// Create list according to category
let pet_list: any = [];
let fruit_list: any = [];
let fish_list: any = [];
for (var key in petObj) {
let pet = {
label: key,
value: petObj[key]
}
pet_list.push(pet)
}
for (var key in fruitObj) {
let fruit = {
label: key,
value: fruitObj[key]
}
fruit_list.push(fruit)
}
for (var key in fishObj) {
let fish = {
label: key,
value: fishObj[key]
}
fish_list.push(fish)
}
// Calculate total sum according to category
var totalPet = pet_list.map((res: any) => res.value).reduce((a: any, b: any) => a + b);
var totalFruit = fruit_list.map((res: any) => res.value).reduce((a: any, b: any) => a + b);
var totalFish = fish_list.map((res: any) => res.value).reduce((a: any, b: any) => a + b);
// Rearrange the JSON
this.rearrangeData = [
{
label: 'Pet',
total: totalPet,
list: pet_list
},
{
label: 'Fruit',
total: totalFruit,
list: fruit_list
},
{
label: 'Fish',
total: totalFish,
list: fish_list
}
]
console.log(this.rearrangeData)
// End rearrange the JSON
});
}
``
You can simplify your function. Take a look this one
group(oldData) {
const data = []; //declare an empty array
oldData.forEach((x) => {
//x will be {pet: 'Cat',fruit: 'Apple',fish: 'Hilsha'},
// {pet: 'Dog',fish: 'Carp'}
// ...
Object.keys(x).forEach((key) => {
//key will be 'pet','fruit',...
const item = data.find((d) => d.label == key); //search in the "data array"
if (item) { //if find it
item.total++; //add 1 to the property total of the element find it
// and search in the item.list the 'Cat'
const list = item.list.find((l) => l.name == x[key]);
//if find it add 1 to the property value of the list
if (list)
list.value++;
else
//if not, add to the list
//an object with property "name" and "value" equal 1
item.list.push({ name: x[key], value: 1 });
} else
//if the element is not in the "array data"
//add an object with properties label, total and list
//see that list is an array with an unique element
data.push({
label: key,
total: 1,
list: [{ name: x[key], value: 1 }],
});
});
});
return data;
}
You can use like
this.dataService.$data.subscribe(data => {
this.rearrangeData=this.group(data)
}
NOTE: this function the labels are 'pet','fruit' and 'fish' not 'Pet', 'Fruit' and 'Fish'
Did you try reading the text leading up to this exercise? That'd be my first approach. After that, I'd use reduce. You can do pretty much anything with reduce.

Getting usable numbers from Nested Array Json

My data that I'm given is formulated like the following. I'm struggling to get any usable data out of it using reduce or map
const data = [
{
id: 25,
status: 1,
description: "No Description",
length: 4,
data: [
{
id: 43,
comment: "Comment1",
eventTimestamp: 1541027189000,
intensity: 29
},
{
comment: "Comment2",
eventTimestamp: 1541027191000,
intensity: 33
},
{
id: 45,
comment: "Comment3",
eventTimestamp: 1541027193000,
intensity: 30
}
],
tTypes: [
{
id: 3,
label: "Johnny",
certainty: "TEST",
comment: "Test Purposes Only",
icon: "bottle",
number: 0
}
]
}
];
I've tried flatting, I've tried iterating the JSON twice and I just seem to end up with either "NaN" or Undefined. I'd like to be able to order them in time order (using time stamp), get the mix/max/ave from the intensity values and more. I have that figured out for the length which is a level higher, but just can't seem to figure out the rest. Can someone point me in the right direction?
export default function App() {
let tTypesArray = data.map((a) => a.tTypes);
let Walker = tTypesArray.reduce((a, tTypes) => tTypes.label === "Johnny" ? ++a : a, 0);
console.log(Walker);
console.log(tTypesArray[0].label);
console.log([].concat(...data)
.map(data => data.tTypes.number)
.reduce((a, b) => a + b))
console.log([].concat(...data).reduce((a, { tTypes: { id }}) => id, 0))
return <div className="App">ARG!</div>;
}
Are some of the examples I've tried.
https://codesandbox.io/s/purple-cache-ivz1y?file=/src/App.js
Is the link to the sandbox.
What I understood from you question is that you need to loop data and for each element in data you want to extract values and do some calculations.
First you need to loop your data input. I will use Array.forEach:
data.forEach(element => { ... })
Now that we have a loop we can access each element property and extract the information we want. For instance lets say you want to sort the comments by timestamp in ascending order:
const sortedComments = element.data.sort((a, b) => a.eventTimestamp - b.eventTimestamp);
console.log(sortedComments)
Now let's say you want the min, max, and average intensity from the comments. There are several ways to get it. Here is an algorithm for that:
let min = Infinity;
let max = -Infinity;
let sum = 0;
for(comment of sortedComments) {
if(comment.intensity < min) {
min = comment.intensity;
}
if(comment.intensity > max) {
max = comment.intensity;
}
sum += comment.intensity;
}
const avg = sum / sortedComments.length;
console.log({min, max, avg})
Putting it all together:
const data = [
{
id: 25,
confirmationStatus: 1,
description: "No Description",
length: 4,
data: [
{
id: 43,
comment: "Comment1",
eventTimestamp: 1541027189000,
intensity: 29
},
{
comment: "Comment2",
eventTimestamp: 1541027191000,
intensity: 33
},
{
id: 45,
comment: "Comment3",
eventTimestamp: 1541027193000,
intensity: 30
}
],
tTypes: [
{
id: 3,
label: "Johnny",
certainty: "TEST",
comment: "Test Purposes Only",
icon: "bottle",
number: 0
}
]
}
];
data.forEach(element => {
const sortedComments = element.data.sort((a, b) => a.eventTimestamp - b.eventTimestamp);
console.log(sortedComments);
let min = Infinity;
let max = -Infinity;
let sum = 0;
for(comment of sortedComments) {
if(comment.intensity < min) {
min = comment.intensity;
}
if(comment.intensity > max) {
max = comment.intensity;
}
sum += comment.intensity;
}
const avg = sum / sortedComments.length;
console.log({min, max, avg});
let walker = element.tTypes.reduce(
(a, tType) => (tType.label === "Johnny" ? ++a : a), 0
);
console.log(walker)
});
I hope it puts you in the right direction.

How to find the object in an array where particular object value is max

Hi Below is the JSON array of ojects
[
{
"BookingId": 366024,
"BookingDetailId": 340708,
"JobCode" : 13
},
{
"BookingId": 366023,
"BookingDetailId": 340707,
"JobCode" : 12
},
{
"BookingId": 366022,
"BookingDetailId": 340706,
"JobCode" : 12
}
]
I want to get particular array object where BookingId is Max where JobCode is 12, for eg. In above array I want object {
"BookingId": 366023,
"BookingDetailId": 340707,
"JobCode" : 12
} whose BookingId is max and JobCode is 12.
How to do it in angular 6
tried code
var a = this.GridSource.find(x => x.JobCode == 12 &&
x.BookingId == Math.max.apply(Math, this.GridSource.map
(function(o) { return o.BookingId; })));
You can use reduce for this. I did an example below, hope this helps. If were are no items that meet conditions, then result of reduce will be null
Also, don't forget about the types :)
interface GridItem {
BookingId: number;
BookingDetailId: number;
JobCode: number;
}
const GridSource: GridItem[] = [
{
BookingId: 366024,
BookingDetailId: 340708,
JobCode: 13
},
{
BookingId: 366023,
BookingDetailId: 340707,
JobCode: 12
},
{
BookingId: 366022,
BookingDetailId: 340706,
JobCode: 12
}
];
const foundGridItem: GridItem = GridSource.reduce(
(result: GridItem, value: GridItem) =>
value.JobCode === 12 &&
(result === null || value.BookingId > result.BookingId)
? value
: result,
null
);
You can make use of reduce to find the max element and then using it in find.
var max = array.reduce(function(prev, curr) {
return prev['BookingId'] > curr['BookingId'] ? prev : curr;
});
var elem = array.find(x => x['JobCode'] == 12 && x['BookingId'] == max['BookingId']);

I have an issue with circular reference to JSON using reactjs

I want to serialize circular reference to JSON
This is the part generating the JSON array and it causes a circular reference because it creates a child inside an element and I want to display the result.
const mappedData = this.state.treeData
.filter(data => data.title === "Category")
.map(categ => {
const { id, title, children, subtitle, type } = categ;
function getChildren(children) {
return children
? children.map(child => {
if (child.title === "Item" || child.title === "Group") {
const data = {
id: child.id,
name: child.subtitle,
type: child.type,
children: getChildren(child.children),
child_id: child.children
? child.children.map(child => child.id)
: []
};
if (data.children.length === 0) delete data.children;
if (data.child_id.length === 0) delete data.child_id;
return data;
} else {
return {
id: child.id,
name: child.subtitle,
type: child.type
};
}
})
: [];
}
const data = {
id: id,
name: subtitle,
type: type,
children: getChildren(children),
child_id: children ? children.map(child => child.id) : []
};
if (data.children.length === 0) delete data.children;
if (data.child_id.length === 0) delete data.child_id;
return data;
});
The HTML part that calls the stringify method
<div className="json">
<p> {JSON.stringify(mappedData)}</p>
</div>
I found a Replacer that it works but the JSON result is too long for what I need
const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
};
JSON.stringify(circularReference, getCircularReplacer());
And here's the result :
[{"id":"7a69fc68","name":{"type":"input","key":null,"ref":null,"props":{"className":"inputSubs","type":"text","placeholder":"Category Name"},"_owner":{"tag":1,"key":null,"stateNode":{"props":{},"context":{},"refs":{},"updater":{},"notificationAlert":{"current":{"props":{},"refs":{"notifications":{"__reactInternalInstance$6qqi1p3qi9b":{"tag":5,"key":null,"elementType":"div","type":"div","return":{"tag":1,"key":null,"return":{"tag":5,"key":null,"elementType":"div","type" .. etc
Any Help ?

React/JSX - iterating JSON object & nest every X items in .row

There must be an easy answer to this but I can't seem to find one.
JSON: -
{
1: {
'desc' : 'desc1',
'title' : 'title 1',
},
2: {
'desc' : 'desc2',
'title' : 'title 2',
},
3: {
'desc' : 'desc3',
'title' : 'title 3',
},
4: {
'desc' : 'desc4',
'title' : 'title 4',
},
5: {
'desc' : 'desc5',
'title' : 'title 5',
},
6: {
'desc' : 'desc6',
'title' : 'title 6',
},
};
So basically I want to iterate this object and have every 3 items nest in a .row class div like this: -
<div class='row'>
<div>desc1 : title1</div>
<div>desc2 : title2</div>
<div>desc3 : title3</div>
</div>
<div class='row'>
<div>desc4 : title4</div>
<div>desc5 : title5</div>
<div>desc6 : title6</div>
</div>
Now I understand how I can simple render() this in a component: -
{
Object.keys(JSONObject).map(key => <TheComponent key={key} details={JSONObject[key]} />)
}
However, I am stumped as to how I can split this into 2 rows of 3 items and nest each of the 3 items in the .row div.
Any help greatly appreciated. I am relatively new to ES6/ReactJS and eager to get past the teething problems.
One way of looking at this is to split the array up first into chunks, then working with that.
So you could get your initial array;
var ar1 = Object.keys(JSONObject);
Then chunk it up
var ar2 = [];
var i, j, chunk = 3;
for (i = 0, j = ar1.length; i < j; i += chunk) {
ar2.push(ar1.slice(i, i+chunk));
}
This will then give you ar2 which is an array of arrays. You could then either loop through this and output the level one array with the rows, then the level 2 array with the inner html.
See this basic bit of code on jsbin to demo the chunking
let arrTheComponent = [], arrJson = [];
Object.keys(JSONObject).map(key => {
arrJson.push(JSONObject[key]);
if (arrJson.length === 3) {
arrTheComponent.push(<TheComponent json={arrJson} />);
arrJson = [];
}
})
Display the component
export const TheComponentList = () => {
let arrTheComponent = [], arrJson = [];
Object.keys(JSONObject).map(key => {
arrJson.push(JSONObject[key]);
if (arrJson.length === 3) {
arrTheComponent.push(<TheComponent json={arrJson} />);
arrJson = [];
}
})
return (<div>
{arrTheComponent}
</div>);
}
I did something very similar, so here is the code I used:
let rowCount = 0;
let rows = [];
Object.keys(JSONObject).forEach((k, i) => {
// this just makes sure there is always an array initialised
rows[rowCount] = rows[rowCount] || [];
// now we add into the current row a component
rows[rowCount].push(
<TheComponent
key={k}
details={JSONObject[key]}
/>
);
if ((i + 1) % 3 === 0) { // the 3 here is how many items you want per row!!
// if we can perfectly divide the current position by 3
// we have filled a row, so now increment the row
rowCount++;
}
});
This will give you an array of arrays:
[
[ <TheComponent key=1 />, <TheComponent key=2 /> <TheComponent key=3 /> ]
[ <TheComponent key=4 /> ... ]
[ .... ]
]
Then you can render like this:
render() {
const rows = this.groupRows(); // this is the function above
// ar below is a single array of <TheComponent ... /> so looks like:
// [ <TheComponent ... />, ... ]
return (
<div>
{ rows.map((ar, i) => <div className="row"> { ar } </div>) }
</div>
);
}
Addendum
I actually created a component to do this for me, so I could use it like so:
render() {
return (
<Grouper>
{ Object.keys(JSONObject).map(k => <TheComponent key={k} details={ JSONObject[key] } />) }
</Grouper>
);
}
And what the <Grouper /> component did was React.Children.forEach(...) grouping them using the code I have above. Which meant all that component scaffolding code was nicely abstracted away from the business view logic.