How to render a complex JSON array of array in React - html

I am new to React JS, I want to render this JSON containing Category and list of items below that category. Consider state.miData has this array response from server. It has category and list of menu items under that category. I want to show it in UI like Category and under that category list of items those fall in that category.
[
{
"category": {
"name": "Pasta",
"id": "P1"
},
"items": [
{
"menuItemId": "1",
"menuItemName": "Alfredo-Pasta"
},
{
"menuItemId": "2",
"menuItemName": "Macroni-Pasta"
}
]
},
{
"category": {
"name": "Burger",
"id": "B1"
},
"items": [
{
"menuItemId": "2",
"menuItemName": "UB-Burger"
},
{
"menuItemId": "1",
"menuItemName": "Thela-Mela-Burger"
}
]
}
]
I have written this code in render function but its not working.
const data = this.state.miData
const listItems = data.map((d) =>
<div>
<p key={d.category.id}>{d.category.name}</p>
<ul>
d.items.map((mi) =>
<li>{mi.menuItemName}</li>
);
</ul>
</div>
);
return (
<div>
{listItems}
</div>
);
Thanks in advance.

Try wrapping up the map for the list item in the curly braces.
<ul>
{
d.items.map((mi) =>
<li>{mi.menuItemName}</li>
);
}
</ul>

Related

How do i acess/map the name field of cities array inside the cities array in following json in dart/flutter

{
"cities": [
{
"cities": [
{
"name": "Adilabad",
},
{
"name": "Afjalpur",
},
]
},]
}
I am using Bloc pattern and trying to load the data in sugestions of SearchField.
I can access cities array like this -> state.cities.map((e) => e.city).toList();
but how can i access the name inside the array
You can do the following to get the city name.
Map map = {
"cities": [
{
"cities": [
{
"name": "Adilabad",
},
{
"name": "Afjalpur",
},
]
},
]
}; //ยดยด
final cities = map['cities'][0]['cities'];
print(map['cities'][0]['cities']); // [{name: Adilabad}, {name: Afjalpur}]
print(cities[0]['name']); // Adilabad

Exclude Empty association array using Sequelize

I have a menus table with a one-to-many self association so basically structure is like
---Menu
|
'--submenu
|
'--submenu
---secondMenu
|
'--submenu
|
'--submenu
|
'--submenu
---thirdMenu
Consider the third menu that does not have any submenu. In that case I want the submenu field to be null or this field should not be attached. I get results like
"menu": [
{
"name": "Settings",
"id": 37,
"slug": "Settings-ecom",
"url": "/Settings",
"submenu": [
{
"name": "Settings-child1",
"id": 38,
"slug": "Settings-ecom-child1",
"url": "/Settings-child1",
"submenu": [
{
"name": "Settings-child1-child1",
"id": 40,
"slug": "Settings-ecom-child1-child1",
"url": "/Settings-child1-child1",
"submenu": []
}
]
}
]
},
{
"name": "Dashboard",
"id": 30,
"slug": "dashboard-ecommerce",
"url": "/dashboard",
"submenu": []
}
]
consider the submenu=[] part in the result, what I need is that when there is no submenu it should not return submenu = [] . either it should exclude submenu or it should be something like submenu = null
below is my query to get menus
const menu = await Menu.findAll({
where: {parent_id: null},
attributes: Constants.attributes,
include: [
{
model: Menu,
as: 'submenu',
attributes: Constants.attributes,
include: [
{
model: Menu,
as: 'submenu',
attributes: Constants.attributes,
},
],
},
],
});
and finally the association is like
menu.hasMany(models.menu, {
as: 'submenu',
foreignKey: 'parent_id',
useJunctionTable: false,
});
Thanks for looking over my question :)
Ok so I found a solution, that is to recursively delete empty submenu object from the final result. Hope it might help someone
cleanMenusObject = async (menuToUpdate) => {
for (let menu of menuToUpdate) {
if (menu.dataValues.submenu) {
if (!menu.dataValues.submenu.length) {
delete menu.dataValues.submenu;
} else {
await cleanMenusObject(menu.dataValues.submenu);
}
}
}
};

ReactJS Display API in Component

I am new to react. I am using an api in the form of
{
"category": "dogs",
"available": [
{
"name": "pedro",
"breed": "chihuahua"
},
{
"name": "roxane"
"breed": "beagle"
}
]
},
{
"category": "cat",
"available": [
{
"name": "garfield",
"breed": "tobby"
}
]
}
I want to display ALL the pets available from the same category in name-breed pairs.
Example: Display all dogs
Pedro
Chihuahua
Roxane
Beagle
but that array is giving me hard times.
Attempt
App.jsx
{this.state.data.map((availablePets, i) => <Content key = {i} data = {Content} />)}
Content.jsx
{this.props.data.available[WhatDoIPutHere?].name}
{this.props.data.available[ajsnxnnx].breed}
Is there another way to display ALL the available pets from the same category in name-breed pairs?
SOLVED
{this.props.data.faqs.map((QA,i) =>
<div key={i}>
<h4>{this.props.data.category[i].name}</h4>
<p>{this.props.data.category[i].breed}</p>
</div>
)}
Your solution is not dynamic.
This will be a better solution.
{
this.props.data.faqs.map((QA,i) => {
const pets = QA.available.map((pets, j) => {
return <div key={j}
<h4>{pets.breed}</h4>
<p>{pets.name}</p>
</div>
})
return <div key={i}>
<h4>{QA.category}</h4>
{pets}
</div>
})
}

How do I use knockout to bind nested foreach loops on dynamically added properties?

