React component render dynamic content in tabs from a JSON object - javascript

In my React component I am not able to render a dynamic tab from a JSON object.
I am able to retrieve the JSON data key and the value array, but I am not able to render it in the UI.
I am using PrimeReact UI components.
https://www.primefaces.org/primereact/#/tabview
Component
export default class Report extends Component {
render() {
const { splitGroupedStartingMaterials } = this.state
return (
<div>
<TabView>
{
Object.keys(splitGroupedStartingMaterials).forEach(k => {
console.log('k : ' + k, JSON.stringify(splitGroupedStartingMaterials[k]));
return (<TabPanel header={'Family'}>
simple content here for testing
</TabPanel>);
})
}
</TabView>
</div>);
}
}
JSON Data :-
"splitGroupedStartingMaterials": {
"1": [
{
"id": 45598,
"symbol": "Mn",
"description": "Mn(NO3)2 (fr mn flake)_[10377-66-9]",
"priority": 1,
"matrices": "HNO3",
"family": "F2.0",
"splitGroup": "1"
},
{
"id": 45636,
"symbol": "Ti",
"description": "(NH4)2TiF6 (as Ti)_[16962-40-6]",
"priority": 2,
"matrices": "F- : HNO3",
"family": "F1.1",
"splitGroup": "1"
}
],
"2": [
{
"id": 45572,
"symbol": "Cr",
"description": "CrCl3 (fr Cr shot)_[10025-73-7]",
"priority": 2,
"matrices": "HCl",
"family": "F3.1",
"splitGroup": "1_2"
}
]
}
Update:-
Console Logs:-
10:46:28.769 InOrganicCreateCustomQuote.jsx:704 k : 1 [{"id":45621,"symbol":"Sc","description":"Sc2O3 (as Sc)_[256652-08-1]","priority":1,"matrices":"HNO3","family":"F2.0","splitGroup":"1"},{"id":45636,"symbol":"Ti","description":"(NH4)2TiF6 (as Ti)_[16962-40-6]","priority":2,"matrices":"F- : HNO3","family":"F1.1","splitGroup":"1"},{"id":45640,"symbol":"V","description":"V2O5 (as V)_[1314-62-1]","priority":1,"matrices":"HNO3","family":"F2.0","splitGroup":"1"}]
10:46:28.770 InOrganicCreateCustomQuote.jsx:704 k : 2 [{"id":45646,"symbol":"Zr","description":"ZrCl2O (as Zr)_[7699-43-6]","priority":1,"matrices":"HCl","family":"F3.1","splitGroup":"1_2"}]
For this code no tabs are rendered

Could you try:
export default class Report extends Component {
render() {
const { splitGroupedStartingMaterials } = this.state
return (
<div>
<TabView>
{
Object.keys(splitGroupedStartingMaterials).map(k => (
<TabPanel header={'Family'}>
simple content here for testing
</TabPanel>
))
}
</TabView>
</div>);
}
}

Related

how do i fetch data by id on react native (rest api)

import React, { Component } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-
native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true
};
}
async getMovies() {
try {
const response = await
fetch('https://reactnative.dev/movies.json');
const json = await response.json();
this.setState({ data: json.movies });
} catch (error) {
console.log(error);
} finally {
this.setState({ isLoading: false });
}
}
componentDidMount() {
this.getMovies();
}
render() {
const { data, isLoading } = this.state;
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<Text>{item.title}, {item.releaseYear}</Text>
)}
/>
)}
</View>
);
}
};
this is the api
{
"title": "The Basics - Networking",
"description": "Your app fetched this from a remote endpoint!",
"movies": [
{ "id": "1", "title": "Star Wars", "releaseYear": "1977" },
{ "id": "2", "title": "Back to the Future", "releaseYear": "1985" },
{ "id": "3", "title": "The Matrix", "releaseYear": "1999" },
{ "id": "4", "title": "Inception", "releaseYear": "2010" },
{ "id": "5", "title": "Interstellar", "releaseYear": "2014" }
]
}
I want this code to fetch and show data by id. just like the query show movies by id.
This is the result.
I try to fetch data with id 1 but i dont know how to do it. i dont know how to show it to react native. and i dont know how fetch the data by id
I pass a parameter like this:
my call to the API:
const getDetails = (id) => {
return api.Get(`/api/details/${id}`);
}
then in the react code
const getInfo = async(e) => {
apiCall.GetDetails(value to be passed here)
}

