I have a react page and one of my inputs is a file upload. When loading, I want to read in the file (it's JSON) and then show the file as a tree to allow my users to select nodes (rules) to run against another dataset. BUT, when I pick the JSON file and the 'onload' event handler actually fires off, the page just stops rendering, I get a blank screen. I'm not sure why, I can't see any errors, but I AM IGNORANT with react and kinda new with javascript as well. So, this is quite likely just a dumb thing I'm doing. Can someone point me at what I'm doing wrong here?
handleRules(event) {
const ruleRdr = new FileReader();
ruleRdr.onload = async (e) => {
const rBuf = (e.target.result);
const rData = JSON.parse(new TextDecoder().decode(rBuf));
// the data is there, but it's not mapping into the tree...!?!?!?
const tree = {
name: "QA/QC Rules",
id: 1,
toggled: true,
children: rData.map((wFlow, index) => ({
name: wFlow.WorkflowName,
id: index,
children: wFlow.Rules.map((rule, idx) => ({
name: rule.RuleName,
id: idx
}))
}))
};
this.setState({ ruleData: rData, hasRules: true, treeData: tree });
}
ruleRdr.readAsArrayBuffer(event.target.files[0]);
}
EDIT #1: I don't think it's the code above now, I think it might be my tree library (react-treebeard) or my ignorance on how I'm using it. The code produces what I think is useable data, but it isn't rendering it out.
{
"name": "QA/QC Rules",
"id": 1,
"toggled": true,
"children": [
{
"name": "COMP",
"id": 0,
"children": [
{
"name": "ParentMustHaveCat",
"id": 0
},
{
"name": "ParentMustHaveMfg",
"id": 1
},
{
"name": "ParentMustHaveFamily",
"id": 2
},
{
"name": "SymbolsMustHaveFamily",
"id": 3
}
]
},
{
"name": "PNLCOMP",
"id": 1,
"children": [
{
"name": "ParentMustHaveCat",
"id": 0
},
{
"name": "ParentMustHaveMfg",
"id": 1
},
{
"name": "ParentMustHaveFamily",
"id": 2
},
{
"name": "SymbolsMustHaveFamily",
"id": 3
}
]
},
{
"name": "PNLTERM",
"id": 2,
"children": [
{
"name": "ParentMustHaveCat",
"id": 0
},
{
"name": "ParentMustHaveMfg",
"id": 1
},
{
"name": "ParentMustHaveFamily",
"id": 2
},
{
"name": "SymbolsMustHaveFamily",
"id": 3
}
]
}
]
}
I figured it out. I switched to MUI since it has more components that I will want to use anyway. I got a similar issue with it as well and realized that I have duplicate IDs between the parent and the children, and was creating a kind of lock when trying to compare parent and child IDs in the MUI library. Totally on me - I'm dumb.
Related
I am trying to export nested json to excel with specific format in react. I found few solution with XLSX which print only root node but I would also like to print nested nodes. Here is my JSON
[
{
"Root":"00000",
"RootId":"b597b7be58b0",
"Index":0,
"Child":[
{
"ChildId":"48bb0b4be689",
"Name":"Dimension",
"Index":0,
"SubChild0":[
{
"SubChildId":"6b620696cf35",
"Label":"Sample 2",
"Index":1
},
{
"SubChildId1":"f6b620696cf38",
"Label":"Sample 2",
"Index":2
}
]
},
{
"ChildId-01":"dcf70d3a-60b3-4b8c-8740-48bb0b4be689",
"Name":"Weight",
"Index":0,
"SubChild1":[
{
"SubChildId":"f42d99f5-37c5-4ea3-8425-6b620696cf35",
"Label":"Sample 2",
"Index":1
},
{
"SubChildId1":"f42d99f5-37c5-4ea3-8425-6b620696cf35",
"Label":"Sample 2",
"Index":2
}
]
}
]
}
]
and I would like to print in excel something like below format
I've never used any libraries that would help with your problem so cannot suggest any.
Your source data can be processed using javascript.
Your data almost fits a regular nested list with children, so creating a recursive function to process the data into something that can be interpreted as a CSV shouldn't be too difficult.
Your data has different tags so is a little more complicated.
The example below wont work for your data as-is. But it might give you an idea of where to start?
// source data with uniform keys in child objects
let data = [
{
"name": "root1",
"label": "root label",
"children": [
{
"name": "root1child1",
"label": "root1 child1 label",
"children": [
{
"name": "root1child1subchild1",
"label": "root1 child1 subchild1 label"
},
{
"name": "root1child1subchild2",
"label": "root1 child1 subchild2 label"
}
]
},
{
"name": "root1child2",
"label": "my label",
"children": [
{
"name": "root1child2subchild1",
"label": "root1 child2 subchild1 label"
},
{
"name": "root1child2subchild2",
"label": "root1 child2 subchild2 label"
}
]
}
]
}
]
let result = []
function process(node,padding) {
for (let i = 0, l = node.length; i<l; i++) {
result.push(Array(padding).concat("name", node[i].name))
result.push(Array(padding).concat("label", node[i].label))
if (node[i].children) {
// process the child node and pad the result to the right
process(node[i].children,++padding)
}
// reset padding and continue with next
--padding
}
}
// start processing the data
process(data,0)
// print the result as a table to the console
console.table(result)
In my front-end I am trying to map through nested objects which is coming from back-end Laravel collection:
[
{
"id": 1,
"name": "Chips",
"product_categories_id": 1,
"category": {
"id": 1,
"category": "Chips",
"brand": "Bombay Sweets"
}
},
{
"id": 2,
"name": "Book",
"product_categories_id": 2,
"category": {
"id": 2,
"category": "Shoe",
"brand": "Nike",
}
}]
I want to display the product name and related category name from nested object. My approach is:
products.map((product)=>{
console.log(product.name)
product.category.map((category)=>(
console.log(category.category)
))
})
which is not working at all. I spent huge amount of time to solve yet no luck.
the error it shows:
ProductListContainer.js:58 Uncaught TypeError: item.category.map is not a function
map method works only with Array. You can use product.category.category to access the value.
Finally solved by this:
products.map((product) => {
console.log(product.name)
Object.entries(product.category).map(() => (
console.log(product.category.category, product.category.brand)
))
})
I've been trying for days to figure out the best approach and also how to make it work. I'm building a product page and each variation options is built dynamically (size, color) based on the GraphQL response it gets back. I'm used to simpler array checking but this one has me baffled and at a lost for even where to start.
So when a user clicks on "M" and "Red" it takes those values and stores them into state
// State Setup
const [variations, setVariations] = useState({});
// Set Variations State that was selected
function productVariationsHandler(event) {
setVariations({ ...variations, [event.target.name]: event.target.value });
}
// State Object after user has made their selections
{
"variations": {
"color": "Red",
"size": "XL"
}
}
I'm trying to take those user selected state variables ("Red", "XL") and match them to the GraphQL response in the variations object to get the databaseId and regularPrice
// GraphQL Response
{
"variations": {
"nodes": [
{
"attributes": {
"nodes": [
{
"attributeId": 237,
"name": "pa_color",
"value": "True Royal"
},
{
"attributeId": 220,
"name": "pa_size",
"value": "S"
}
]
},
"databaseId": 1846,
"regularPrice": "$24.95",
"salePrice": null,
"status": "publish"
},
{
"attributes": {
"nodes": [
{
"attributeId": 237,
"name": "pa_color",
"value": "Red"
},
{
"attributeId": 221,
"name": "pa_size",
"value": "XL"
}
]
},
"databaseId": 1847,
"regularPrice": "$24.95",
"salePrice": null,
"status": "publish"
}
]
}
}
I've tried using the find method and as well as map and even tried for as seen below but without avail
// My Failed Attempt
// Find the Variation based on user selected options
function findVariationProduct() {
for (const key in variations) {
product.variations.nodes.map((variation) => {
const variationProduct = variation.attributes.nodes.find(
({ value, name }) => {
if (name == `pa_${key}` && value == variations[key]) {
console.log(variationProduct);
}
}
);
});
}
}
Any help would be greatly appreciated!
I have two arrays of object, the first array (printers, around 80 elements) is made of the following type of objects:
[{
printerBrand: 'Mutoh',
printerModel: 'VJ 1204G',
headsBrand: 'Epson',
headType: '',
compatibilty: [
'EDX',
'DT8',
'DT8-Pro',
'ECH',
],
cartridges: [],
},
....
]
The second array (cardridges, around 500 elements) is made of the following type of objects:
[
{
"customData": {
"brand": {
"value": {
"type": "string",
"content": "ECH"
},
"key": "brand"
},
"printer": {
"value": {
"type": "string",
"content": "c4280"
},
"key": "printer"
}
},
"name": "DT8 XLXL",
"image": {
"id": "zLaDHrgbarhFSnXAK",
"url": "https://xxxxxxx.net/images/xxxxxx.jpg"
},
"brandId": "xxxxx",
"companyId": "xxxx",
"createdAt": "2018-03-26T14:39:47.326Z",
"updatedAt": "2018-04-09T14:31:38.169Z",
"points": 60,
"id": "dq2Zezwm4nHr8FhEN"
},
...
]
What I want to do first is to is to iterate through the first array and and then iterate for all the cardridge available: if a the value customData.brand.value of a cardridge is included inside the array 'compatibility' of a printer, then I have to add this cardridge object inside the cardridges array of this printer. I have tried but somehow the iteration doesn't take place correctly. This is what I tried:
printers.forEach((printerItem) => {
const printer = printerItem;
printer.compatibilty.forEach((compatibilityItem) => {
const compatibility = compatibilityItem;
cardridges.forEach((cartridge) => {
if (compatibility === cartridge.customData.brand.value.content) {
printer.cartridges.push(cartridge);
}
});
});
});
What am I doing wrong?
You're accessing the wrong property. It should be cartridge.customData.brandName.value.content, carefully note brandName.value rather than brand.value
Your issue is that you're accessing it by the wrong property - brand and not brandName.
Furthermore, if you're targeting everything but IE, you could simplify your nested for loops to utilize some fancy ES6 array methods.
printers.forEach((p) => {
p.cartridges.push(cartridges.filter((c) => {
const brandName = c.customData.brandName.value.content;
return p.compatibilty.includes(brandName);
}));
});
Moving from D3 to Highcharts and this is eluding me. I have a fairly complex object that contains a clickthrough object which needs to be accessed in a function on a point click in the series. I'm creating the series array with the data and name just fine with a small conversion, but I need to attach this object to the data points as well. No idea how.
Quick example. original data:
[
{
"key": "Super Cool Thing",
"format": ".2f",
"values": [
{
"label": "01",
"value": 9.5,
"format": ".2f",
"order": 0,
"tooltip": "numerator = 133, denominator = 14",
"clickthrough": {
"output_format": "json",
"metrics": "",
"options": {
"columns": [
{
"order": 1,
"display_as": "Brand",
"format": "{0}",
"name": "brand",
"data_type": "string"
},
{
"order": 2,
"display_as": "Last Submit Time (Month)",
"format": "%m",
"name": "last-submit-time-month",
"data_type": "datetime"
},
{
"order": 3,
"display_as": "Agent Things",
"format": "{0}",
"name": "agent-thing-values",
"data_type": "string"
}
]
},
"cut_y": "brand",
"type": "",
"filter": { },
"cut_x": "last-submit-time-month"
},
"metrics": [
{
"name": "Agent - Feel Appreciated Mean",
"slug": "qcustomersatr4-mean"
}
]
}
]
}
]
run through a (super quick POC) funct:
for(let i = 0; i < data.length; i++){
var values = [];
var xcuts = [];
data[i].values.forEach(val => {
values.push(val.value);
xcuts.push(val.label);
});
chart.addSeries({
name: data[i].key,
data: values
})
chart.xAxis[0].setCategories(xcuts);
}
and this all works fine. But I need the clickthrough object so I can do something like:
plotOptions: {
series: {
allowPointSelect: true,
cursor: 'pointer',
point: {
events: {
click: function (event) {
console.log('CLICKTHROUGH DATA HERE');
console.log(event.point);
}
}
}
},
},
I'm unsure how to format the series data to include additional data that's accessible in an event function later down the line. I currently do this via d3 and it's fine, but am struggling with the Highcharts method to do the same. It seems I can't just add whatever I want to the series or data, so is this possible?
Have it. I have to set the y value explicitly and then I can add whatever else which is then avail in the event.
example:
data[i].values.forEach(val => {
values.push({link: val.clickthrough, y:val.value});
xcuts.push(val.label);
});
chart.addSeries({
name: data[i].key,
data: values
})