Reputation: 381
I have a json file with a tree-like structure that could go down several levels, which looks something like this, and am trying to convert it into a menu (with children elements a sub-menu):
[
{
"label": {
"en": "Home"
},
"icon": "/images/nav/home.png",
"link": "/",
"type": "basic"
},
{
"label": {
"en": "Channels"
},
"icon": "/images/nav/channels.png",
"type": "children",
"children": [
{
"label": {
"en": "Getting Started"
},
"link": "/getting-started",
"type": "basic"
},
{
"label": {
"en": "Recommendations"
},
"link": "/recommendations",
"type": "basic"
},
{
"label": {
"en": "Calendar View"
},
"link": "/calendar",
"type": "basic"
},
{
"label": {
"en": "My Pictures"
},
"link": "/account/media",
"type": "basic"
},
{
"type": "space"
},
{
"label": {
"en": "All Channels"
},
"link": "/channels",
"type": "basic"
},
{
"label": {
"en": "Channel 1"
},
"link": "/channels/channel-1",
"type": "statuses",
"datasource": "/data/1",
"children": [
{
"label": {
"en": "Channel 1-1"
},
"link": "/channels/channel-1-1",
"type": "basic"
},
{
"label": {
"en": "Channel 1-2"
},
"link": "/channels/channel-1-2",
"type": "basic"
},
{
"label": {
"en": "Channel 1-3"
},
"link": "/channels/channel-1-3",
"type": "basic"
},
{
"label": {
"en": "Channel 1-4"
},
"link": "/channels/channel-1-4",
"type": "basic"
},
{
"label": {
"en": "Channel 1-5"
},
"link": "/channels/channel-1-5",
"type": "basic"
}
]
},
{
"label": {
"en": "Channel 2"
},
"link": "/channels/2",
"type": "statuses",
"datasource": "/data/2",
"children": [
{
"label": {
"en": "Channel 2"
},
"link": "/channels/channel-2",
"type": "basic"
},
{
"label": {
"en": "Channel 2-1"
},
"link": "/channels/channel-2-1",
"type": "basic"
},
{
"label": {
"en": "Channel 2-2"
},
"link": "/channels/channel-2-2",
"type": "basic"
},
{
"label": {
"en": "Channel 2-3"
},
"link": "/channels/channel-2-3",
"type": "basic"
},
{
"label": {
"en": "Channel 2-4"
},
"link": "/channels/channel-2-4",
"type": "basic"
}
]
},
{
"type": "custom",
"content": "<div><span class=\"green_bull\">•</span>Currently Online</div><div><span class=\"red_bull\">•</span>Currently Offline</div>"
}
]
},
{
"label": {
"en": "Shows"
},
"icon": "/images/nav/shows.png",
"type": "children",
"children": [
{
"label": {
"en": "LIVE"
},
"link": "/live",
"type": "basic"
},
{
"label": {
"en": "Browse Shows"
},
"link": "/live",
"type": "basic"
},
{
"label": {
"en": "Full Schedule"
},
"link": "/live",
"type": "basic"
},
{
"label": {
"en": "Upcoming Shows"
},
"type": "components",
"component": "navShow",
"datasource": "/shows/upcoming?limit=3"
}
]
},
{
"label": {
"en": "Community"
},
"icon": "/images/nav/community.png",
"type": "children",
"children": [
{
"label": {
"en": "Latest"
},
"link": "/community",
"type": "basic"
},
{
"label": {
"en": "Best of"
},
"link": "/community/highlight",
"type": "basic"
},
{
"label": {
"en": "Discussion Boards"
},
"link": "http://forum.slooh.askmp.ca/",
"type": "basic"
},
{
"label": {
"en": "Rankings"
},
"link": "/community/rankings",
"type": "basic"
},
{
"label": {
"en": "Full Listings"
},
"link": "/community/listings",
"type": "basic"
},
{
"type": "space"
},
{
"label": {
"en": "Hot this Month"
},
"type": "basic-loaded",
"datasource": "/community/hot"
},
{
"type": "space"
},
{
"type": "component",
"component": "nav",
"datasource": "/data/nav"
},
{
"type": "custom",
"content": "[social media HTML]"
}
]
},
{
"label": {
"en": "About"
},
"icon": "/images/nav/about.png",
"type": "children",
"children": [
{
"label": {
"en": "Our Values"
},
"link": "/about",
"type": "basic"
},
{
"label": {
"en": "In the News"
},
"link": "/about/media",
"type": "basic"
},
{
"label": {
"en": "The Team"
},
"link": "/about/#team",
"type": "basic"
},
{
"label": {
"en": "Guests"
},
"link": "/about/#guests",
"type": "basic"
},
{
"label": {
"en": "Partners"
},
"link": "/about/#partners",
"type": "basic"
},
{
"label": {
"en": "Media Kit"
},
"link": "/about/media",
"type": "basic"
},
{
"label": {
"en": "Contact Us"
},
"link": "/about/#contact",
"type": "basic"
},
{
"label": {
"en": "Upcoming Shows"
},
"type": "components",
"component": "navShow",
"datasource": "/data/shows/upcoming?limit=1"
}
]
},
{
"label": {
"en": "Help"
},
"icon": "/images/nav/help.png",
"link": "/",
"type": "children",
"children": [
{
"label": {
"en": "New here?"
},
"link": "/about",
"type": "basic"
},
{
"type": "space"
},
{
"label": {
"en": "Guides"
},
"link": "/help",
"type": "basic"
},
{
"label": {
"en": "Troubleshooting"
},
"link": "/help/#troubleshooting",
"type": "basic"
},
{
"label": {
"en": "Practice Activities"
},
"link": "/help#practice",
"type": "basic"
},
{
"label": {
"en": "Image Management"
},
"link": "/help/images",
"type": "basic"
},
{
"label": {
"en": "Photography 101"
},
"link": "/help/photography",
"type": "basic"
},
{
"label": {
"en": "What’s What?"
},
"link": "/community/whats",
"type": "basic"
},
{
"label": {
"en": "Hints and Tips"
},
"link": "/help/#hints",
"type": "basic"
},
{
"type": "space"
},
{
"label": {
"en": "Trouble Logging In?"
},
"link": "/help/account",
"type": "basic"
},
{
"label": {
"en": "Pricing Tiers"
},
"link": "/help/#account",
"type": "basic"
},
{
"label": {
"en": "Account FAQs"
},
"link": "/help/#account",
"type": "basic"
},
{
"label": {
"en": "Shows FAQs"
},
"link": "/help/shows",
"type": "basic"
},
{
"label": {
"en": "Reservations FAQs"
},
"link": "/help/faqs",
"type": "basic"
},
{
"type": "space"
},
{
"label": {
"en": "Contact Customer Support"
},
"link": "/help/contact",
"type": "basic"
},
{
"label": {
"en": "Site Feedback"
},
"link": "/help/contact#feedback",
"type": "basic"
}
]
},
{
"label": {
"en": "Settings"
},
"icon": "/images/nav/settings.png",
"link": "/",
"type": "children",
"children": [
{
"label": {
"en": "Personal Profile"
},
"link": "/account",
"type": "basic"
},
{
"label": {
"en": "Subscription Management"
},
"link": "/account/subscription",
"type": "basic"
},
{
"label": {
"en": "Alerts & Email Settings"
},
"link": "/account/#notifications",
"type": "basic"
}
]
}
]
I'm attempting to iterate through it, and create a secondary navigation out of the children.
The top level is easy enough to get at, and the second level is almost there. When mapping over children (in GetChildren below), though, I can't get anything that's a child array, only direct objects. So, I can get {child.link}, but {child.label.en} returns an error. Should I be approaching this a smarter way?
var GetChildren = React.createClass({
render: function() {
var childlink = this.props.data.map(function (child, i){
return (
<a key = {i} href={child.link}> {child.label.en}</a>
);
});
return (
<li className="childlist">
{childlink}
</li>
);
}
});
var MenuComponent = React.createClass({
getInitialState: function() {
return {
condition: [],
menuItem: []
};
},
componentDidMount: function() {
$.get(this.props.source, function(result) {
var items = result;
if (this.isMounted()) {
this.setState({
menuItem: items,
condition: false
});
}
}.bind(this));
},
render: function(condition) {
PrimaryMenu = this.state.menuItem || [];
return (
<aside>
<nav>
<ul>
{PrimaryMenu.map(function(el, i){
if (el.type == "basic") {
var PrimaryMenuLink = el.link;
} else {
PrimaryMenuLink = '/' +el.label.en.toLowerCase();
}
return <li key={i}> <a data-nav={'nav-' + el.label.en.toLowerCase()}>
{el.label.en}</a></li>
})}
</ul>
</nav>
{PrimaryMenu.map(function(el, i){
if (el.type == "children") {
return <section key={i} id={'nav-' + el.label.en.toLowerCase()}><ul><GetChildren data={el.children}/> </ul></section>
}
})}
</aside>
);
}
});
Upvotes: 0
Views: 752
Reputation: 11693
The problem may come from some of the json nodes that doesn't have the label
property. Like this node:
{
"type": "space"
},
As a result, it will generate "cannot read property of undefined" on the label
property when reading en
.
You should verify all the children
nodes to be sure label
is existing. Verify link
too to avoid getting undefined
as href
props
Upvotes: 1