Material UI - TreeView datastructure

I want to structure the data that I get from a server, so I can use the TreeView component from Material UI: https://material-ui.com/api/tree-view/
I'm fetching large amounts of data so I want to fetch child nodes from the server when the user clicks on the expand button. So
when the first node is expanded a HTTP request is sent to a server which returns all of the children of that node. When another node is expanded the children of that node is fetched etc.
On startup of the page I want to fetch the root node and its children. The JSON returned will look something like this:
{
"division": {
"id": "1234",
"name": "Teest",
"address": "Oslo"
},
"children": [
{
"id": "3321",
"parentId": "1234",
"name": "Marketing",
"address": "homestreet"
},
{
"id": "3323",
"parentId": "1234",
"name": "Development",
"address": "homestreet"
}
]
}
When expanding the Marketing node I want to make a HTTP call to fetch the children of this node. So I would get JSON like this:
{
"children": [
{
"id": "2212",
"parentId": "3321",
"name": "R&D",
"address": "homestreet"
},
{
"id": "4212",
"parentId": "3321",
"name": "Testing",
"address": "homestreet"
}
]
}
But I am confused on how to create such a data structure which can later be used my the TreeView component. How can I create such a structure?
For anyone still looking for a solution to this problem I've recently tackled it using a combination of the selected and expanded props in the TreeView API. See this Code Sandbox demo for an example of how to asynchronously load new children and expand their parent once they are loaded.
import React from "react";
import TreeView from "#material-ui/lab/TreeView";
import ExpandMoreIcon from "#material-ui/icons/ExpandMore";
import ChevronRightIcon from "#material-ui/icons/ChevronRight";
import TreeItem from "#material-ui/lab/TreeItem";
import TreeNode from "./TreeNode";
const mockApiCall = async () => {
return new Promise((resolve) => {
setTimeout(() => {
const nextId = Math.ceil(Math.random() * 100);
resolve([
{
id: `${nextId}`,
name: `child-${nextId}`,
children: []
},
{
id: `${nextId + 1}`,
name: `child-${nextId + 1}`,
children: []
}
]);
}, Math.ceil(Math.random() * 1000));
});
};
export default class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {
expanded: [],
selected: "1",
tree: new TreeNode({
id: "1",
name: "src",
children: []
})
};
}
handleChange = async (event, nodeId) => {
const node = this.state.tree.search(nodeId);
if (node && !node.children.length) {
mockApiCall()
.then((result) => {
this.setState({ tree: this.state.tree.addChildren(result, nodeId) });
})
.catch((err) => console.error(err))
.finally(() => {
this.setState({
selected: nodeId,
expanded: [...this.state.expanded, nodeId]
});
});
}
};
createItemsFromTree = (tree) => {
if (tree.children.length) {
return (
<TreeItem key={tree.id} nodeId={tree.id} label={tree.name}>
{tree.children.length > 0 &&
tree.children.map((child) => this.createItemsFromTree(child))}
</TreeItem>
);
}
return <TreeItem key={tree.id} nodeId={tree.id} label={tree.name} />;
};
render() {
return (
<TreeView
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
selected={this.state.selected}
onNodeSelect={this.handleChange}
expanded={this.state.expanded}
>
{this.createItemsFromTree(this.state.tree)}
</TreeView>
);
}
}

TypeError: .json WEBPACK_IMPORTED_MODULE_2__.filter is not a function