I have a collection of items. The items are broken down into "types" and then further divided within the type into "categories". I do not know the names of the "types" or the "categories" before hand.
I would like to do some nested foreach binding to represent the data hierarchically. Something like this:
<ul data-bind="foreach: OrderItems.Types">
<li>
ItemType: <span data-bind='text: $data'></span>
<ul data-bind="foreach: Categories">
<li>
Category: <span data-bind='text: $data'></span>
<ul data-bind="foreach: OrderItems">
<li>
Item: <span data-bind="text: Name"> </span>
</li>
</ul>
</li>
</ul>
</li>
var order = {
"OrderNumber": "394857",
"OrderItems": {
"Types": {
"Services": {
"Categories": {
"carpet cleaning": {
"OrderItems": [
{
"OrderItemID": "9d398f88-892c-11e3-8f31-18037335d26a",
"Name": "ARug-Oriental Rugs (estimate on site)"
},
{
"OrderItemID": "9d398f53-892c-11e3-8f31-18037335d26a",
"Name": "C1-Basic Cleaning (per room)"
},
{
"OrderItemID": "9d398f54-892c-11e3-8f31-18037335d26a",
"Name": "C2-Clean & Protect (per room)"
},
{
"OrderItemID": "9d398f55-892c-11e3-8f31-18037335d26a",
"Name": "C3-Healthy Home Package (per room)"
}
]
},
"specialty": {
"OrderItems": [
{
"OrderItemID": "9d398f8f-892c-11e3-8f31-18037335d26a",
"Name": "SOTHR-Other"
}
]
},
"tile & stone": {
"OrderItems": [
{
"OrderItemID": "9d398f8e-892c-11e3-8f31-18037335d26a",
"Name": "TILE-Tile & Stone Care"
}
]
},
"upholstery": {
"OrderItems": [
{
"OrderItemID": "9d398f7b-892c-11e3-8f31-18037335d26a",
"Name": "U3S1-Upholstery - Sofa (Seats 3: 7 linear feet)"
},
{
"OrderItemID": "9d398f7c-892c-11e3-8f31-18037335d26a",
"Name": "U3S2-Upholstery - Sofa - Clean & Protect (Seats 3: 7 linear feet"
}
]
}
}
},
"Products": {
"Categories": {
"carpet cleaning": {
"OrderItems": [
{
"OrderItemID": "9d398f84-892c-11e3-8f31-18037335d26a",
"Name": "PLB-Leave Behind Item"
}
]
}
}
}
}
}
};
var viewModel = ko.mapping.fromJS(order);
ko.applyBindings(viewModel);
here's a fiddle with the above code: http://jsfiddle.net/mattlokk/6Q5f7/5/
To bind against your structure, you would need to turn the objects into arrays. Given that you are using the mapping plugin, the easiest way would likely be to use a binding that translates an object with properties to an array of key/values.
Here is a sample binding:
ko.bindingHandlers.objectForEach = {
init: function(element, valueAccessor, allBindings, data, context) {
var mapped = ko.computed({
read: function() {
var object = ko.unwrap(valueAccessor()),
result = [];
ko.utils.objectForEach(object, function(key, value) {
var item = {
key: key,
value: value
};
result.push(item);
});
return result;
},
disposeWhenNodeIsRemoved: element
});
//apply the foreach bindings with the mapped values
ko.applyBindingsToNode(element, { foreach: mapped }, context);
return { controlsDescendantBindings: true };
}
};
This will create a computed on-the-fly that maps the object to an array of key/values. Now you can use objectForEach instead of foreach against your objects.
Here is a basic sample: http://jsfiddle.net/rniemeyer/nn3jg/ and here is an example with your fiddle: http://jsfiddle.net/rniemeyer/47Wbe/

Loading TreeStore with JSON that has different children fields

I am having a JSON data like below.
{
"divisions": [{
"name": "division1",
"id": "div1",
"subdivisions": [{
"name": "Sub1Div1",
"id": "div1sub1",
"schemes": [{
"name": "Scheme1",
"id": "scheme1"
}, {
"name": "Scheme2",
"id": "scheme2"
}]
}, {
"name": "Sub2Div1",
"id": "div1sub2",
"schemes": [{
"name": "Scheme3",
"id": "scheme3"
}]
}
]
}]
}
I want to read this into a TreeStore, but cannot change the subfields ( divisions, subdivisions, schemes ) to be the same (eg, children).
How can achieve I this?
When nested JSON is loaded into a TreeStore, essentially the children nodes are loaded through a recursive calls between TreeStore.fillNode() method and NodeInterface.appendChild().
The actual retrieval of each node's children field is done within TreeStore.onNodeAdded() on this line:
dataRoot = reader.getRoot(data);
The getRoot() of the reader is dynamically created in the reader's buildExtractors() method, which is what you'll need to override in order to deal with varying children fields within nested JSON. Here is how it's done:
Ext.define('MyVariJsonReader', {
extend: 'Ext.data.reader.Json',
alias : 'reader.varijson',
buildExtractors : function()
{
var me = this;
me.callParent(arguments);
me.getRoot = function ( aObj ) {
// Special cases
switch( aObj.name )
{
case 'Bill': return aObj[ 'children' ];
case 'Norman': return aObj[ 'sons' ];
}
// Default root is `people`
return aObj[ 'people' ];
};
}
});
This will be able to interpret such JSON:
{
"people":[
{
"name":"Bill",
"expanded":true,
"children":[
{
"name":"Kate",
"leaf":true
},
{
"name":"John",
"leaf":true
}
]
},
{
"name":"Norman",
"expanded":true,
"sons":[
{
"name":"Mike",
"leaf":true
},
{
"name":"Harry",
"leaf":true
}
]
}
]
}
See this JsFiddle for fully working code.