hi everyone I have data given below by using this data I just want to create a cart click on this link to check what kind of cart I want to design from this data
const result = [
{
name: 'shanu',
label: ['ak', 'pk', 'plk', 'k'],
value: [1, 2, 3, 5],
},
];
// what i did
{result.map((el) => {
return (
<div>
<h1>{el.name}</h1>
<div className="vart">
<div>
{el.label.map((e) => {
return <p>{e}</p>;
})}
</div>
<div>
{el.value.map((e) => {
return <p>{e}</p>;
})}
</div>
</div>
</div>
);
})}
.vart {
display: flex;
flex-direction: row;
}
You can access the value according to the index of the label as below. You can use a CSS grid system to show a two-column view.
export default function App() {
const result = [
{
name: "shanu",
label: ["ak", "pk", "plk", "k"],
value: [1, 2, 3, 5]
}
];
return result.map((el) => {
return (
<div>
<div className="header">{el.name}</div>
<div className="grid-container">
{el.label.map((e, index) => {
return (
<div
className="grid-item"
style={{ textAlign: index % 2 === 0 ? "left" : "right" }}
>
{e} : {el.value[index]}
</div>
);
})}
</div>
</div>
);
});
}
Following styles will organise the grid with right aligning the second column.
.header {
color: #ffffff;
background-color: #4473c4;
padding: 10px 20px;
}
.grid-container {
display: grid;
grid-template-columns: auto auto;
}
.grid-item {
padding: 10px 20px;
color: #ffffff;
background-color: #91cf50;
}
HTML Output
Code Sandbox
If you want to link value and label this way:
ak => 1
pk => 2
plk => 3
k => 5
It would be better practice to change your data structure and move them aside. It avoids running in cases where label[x] is defined, but value[x] is not:
export default function App() {
const result = [
{
name: "shanu",
items: [
{ label: "ak", value: 1 },
{ label: "pk", value: 2 },
{ label: "plk", value: 3 },
{ label: "k", value: 5 },
],
}
];
return result.map((el) => {
return (
<div>
<h1>{el.name}</h1>
<div className="vart">
<div>
{el.items.map((e, index) => {
return (
<p>
{e.label} : {e.value}
</p>
);
})}
</div>
</div>
</div>
);
});
}
Related
I want to create a drag and drop application using the Vue JS framework. Here is an example of my complete code.
The problem is with the id properties inside the children arrays.
For example, when I drag an object named 'AAA' to another place, everything works fine for me, but when I drag it back, I get an error like - Duplicate keys detected: '0'. This may cause an update error.
I'm pretty sure the problem is inside the oneDrop function
onDrop(e, categoryId) {
const itemId = parseInt(e.dataTransfer.getData('itemId'))
this.categories.map(item => {
item.children = item.children.filter(child => {
if (child.id == itemId) {
child.categoryId = categoryId;
this.categories[categoryId].children.push(child);
}
return child
})
})
}
Of course, I understand that when dragging using the push method, the old object remains and is not deleted, so I get this error, but how to deal with this problem? (Full code at the beginning of the question)
You need to filter list from and add item to list to:
new Vue({
el: "#demo",
data() {
return {
categories: [
{id: 0, title: "This is parent block", children: [{ id: 0, title: "AAA", categoryId: 0 }, { id: 1, title: "BBB", categoryId: 0 },],},
{id: 1, title: "This is parent block", children: [{ id: 2, title: "CCC", categoryId: 1 }, { id: 3, title: "DDD", categoryId: 1 },],},
],
};
},
methods: {
onDrop(e, categoryId) {
const itemId = parseInt(e.dataTransfer.getData("itemId"));
const id = categoryId === 0 ? 1 : 0
const child = this.categories[id].children.find(c => c.id === itemId)
child.categoryId = categoryId;
this.removeFromList(id, itemId)
this.addToList(categoryId, child)
},
addToList(categoryId, child) {
this.categories[categoryId].children = [...this.categories[categoryId].children, child];
},
removeFromList(id, itemId) {
this.categories[id].children = this.categories[id].children.filter(c => c.id !== itemId);
},
onDragStart(e, item) {
e.dataTransfer.dropEffect = "move";
e.dataTransfer.effectAllowed = "move";
e.dataTransfer.setData("itemId", item.id.toString());
},
},
})
.droppable {
padding: 15px;
border-radius: 5px;
background: #2c3e50;
margin-bottom: 10px;
}
.droppable h4 {
color: white;
}
.draggable {
background: white;
padding: 5px;
border-radius: 5px;
margin-bottom: 5px;
}
.draggable h5 {
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<div
v-for="category in categories"
:key="category.id"
#drop="onDrop($event, category.id)"
class="droppable"
#dragover.prevent
#dragenter.prevent
>
<h4>{{ category.title }}</h4>
<div class="child">
<div
v-for="item in category.children.filter(
(x) => x.categoryId === category.id
)"
:key="item.id"
#dragstart="onDragStart($event, item)"
class="draggable"
draggable="true"
>
<h5>{{ item.title }}</h5>
</div>
</div>
</div>
{{categories}}
</div>
import { useState } from "react";
function App() {
const [itemsClicked, setItemsClicked] = useState([]);
const dataList = [
{ id: 1, name: "jake" },
{ id: 12, name: "edd" },
{ id: 13, name: "john" }
];
const highlight = (data) => {
setItemsClicked((array) => {
let itemClicked = array.includes(data)
? array.filter((x, i) => x.id !== data.id)
: [...array, data]; // What I'm trying to do here is to add a new field which is 'active' >> [...array, {...data, active: true}];
return itemClicked;
});
};
return (
<div>
{dataList.map((item, i) => (
<div
style={{
borderColor: itemsClicked[i]?.active ? "1px solid green" : ""
}}
>
<button onClick={() => highlight(dataList[i])}>HIGHLIGHT</button>
</div>
))}
</div>
);
}
export default App;
What I'm trying to do here is to create a toggle which is to highlight the div.
but my problem is on the state instead of it will remove the data object, it will continue appending. how to fix it?
for example when I try to click the first data which is jake, the output should be like this in itemsClicke
[{ id: 1, name: jake, active: true }]
but when I try to click again it will just remove it from the list, but on my side, it continuing to append the data which is wrong
[{ id: 1, name: jake, active: true },{ id: 1, name: jake, active: true },{ id: 1, name: jake, active: true },{ id: 1, name: jake, active: true }]
You can simply remove the itemsClicked state and put the dataList in a state variable to have control over it:
const [dataList, setDataList] = useState([
{ id: 1, name: "jake" },
{ id: 12, name: "edd" },
{ id: 13, name: "john" }
]);
Now, you need to check an isActive property to conditionally add some styles, so you need isActive but it's not in the current dataList and you created itemsClicked to solve this issue. But there are some simpler solutions like adding a property on the fly with your dataList.
You can implement toggleHighlight function to change isActive property:
const toggleHighlight = (id) => {
setDataList((prevState) =>
prevState.map((item) =>
item.id === id ? { ...item, isActive: !item.isActive } : item
)
);
};
this toggleHandler will accept an id and take a for loop over the dataList, it finds the clicked item. if it's an active item so it changes it to false and vice versa.
let's recap and put all things together:
import { useState } from "react";
function App() {
const [dataList, setDataList] = useState([
{ id: 1, name: "jake" },
{ id: 12, name: "edd" },
{ id: 13, name: "john" }
]);
const toggleHighlight = (id) => {
setDataList((prevState) =>
prevState.map((item) =>
item.id === id ? { ...item, isActive: !item.isActive } : item
)
);
};
return (
<div>
{dataList.map((item) => (
<div
key={item.id}
style={{
display: "flex",
paddingTop: 10,
border: item.isActive ? "2px solid green" : ""
}}
>
<p style={{ padding: 5 }}>{item.name}</p>
<button onClick={() => toggleHighlight(item.id)}>HIGHLIGHT</button>
</div>
))}
</div>
);
}
export default App;
Try this on a live playground
array.includes(data)
won't return true because of this: https://stackoverflow.com/a/50371323/17357155
Just use this. It's a simple example. I used itemsClicked only for storing the ids
const highlight = (data) => {
if(itemsClicked.indexOf(data.id) == -1)
{
setItemsClicked(prevData => {
return [...prevData, data.id]
})
}
}
{
dataList.map((item, i) => (
<div
style={{
border:
itemsClicked.indexOf(item.id) > -1 ? '1px solid green' : '',
}}
>
{itemsClicked.indexOf(item.id) > -1 ? '1px solid green' : ''}
<button onClick={() => highlight(dataList[i])}>HIGHLIGHT</button>
</div>
))
}
I have many div in cascade.
and I want to apply alternated colors to my golbal div ( green, yellow for example ). But i want that colors start from the begening of the global div not from the begening of the div that contains it..
I created this using recursivity.
This is what i have ( I displayed div borders to explain the design of the page i have. )
This is what i want
React code
<div>
{
intervenants.map(i => {
return (updateListDiv(i))
})
}
</div>
const updateListDiv = (intervenant) => {
if (intervenant.children && intervenant.children.length > 0) {
return (
intervenant.children.map((int, index) => {
let n = int.name + ' ( ' + int.profile.name + ' ) '
return (<div className="a b" key={Math.random()}>
<a> {int.name} </a>
( {int.profile.name} )
{updateListDiv(int)}
</div>)
})
)
} else {
}
}
css
.a {
margin-left: 30px;
}
.b {
line-height: 24pt;
border: solid 1px black;
}
Every item needs to know the previous color. So you can store the state globally, or (probably better) pass the state to your updateListDiv function.
Here I call the state isEven:
import React from 'react';
const intervenants = [
{ name: 'a', profile: { name: 'pa' }, children: [ { name: 'a.a', profile: { name: 'pa.a' }, children: null }, { name: 'a.b', profile: { name: 'pa.b' }, children: null }, ] },
{ name: 'b', profile: { name: 'pb' }, children: [ { name: 'b.a', profile: { name: 'pb.a' }, children: null }, { name: 'b.b', profile: { name: 'pb.b' }, children: null }, ] },
{ name: 'c', profile: { name: 'pc' }, children: [ { name: 'c.a', profile: { name: 'pc.a' }, children: null }, { name: 'c.b', profile: { name: 'pc.b' }, children: null }, ] },
];
const updateListDiv = (intervenant, isEven) => {
if (!intervenant.children || intervenant.children.length < 1) {
return;
}
return (
intervenant.children.map((int, index) => {
isEven = !isEven;
return (<div
key={ index }
style={{
marginLeft: '30px',
border: 'solid 1px',
backgroundColor: isEven ? '#ff0' : '#0f0',
}}
>
{ int.name }
{ updateListDiv(int, isEven) }
</div>);
})
);
}
export const ColorTree = ()=>{
return (<div>
{ updateListDiv({ children: intervenants }, false) }
</div>);
};
Alternatively, you can pass down an overall index, and check for modulo-2.
I like this approach more, because this is more flexible (it might come in handy to have a "total" index inside the childs, and it also becomes possible to e.g. use modulo-3 or something)
const updateListDiv = (intervenant, overAllIndex) => {
// ...
return (
intervenant.children.map((int, index) => {
overAllIndex++;
return (<div
style={{
backgroundColor: (overAllIndex % 2) ? '#ff0' : '#0f0',
}}
>
{ updateListDiv(int, overAllIndex) }
</div>);
})
);
}
I am basically a beginner in React. I have a dashboard page where I display a React Table. I have a customize button which will open a popup page, this popup page has some check boxes allows me to show/hide those React columns. Initially all the check boxes in this popup page is set to true. When I uncheck a column that particular column get disabled.
This is my parent component - the parent page is the page with the ReactTable, there are 10 columns now, not 8 as shown in the image.
import React, { Component } from 'react';
import { connect } from 'react-redux';
import ReactTable from 'react-table';
import LoadingComponent from '../shared/loading/LoadingComponent';
import InputComponent from '../shared/input/InputComponent';
import { makeData } from '../../util/Utils';
import CustomizedView from './customized_view/CustomizedView';
import filter from '../../assets/svg/filter.svg';
import config from '../../../framework/config';
//import EnquiryDetails from './enquiry_details/enquiryDetails';
const searchIcon = config.assetUrl + '/table_filter/svg/search-icon.svg';
class Dashboard extends Component {
constructor(props) {
super(props);
this.state = {
filterState: {},
data: makeData(),
searchText: '',
isFilterOpen: false,
isCustomizedOpen: false,
isFiltered: false,
isSearched: false,
searchedTableData: [],
filteredTableData: [],
filterItems: [
{ id: 1, value: 'Col 1', isChecked: true },
{ id: 2, value: 'Col 2', isChecked: true },
{ id: 3, value: 'Col 3', isChecked: true },
{ id: 4, value: 'Col 4', isChecked: true },
{ id: 5, value: 'Col 5', isChecked: true },
{ id: 6, value: 'Col 6', isChecked: true },
{ id: 7, value: 'Col 7', isChecked: true },
{ id: 8, value: 'Col 8', isChecked: true },
{ id: 9, value: 'Col 9', isChecked: true },
{ id: 10, value: 'Col 10', isChecked: true },
],
};
this.handleFilterClickinv = this.handleFilterClickinv.bind(this);
this.handleCustClickinv = this.handleCustClickinv.bind(this);
}
getTopBar() {
return (
<div className='top-bar-div'>
<div className='heading-div'>Dashboard</div>
</div>);
}
getFilterBar() {
const searchIconImg = (<img src={searchIcon} alt="" />);
if(this.state.isFiltered) table = this.state.filteredTableData;
if(this.state.isSearched) table = this.state.searchedTableData;
return (
<div className='table-header-div' >
<div className="filter-container-div">
</div>
<div className='search-enquiry-div'>
<div className="search-container">
<div className="search-input-container-div">
<InputComponent
height="41px"
width="280px"
inputClassName="order-filter-input"
placeholder='Search'
type="text"
value={this.state.searchText}
icon={searchIconImg}
onChange={this.onSearch}
/>
</div>
</div>
</div>
<div className="filter-icon-div-main">
<div className="custom-icon-div" onClick={() => { this.handleCustClickinv(); }}>
<div className='customize-view-inventory'>Customized View </div>
</div>
</div>
</div>);
}
getColumns() {
const columns = [
{
id: "col16",
Header: () => {
return (
<div>
<div className="col1-heading">Col 1</div>
<div className="col6-heading">Col 6</div>
</div>
);
},
accessor: d => {
return (
<div>
<div className="col1">{d.firstName}</div>
<div className="col6">{d.lastName}</div>
</div>
);
},
width: 200
},
{
id: "col27",
Header: () => {
return (
<div>
<div className="col2-heading">Col 2</div>
<div className="col7-heading">Col 7</div>
</div>
);
},
accessor: d => {
return (
<div>
<div className="col2">{d.firstName}</div>
<div className="col7">{d.lastName}</div>
</div>
);
},
width: 200
},
{
id: "col38",
Header: () => {
return (
<div>
<div className="col3-heading">Col 3</div>
<div className="col8-heading">Col 8</div>
</div>
);
},
accessor: d => {
return (
<div>
<div className="col3">{d.firstName}</div>
<div className="col8">{d.lastName}</div>
</div>
);
},
width: 200
},
{
id: "col49",
Header: () => {
return (
<div>
<div className="col4-heading">Col 4</div>
<div className="col9-heading">Col 9</div>
</div>
);
},
accessor: d => {
return (
<div>
<div className="col4">{d.firstName}</div>
<div className="col9">{d.lastName}</div>
</div>
);
},
width: 200
},
{
id: "col510",
Header: () => {
return (
<div>
<div className="col5-heading">Col 5</div>
<div className="col10-heading">Col 10</div>
</div>
);
},
accessor: d => {
return (
<div>
<div className="col5">{d.firstName}</div>
<div className="col10">{d.lastName}</div>
</div>
);
},
width: 200
},
{
id: "col11",
Header: "Col 11",
columns: [
{
id: "scol11a",
Header: "Sub Col 11a",
accessor: d => {
return d.firstName;
},
width: 80
},
{
id: "scol11b",
Header: "Sub Col 11b",
accessor: d => {
return d.firstName;
},
width: 80
},
{
id: "scol11c",
Header: "Sub Col 11c",
accessor: d => {
return d.firstName;
},
width: 80
},
{
id: "scol11d",
Header: "Sub Col 11d",
accessor: d => {
return d.firstName;
},
width: 80
}
]
},
{
id: "col12",
Header: "Col 12",
columns: [
{
id: "scol12a",
Header: "Sub Col 12",
accessor: d => {
return d.firstName;
},
width: 80
}
]
},
{
id: "col13",
Header: "Col 13",
columns: [
{
id: "scol13a",
Header: "Sub Col 13a",
accessor: d => {
return d.firstName;
},
width: 80
},
{
id: "scol13b",
Header: "Sub Col 13b",
accessor: d => {
return d.firstName;
},
width: 80
},
{
id: "scol13c",
Header: "Sub Col 13c",
accessor: d => {
return d.firstName;
},
width: 80
},
{
id: "scol13d",
Header: "Sub Col 13d",
accessor: d => {
return d.firstName;
},
width: 80
}
]
}
];
// if(this.state.isDisabled) {
// columns.splice(0, 1);
// columns.splice(columns.length - 1, 1);
// }
return columns;
}
/* function (item)*/
getCheckBox(item) {
return (
<div>
<input
value={item.id}
type='checkbox'
checked={item.isChecked}
onClick={(e) => { this.handleCheckChildElement(e); }}
/>
{item.value}
</div>);
}
handleCheckChildElement(event) {
const { items } = this.state.filterItems;
for (let i = 0; i < items.length; i = i + 1) {
if(items[i].id === +event.target.value) {
items[i].isChecked = !items[i].isChecked;
break;
}
}
this.setState({ filterItems: items });
console.log('handleCheckChildElement : > Items : ' + JSON.stringify(filterItems));
}
handleFilterClickinv() {
if(this.state.isCustomizedOpen) {
this.setState({ isCustomizedOpen: false });
}
const currentState = this.state.isFilterOpen;
this.setState({ isFilterOpen: !currentState });
}
handleCustClickinv() {
if(this.state.isFilterOpen) {
this.setState({ isFilterOpen: false });
}
const currentState = this.state.isCustomizedOpen;
this.setState({ isCustomizedOpen: !currentState });
}
resetFilter() {
const { items } = this.state.filterItems;
console.log("In resetFilter this.state.filterItems : " + JSON.stringify(this.state.filterItems));
console.log("In resetFilter : " + items);
for (let i = 0; i < items.length; i = i + 1) {
items[i].isChecked = true;
}
this.setState({ filterItems: items });
console.log('Reset filter : > Items : ' + JSON.stringify(filterItems));
}
render() {
const { data } = this.state;
return (
<div className='dashboard-body-container'>
<div className='hide'> {this.state.activeStepId}</div>
{this.getTopBar()}
{this.state.isCustomizedOpen &&
<CustomizedView
// items={filterItems}
getCheckBox={(item) => { this.getCheckBox(item); }}
// handleCheckChildElement={(event) => { this.handleCheckChildElement(event); }}
resetFilter={this.resetFilter()}
/>}
<div className='whiteBackground'>
{this.getFilterBar()}
<div>
{this.state.isLoading &&
<LoadingComponent />
}
</div>
<div>
<ReactTable
data={data}
columns={this.getColumns()}
showPagination
defaultPageSize={10}
/>
</div>
</div>
</div>
);
}
}
Dashboard.propTypes = {
};
function mapStateToProps(state) {
return {
auth: state.auth
};
}
export default connect(mapStateToProps)(Dashboard);
This is my child component - in my child page (the page in which checkboxes are displayed) I have 4 major functions - getCheckbox - to create checkbox, handlecheckchild - handle the check uncheck events, resetFilter and applyFilter. I have not still finished the code of applyFilter.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { ActionCreators } from '../../../actions';
import ButtonComponent from '../../common/button/ButtonComponent';
class CustomizedView extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
const { items } = this.state;
return (
<div className='DashboardFilter-container-custom' >
<div className='bottomBar'>
<ButtonComponent
text='Apply'
className='activeButton filterMargin-div'
width='100'
display='inline-block'
// onClick={() => { this.props.applyFilter(); }}
/>
<ButtonComponent
text='Reset View'
className='greyedButton clear-div-filter'
width='100'
display='block'
marginTop='60'
onClick={() => { this.props.resetFilter(); }}
/>
</div>
<div>
<div className='column-points-text'>
<span> Columns </span>
</div>
<div className="App">
{items.map((item) => {
return this.props.getCheckBox(item);
})}
</div>
</div>
</div>
);
}
}
CustomizedView.propTypes = {
// items: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
getCheckBox: PropTypes.func.isRequired,
// handleCheckChildElement: PropTypes.func.isRequired,
resetFilter: PropTypes.func.isRequired
};
CustomizedView.defaultProps = {
};
function mapStateToProps(state) {
return {
auth: state.auth
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(ActionCreators, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(CustomizedView);
I have written all the major functions (for operations in child page in my parent and passing those functions as props - getCheckBox and resetFilter from parent page to child page.
I am getting error in the this line of my parent page - Cannot read property 'length' of undefined
for (let i = 0; i < items.length; i = i + 1) {
I am basically a beginner in React. So please help to me understand what is causing the error.
Also tell me whether it is okay to write all child functions in parent page?
Edit 1 - According to Code Maniac's answer
I changed my code in parent to
handleCheckChildElement(event) {
const { filterItems } = this.state;
for (let i = 0; i < filterItems.length; i = i + 1) {
if(filterItems[i].id === +event.target.value) {
filterItems[i].isChecked = !filterItems[i].isChecked;
break;
}
}
this.setState({ filterItems });
console.log('handleCheckChildElement : > Items : ' + JSON.stringify(filterItems));
}
resetFilter() {
const { filterItems } = this.state;
for (let i = 0; i < filterItems.length; i = i + 1) {
filterItems[i].isChecked = true;
}
this.setState({ filterItems });
console.log('Reset filter : > Items : ' + JSON.stringify(filterItems));
}
I am now getting error - The prop resetFilter is marked as required in CustomizedView, but its value is undefined.
I am getting error and warning in an infinite loop.
Edit 2 - if change my code like this
handleCheckChildElement(event) {
const { items } = this.state;
for (let i = 0; i < items.length; i = i + 1) {
if(items[i].id === +event.target.value) {
items[i].isChecked = !items[i].isChecked;
break;
}
}
this.setState({ filterItems: items });
console.log('handleCheckChildElement : > Items : ' + JSON.stringify(filterItems));
}
resetFilter() {
const { items } = this.state;
for (let i = 0; i < items.length; i = i + 1) {
items[i].isChecked = true;
}
this.setState({ filterItems: items });
console.log('Reset filter : > Items : ' + JSON.stringify(filterItems));
}
I am geeting yarn build error - Unused state field: 'filterItems' react/no-unused-state
Well problem in you code is here
const { items } = this.state.filterItems;
You're trying to find a key ( item property ) in array ( fillterItems is an array ) which is why you're getting undefined .
This will be same as below example.
let a = [{v:1},{2:2}];
let {items} = a;
console.log(items)
And what you should do instead to get proper output.
const { filterItems } = this.state;
Demo code
let a = {
items : [{v:1},{2:2}],
itemstemp : "temp"
}
let {items} = a;
console.log(items)
I am trying to filter the list of items in state.items by adding items from state.filterItems to my state.filter array
if I use this.state.items.filter(items => items.cat === 'veg' ) of course this works but I need to be able to filter dynamically using the list of items added to my state.filter array and I'm not sure how to do this,
I would also like to be able select multiple options and then hit a button to apply the filters rather than selecting them one by one
https://www.webpackbin.com/bins/-KoCT_DiT2CNLz8ddr4O
Hello.js
import React, { Component } from 'react';
import logo from './logo.svg'
import './App.css'
import update from 'immutability-helper'
import TodoList from './TodoList'
import styled from 'styled-components'
import FilterList from './FilterList'
const Wrapper = styled.div`
max-width:1280px;
background: papayawhip;
margin: 0 auto;
padding:20px;
`
const Grid = styled.div`
display:flex;
flex-wrap:wrap;
`
const Cell = styled.div`
flex: 0 0 25%;
padding: 20px;
`
export default class hello extends Component {
constructor(props) {
super(props)
this.state = {
items: [
{id: 1, cat: 'fruit', text: 'apples'},
{id: 2, cat: 'fruit', text: 'oranges'},
{id: 3, cat: 'fruit', text: 'peaches'},
{id: 4, cat: 'veg', text: 'carrots'},
{id: 5, cat: 'veg', text: 'aubergine'},
{id: 6, cat: 'veg', text: 'peaches'},
{id: 7, cat: 'bread', text: 'olive bread'},
{id: 8, cat: 'bread', text: 'bread roll'},
{id: 9, cat: 'bread', text: 'bagel'},
],
filterItems: [
{id: 1, text: 'bread'},
{id: 2, text: 'fruit'},
{id: 3, text: 'vegetables'},
],
filter: [
{text: 'bread'}
],
}
}
handleFilterChange = (filter) => {
this.setState({filter: filter})
}
render() {
return (
<Wrapper>
<div>
<FilterList
value={this.state.filter}
onChange={this.handleFilterChange}
filterItems={this.state.filterItems}
/>
</div>
<Grid>
{
this.state.items.filter(items => items.cat === 'veg', 'fruit' )
.map(item =>
<Cell>
{console.log(this.state.filter.text)}
<div>{item.cat}</div>
<div>{item.text}</div>
</Cell>
)
}
</Grid>
</Wrapper>
)
}
}
// <pre>{JSON.stringify(this.state, null, 4)} </pre>
FilterList.js
import React, { Component } from 'react';
import TodoItem from './TodoItem'
import update from 'immutability-helper'
import styled from 'styled-components'
const FilterListBg = styled.div`
background: lightblue;
width: 100%;
height: 60px;
`
const FilterListItem = styled.div`
float: left;
height: 40px;
width: 100px;
padding:10px;
border-right: 1px solid #ff00ff;
`
const FilterBg = styled.div`
width: 100%;
height:40px;
background: #fff;
margin-top:20px;
`
const FilterItem = styled.div`
float: left;
height: 40px;
width: 100px;
padding:10px;
border-right: 1px solid #ff00ff;
`
export default class FilterList extends Component {
constructor() {
super()
this.state = {
search: ''
}
}
handleAdd = (item) => {
const value = update(this.props.value, {
$push: [
{
text: item,
id: Math.random(),
}
]
})
this.props.onChange(value)
}
handleRemove = (index) => {
const value = update(this.props.value, {
$splice: [
[index, 1]
]
})
this.props.onChange(value)
}
handleFilterUpdate = event => {
this.setState({ search: event.target.value })
}
render() {
return (
<div>
<input
type="text"
value={this.state.search}
onChange={this.handleFilterUpdate}
placeholder="Hledat podle nazvu"
/>
{this.state.search}
<FilterListBg>
{
this.props.filterItems.filter(items => items.text.toLowerCase().indexOf(this.state.search.toLowerCase()) >= 0)
.map((item,cat,index) =>
<FilterListItem key={item.id} onClick={()=>this.handleAdd(item.text)}>
{item.text}
</FilterListItem>
)
}
</FilterListBg>
AktivnĂ filtry
<FilterBg>
{
this.props.value.map((item, index) =>
<FilterItem key={item.id} onClick={this.handleRemove}>
{item.text}
</FilterItem>
)
}
</FilterBg>
</div>
)
}
}
Assuming you want to show the items matching your filterList, shouldn't something simple like this work?
const filterTexts = this.state.filter.map(item => item.text);
const itemsToShow = this.state.items.filter(
item => filterTexts.indexOf(item.cat) !== -1);
And then you can map over itemsToShow to create your Cells.
If you want a one-liner to simply copy-paste:
this.state.items.filter(items => this.state.filterItems.map(item => item.text)
.indexOf(items.cat) !== -1 )
.map(item =>
<Cell>
{console.log(this.state.filter.text)}
<div>{item.cat}</div>
<div>{item.text}</div>
</Cell>
)