I am getting error when i try to get data from json file at this line in my code selectedEmployee: employeeList.data.Table[0],
TypeError: _employeeList_json__WEBPACK_IMPORTED_MODULE_2__.filter is
not a function
//App.js
const filterEmployee = (searchText, maxResults) => {
return employeeList.filter((employee) => {
if (employee.data.Table.name.toLowerCase().includes(searchText.toLowerCase())) {
return true;
}
return false;
}).slice(0, maxResults);
}
var maxResults = 4;
export default class App extends React.Component {
constructor(){
super();
this.state = {
selectedEmployee: employeeList.data.Table[0],
filteredEmployee: filterEmployee('', maxResults)
}
}
onSearch = (event) => {
this.setState({
filteredEmployee: filterEmployee(event.target.value, maxResults)
});
}
onEmployeeClick = (employee) => {
this.setState({
selectedEmployee: {name: employee.name, info: employee.info, contact: employee.contact}
});
}
render() {
return (
<Col lg={8} md={7} sm={4} lgOffset={2}>
<Col lg={6}>
<HomePage onSearch={this.onSearch} employeeData={this.state.filteredEmployee} onEmployeeClick={this.onEmployeeClick}/>
</Col>
<Col lg={6}>
<EmployeePage selectedEmployee={this.state.selectedEmployee}/>
</Col>
</Col>
);
}
}
//my json file looks like this
{
"data": {
"Table": [
{
"id": "1001",
"name": "Alez",
"info": "Alez"
},
{
"id": "1002",
"name": "Baro",
"info": "Alez"
}
]
}
}
What i want to accomplish is using a different .json format.
these was the orginal json file format
[
{
"key": "t1",
"data":{
"name": "James",
"info": "Software Development",
"contact": {
"office": "781-000-002",
"mobile": "087-321-0292",
"sms": "617-000-002",
"email": "jtaylor#company.ie"
}
}
}
]
I want to use these json file format instead and update my code
{
"data": {
"Table": [
{
"id": "1001",
"name": "Alez",
"info": "Alez"
},
{
"id": "1002",
"name": "Baro",
"info": "Alez"
}
]
}
}
The error is related to the filter function call at the top of your code. You can only filter on an array. Therefore you need to call filter like using employeeList.data.Table as your array:
const filterEmployee = (searchText, maxResults) => {
return employeeList.data.Table.filter((employee) => {
// returns true if condition is met, otherwise returns false
return employee.name.toLowerCase().includes(searchText.toLowerCase());
}).slice(0, maxResults);
}
and then when checking if the employee.name includes the searchText, you can just access employee.name instead.

How to property call component inside same component using ReactJS?

I'm building a sidebar menu with submenu levels, and I'm using this code to build the menu and the submenus:
Sidebar menu:
import React from 'react';
import SidebarMenuItem from './SidebarMenuItem';
var menuData = require("./data/menu.json");
class SidebarMenu extends React.Component {
constructor(props)
{
super(props);
this.state = { expanded: true };
};
render() {
return (
<div>
{
menuData.map((item, index) => <SidebarMenuItem id={ index.toString()} key={index.toString()} {...item} />)
}
</div>
);
};
}
export default SidebarMenu;
SidebarMenuItem:
import React from 'react';
class SidebarMenuItem extends React.Component {
render() {
console.log(this.props.id);
return (
<div>
<a href={this.props.link}>{this.props.title}<i className={'fa ' + this.props.icon}/></a>
{this.props.submenu ? this.props.submenu.map((subitem, index) => <SidebarMenuItem key={this.props.id + index.toString()} {...subitem} />) : null }
</div>
)
}
}
SidebarMenuItem.propTypes = {
id: React.PropTypes.string,
key: React.PropTypes.string,
title: React.PropTypes.string,
ref: React.PropTypes.string,
icon: React.PropTypes.string,
submenu: React.PropTypes.array
}
export default SidebarMenuItem;
Although I can see the submenus on screen, I'm getting the following error:
Warning: SidebarMenuItem: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop.
Another clue that something is wrong is the console output:
0
1
undefined <-- I was supposed to get 11 and 12 here, as this option has 2 submenus
2
And finally my menu.JSON data:
[
{
"title": "Option1",
"link": "www.google.com",
"icon": "fa-edit"
},
{
"title": "Option2",
"link": "",
"icon": "fa-hello",
"submenu":
[
{
"title": "SubOption2.1",
"link": "wwww.yahoo.com",
"icon": "fa-asterisk"
},
{
"title": "SubOption2.2",
"link": "wwww.tisafe.com",
"icon": "fa-save"
}
]
},
{
"title": "Option3",
"link": "www.mezasoft.com",
"icon": "fa-save"
}
]
Help appreaciated to find out what's wrong with my code.
You are getting the warning because key is a restricted attribute and cannot be passed as a prop, change it to keyValue. Also you get undefined when you use this.props.id because in your SidebarMenuItem render function for submenus you are still calling the same component and there you are not passing the id as a prop. you can see that in the snippet below. I hope it helps
class SidebarMenu extends React.Component {
constructor(props)
{
super(props);
this.state = { expanded: true };
};
render() {
var menuData = [
{
"title": "Option1",
"link": "www.google.com",
"icon": "fa-edit"
},
{
"title": "Option2",
"link": "",
"icon": "fa-hello",
"submenu":
[
{
"title": "SubOption2.1",
"link": "wwww.yahoo.com",
"icon": "fa-asterisk"
},
{
"title": "SubOption2.2",
"link": "wwww.tisafe.com",
"icon": "fa-save"
}
]
},
{
"title": "Option3",
"link": "www.mezasoft.com",
"icon": "fa-save"
}
];
return (
<div>
{
menuData.map((item, index) => <SidebarMenuItem id={ index.toString()} keyValue={index.toString()} {...item} />)
}
</div>
);
};
}
class SidebarMenuItem extends React.Component {
render() {
console.log('in render',this.props);
return (
<div>
<a href={this.props.link}>{this.props.title}<i className={'fa ' + this.props.icon}/></a>
{this.props.submenu ? this.props.submenu.map((subitem, index) => <SidebarMenuItem keyValue={this.props.id + index.toString()} {...subitem} />) : null }
</div>
)
}
}
SidebarMenuItem.propTypes = {
id: React.PropTypes.string,
keyValue: React.PropTypes.string,
title: React.PropTypes.string,
ref: React.PropTypes.string,
icon: React.PropTypes.string,
submenu: React.PropTypes.array
}
ReactDOM.render(<SidebarMenu/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>

Passing list of values as filtertable content

I'm attempting to filter using a list of values with React.
All my "tags" have a "taglevel" to indicate their relevance.
I want it to "cancel out" tags which are the same (ie don't repeat the tag if its' the same).
I want the first row to show all tag.name with "taglevel" of 1.
I want the second row to show all tag.name with "taglevel" of 2 or more.
I am unable to show and filter on the value "tags". Possibly it is around line 145 of my codepen where I have made the error.
Here is what I am trying to achieve:
I've put this together in a codepen.
http://codepen.io/yarnball/pen/GqbyWr?editors=1010
Without success, I have now tried the following:
I tried filtering using this using:
var LevelFilter = React.createClass({
render: function(){
if (!this.props.tags) return null;
return this.props.tags.filter(tag => tag.taglevel === this.props.targetLevel).map(tag => <a onClick={this.props.onClick}>{tag.name}</a>);
}
});
Then trying to get it in my return here:
render: function(){
...
var getUniqueCategories=[];
PHOTODATA.forEach(function(el){
if(getUniqueCategories.indexOf(el.tag) === -1 ) getUniqueCategories.push(el.tag);
})
return (
<div className="overlay-photogallery">
<div className="filter-panel"><b>Tags with taglevel 1 only to be displayed</b>
{
getUniqueCategories.map(function(el,i){
var boundClick = titleToSelect.bind(null,el);
return <LevelFilter onClick={boundClick} targetLevel={1} tags={el.tag} />
})
}
<a className="resetBtn" onClick={this.resetFilter}> Reset Filter </a>
</div>
My data looks like this:
"title": "Into the Wild",
"tag": [
{
"name": "Movie",
"taglevel": 1,
"id": 1
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Book",
"taglevel": 1,
"id": 2
}
],
"info": []
}
TL;DR
You have some serious issues with your array manipulation and your React components.
Remember that React advocates a specific top down structure and you should read up on it some more. Each React Component should use props as much as possible and ideally only 1 top-level component should hold state.
QUICK ways forward:
Pass all the data down and let each level filter make the list unique.
Seriously, split up your components and let them depend on props as much as possible.
Give variables meaningful names. el is not meaningful and in your case refers to PHOTO items in the PHOTODATA array, tags in a PHOTO and then you use element to mean something else again. Don't go to over the top, but at least be able to identify what the variable is supposed to do.
I've given in and made a codepen with a much updated structure. The behaviour may not be exactly what you're looking for, but look at the code and how it is organised and how information is shared and passed between components.
http://codepen.io/anon/pen/AXGGLy?editors=1010
UPDATE
To allow multiple filters two methods should be updated:
selectTag: function (tag) {
this.setState({
displayedCategories: this.state.displayedCategories.concat([tag])
});
}
tagFilter: function (photo) {
return this.props.displayedCategories.length !== 0 &&
this.props.displayedCategories.every(function(thisTag) {
return photo.tag.some(function (photoTag) {
return photoTag.id === thisTag.id &&
photoTag.taglevel === thisTag.taglevel;
});
});
},
selectTag now appends to the displayedCategories array rather than replacing it.
tagFilter now checks that at least one filter has been applied (remove this.props.displayedCategories.length !== 0 to disable this) so that it doesn't display all by default and then checks that every selected filter is present in each photo, thus making the components additive.
There are further improvements that could be made, such as to disable a level when a filter is applied at that level (one choice per level) or to show a list of applied filters, either through colour on the buttons or a tag list above the results.
(codepen updated with these latest changes)
Ok, there are a few problems with your codepen.
First, on line 137 you extract the tag array from the object:
if(getUniqueCategories.indexOf(el.tag) === -1 ) getUniqueCategories.push(el.tag);
Then, on 146 you extract it again:
return <LevelFilter onClick={boundClick} targetLevel={1} tags={el.tag} />
and again for level 2:
return <LevelFilter onClick={boundClick} targetLevel={2} tags={el.tag} />
For both of these it should be:
return <LevelFilter onClick={boundClick} targetLevel={n} tags={el} />
Which then allows another problem to manifest itself, which is that LevelFilter doesn't return a valid React component (an array is not valid).
return this.props.tags.filter(tag => tag.taglevel === this.props.targetLevel).map(tag => <a onClick={this.props.onClick}>{tag.name}</a>);
should be
return (
<div>
{
this.props.tags
.filter(tag => tag.taglevel === this.props.targetLevel)
.map(tag => <a onClick={this.props.onClick}>{tag.name}</a>)
}
</div>
);
After these changes you should have a much closer attempt to where you want to be.
There are further issues you will need to look into, things like your boundClick function won't work correctly because you only have a list of tags, not PHOTODATA.
However, just a final thought. You might want to break your React components up a little more.
For reference, here is the full code listing from the codepen:
var PHOTODATA = [{
"title": "Into the Wild",
"tag": [
{
"name": "Movie",
"taglevel": 1,
"id": 1
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Book",
"taglevel": 1,
"id": 2
}
],
"info": []
},{
"title": "Karate Kid",
"tag": [
{
"name": "Movie",
"taglevel": 1,
"id": 1
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Kids",
"taglevel": 3,
"id": 4
}
],
"info": []
},
{
"title": "The Alchemist",
"tag": [
{
"name": "Book",
"taglevel": 1,
"id": 2
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Classic",
"taglevel": 2,
"id": 4
},
{
"name": "Words",
"taglevel": 4,
"id": 4
}
],
"info": []
}];
var PhotoGallery = React.createClass({
getInitialState: function() {
return {
displayedCategories: []
};
},
selectTag: function (tag) {
this.setState({
displayedCategories: this.state.displayedCategories.concat([tag])
});
},
resetFilter: function(){
this.setState({
displayedCategories: []
});
},
render: function(){
var uniqueCategories = PHOTODATA.map(function (photo) {
return photo.tag; // tag is a list of tags...
}).reduce(function (uniqueList, someTags) {
return uniqueList.concat(
someTags.filter(function (thisTag) {
return !uniqueList.some(function(uniqueTag) {
return uniqueTag.id === thisTag.id && uniqueTag.taglevel === thisTag.taglevel
});
})
);
}, []);
return (
<div className="overlay-photogallery">
<div className="filter-panel"><b>Tags with taglevel 1 only to be displayed</b>
<PhotoGalleryLevel level={1} tags={uniqueCategories} displayedCategories={this.state.displayedCategories} selectTag={this.selectTag} />
<a className="resetBtn" onClick={this.resetFilter}> Reset Filter </a>
</div>
<div className="filter-panel"><b>Tags with taglevel 2 only to be displayed</b>
<PhotoGalleryLevel level={2} tags={uniqueCategories} displayedCategories={this.state.displayedCategories} selectTag={this.selectTag} />
</div>
<div className="PhotoGallery">
<PhotoDisplay displayedCategories={this.state.displayedCategories} photoData={PHOTODATA} />
</div>
</div>
);
}
});
var PhotoGalleryLevel = React.createClass({
render: function () {
var filteredTags = this.props.tags.filter(function (tag) {
return tag.taglevel === this.props.level;
}.bind(this));
var disabled = this.props.displayedCategories.some(function (tag) {
return tag.taglevel === this.props.level;
}.bind(this));
return (
<div>
{filteredTags.map(function (tag){
return <PhotoGalleryButton tag={tag} selectTag={this.props.selectTag} disabled={disabled} />;
}.bind(this))}
</div>
);
}
});
var PhotoGalleryButton = React.createClass({
onClick: function (e) {
this.props.selectTag(this.props.tag);
},
render: function () {
return (
<a className={this.props.disabled} onClick={this.onClick}>{this.props.tag.name}</a>
);
}
});
var PhotoDisplay = React.createClass({
getPhotoDetails: function (photo) {
console.log(this.props.displayedCategories, photo);
return (
<Photo title={photo.title} name={photo.name} tags={photo.tag} />
);
},
tagFilter: function (photo) {
return this.props.displayedCategories.length !== 0 &&
this.props.displayedCategories.every(function(thisTag) {
return photo.tag.some(function (photoTag) {
return photoTag.id === thisTag.id &&
photoTag.taglevel === thisTag.taglevel;
});
});
},
render: function () {
return (
<div>
{this.props.photoData.filter(this.tagFilter).map(this.getPhotoDetails)}
</div>
);
}
});
var Photo = React.createClass({
getTagDetail: function (tag){
return (
<li>{tag.name} ({tag.taglevel})</li>
);
},
sortTags: function (tagA, tagB) {
return tagA.taglevel - tagB.taglevel;
},
render: function(){
return (
<div className="photo-container" data-title={this.props.title} >
{this.props.title}
<ul>
{this.props.tags.sort(this.sortTags).map(this.getTagDetail)}
</ul>
</div>
);
}
});
ReactDOM.render(<PhotoGallery />, document.getElementById('main'));
With below react component I was able to do what you are looking for,
and here's what i've done in the code,
i) from the PHOTODATA array i have created taglevel1, taglevel2 array
one the render method at the begining.
ii) show them in two rows in showLevel1, showLevel2 function.
iii) when the tag item will be click it will call handleClick function and filter the data and save it to the filterData state.
import React, { Component } from 'react';
import { pluck } from 'underscore';
class Router extends Component {
constructor(props) {
super(props);
this.state = {
filterData: [],
};
this.filterArray = [];
this.PHOTODATA = [{
"title": "Into the Wild",
"tag": [
{
"name": "Movie",
"taglevel": 1,
"id": 1
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Book",
"taglevel": 1,
"id": 2
}
],
"info": []
},{
"title": "Karate Kid",
"tag": [
{
"name": "Movie",
"taglevel": 1,
"id": 1
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Kids",
"taglevel": 3,
"id": 4
}
],
"info": []
},
{
"title": "The Alchemist",
"tag": [
{
"name": "Book",
"taglevel": 1,
"id": 2
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Classic",
"taglevel": 2,
"id": 4
},
{
"name": "Words",
"taglevel": 4,
"id": 4
}
],
"info": []
}];
}
handleClick(item) {
const findItem = this.filterArray.indexOf(item);
if (findItem === -1) {
this.filterArray.push(item);
} else {
this.filterArray.pop(item);
}
const filterData = [];
if(this.filterArray.length) {
this.PHOTODATA.map((item) => {
const data = pluck(item.tag, 'name');
let count = 0;
// console.log(data);
this.filterArray.map((filterItem) => {
const find = data.indexOf(filterItem);
if(find !== -1) {
count++;
}
});
if(count === this.filterArray.length) {
filterData.push(item);
}
});
}
console.log(this.filterArray);
this.setState({ filterData });
}
render() {
const taglevel1 = [];
const taglevel2 = [];
this.PHOTODATA.map((item) => {
item.tag.map((tagItem) => {
if(tagItem.taglevel === 1) {
const find = taglevel1.indexOf(tagItem.name);
if(find === -1) {
taglevel1.push(tagItem.name);
}
} else {
const find = taglevel2.indexOf(tagItem.name);
if(find === -1) {
taglevel2.push(tagItem.name);
}
}
});
});
const showLevel1 = (item, index) => {
return <span onClick={this.handleClick.bind(this, item)}> {item} </span>
};
const showLevel2 = (item, index) => {
return <span onClick={this.handleClick.bind(this, item)}> {item} </span>
};
const showData = (item, index) => {
return <div>{item.title}</div>
};
return (<div>
<ul>Tag Level 1: {taglevel1.map(showLevel1)}</ul>
<ul>Tag Level 2: {taglevel2.map(showLevel2)}</ul>
<div>Movie Title: {this.state.filterData.map(showData)}</div>
</div>);
}}
and here you can see how my outputs look like

Categories

Resources