I do have a problem on my code. What I am trying to do, is that when I want to click on a button, I want that this button become "HIDE" (it's show in the beginning), and show the specific Id's information. I tryed to do it with many example but the others buttons change this specific button too. Then, I didn't find the issue. If someone can help me with it. Thank you very much.
import React, { Component } from "react";
import "./IlkOnbir.css";
export default class IlkOnbir extends Component {
state = {
info: false,
btn: true,
players: [
{
id: 1,
name: "Altay Bayindir",
age: "21",
mevki: "Kaleci",
},
{
id: 2,
name: "Serdar Aziz",
age: "29",
mevki: "Stoper",
},
{
id: 3,
name: "Simon Falette",
age: "23",
mevki: "Stoper",
},
{
id: 4,
name: "Nabil Dirar",
age: "33",
mevki: "Sag Bek",
},
{
id: 5,
name: "Hasan Ali Kaldirim",
age: "32",
mevki: "Sol Bek",
},
{
id: 6,
name: "Emre Belözoglu",
age: "37",
mevki: "Orta Saha",
},
{
id: 7,
name: "Luiz Gustavo",
age: "32",
mevki: "Orta Saha",
},
{
id: 8,
name: "Ozan Tufan",
age: "25",
mevki: "Orta Saha",
},
{
id: 9,
name: "Deniz Türüç",
age: "28",
mevki: "Orta Saha",
},
{
id: 10,
name: "Gary Rodriguez",
age: "29",
mevki: "Kanat",
},
{
id: 11,
name: "Tolga Cigerci",
age: "29",
mevki: "Orta Saha",
},
{
id: 12,
name: "Ferdi",
age: "21",
mevki: "Stoper",
},
{
id: 13,
name: "Mevlüt",
age: "33",
mevki: "Stoper",
},
{
id: 14,
name: "Vedat",
age: "26",
mevki: "Stoper",
},
],
}
showInfo = (i) => {
this.setState({ info: !this.state.info});
}
handleClick = event => {
event.currentTarget.classList.toggle('active');
}
btnDisplay = (e) => {
console.log(e.currentTarget.id);
this.setState({info: !this.state.info, btn:!this.state.btn});
}
render() {
const hideInfo = this.state.info;
const pl = this.state.players.map((player,i) => {
return (
<div key={i} className="card--content movie" onClick={this.handleClick}>
<div className="content">
<img src={player.source} alt="" />
<div class="buttons">
<p
onClick={() => this.showInfo(player[i])} key={player[i]} className="btn effect04 movie" data-sm-link-text="INFO"><span>{this.state.btn === true ? "SHOW" : "HIDE"}</span>
</p>
{hideInfo === true ? (
<div className="opening">
<p>{player.name}</p>
<p>{player.age} </p>
<p>{player.mevki} </p>
</div>
) : (
""
)}
</div>
</div>
</div>
)})
return (
<div className="container">
<section className="card">
{pl}
</section>
</div>
)}}
Each player needs its own info property; right now info applies to all of them.
See working example:
https://codesandbox.io/s/sweet-jang-m3yfe?file=/src/App.js
{
id: 1,
name: "Altay Bayindir",
age: "21",
mevki: "Kaleci",
info: false
}
showInfo = i => {
this.setState(state => ({
...state,
players: state.players.map((player, index) =>
index === i ? { ...player, info: !player.info } : player
)
}));
};
onClick={() => this.showInfo(i)}
{player.info && (
<div className="opening">
<p>{player.name}</p>
<p>{player.age} </p>
<p>{player.mevki} </p>
</div>
)}
Related
So I made an array of object and map the array. I also make a simple collapsible.
The thing is, the collapsible didn't work correctly. It should only show the content where the user clicked on. i.e. when the user click the button belongs to John Doe, the collapsible should show the status belongs to him. What happen to my code is, it shows everyone's status. I have tried with key={index} but still no result.
Here's my code so far...
import { useState } from "react";
const App = () => {
const [showCollapsible, setShowCollapsible] = useState(false);
const myDatas = [
{
id: 1,
fullName: "John Doe",
age: 28,
status: "On Duty",
},
{
id: 2,
fullName: "Jane Doe",
age: 27,
status: "Rest",
},
{
id: 3,
fullName: "James Doe",
age: 32,
status: "Take a leave",
},
];
return (
<div>
{myDatas.map((data, index) => {
return (
<div>
<p>{data.fullName}</p>
<p>{data.age}</p>
<button
key={index}
onClick={() => setShowCollapsible(!showCollapsible)}
>
Status
</button>
{showCollapsible && <div>{data.status}</div>}
</div>
);
})}
</div>
);
};
export default App;
You are using the same single boolean state to toggle all of the collapsible divs. Instead, store some state that uniquely identifies a mapped element, like the data's id property. Use the id to check if the div should be collapsed or visible.
const App = () => {
const [showCollapsible, setShowCollapsible] = useState({});
const myDatas = [
{
id: 1,
fullName: "John Doe",
age: 28,
status: "On Duty"
},
{
id: 2,
fullName: "Jane Doe",
age: 27,
status: "Rest"
},
{
id: 3,
fullName: "James Doe",
age: 32,
status: "Take a leave"
}
];
const toggleCollapsable = (id) => () => {
setShowCollapsible((set) => ({
...set,
[id]: !set[id]
}));
};
return (
<div>
{myDatas.map((data) => {
return (
<div>
<p>{data.fullName}</p>
<p>{data.age}</p>
<button onClick={toggleCollapsable(data.id)}>Status</button>
{showCollapsible[data.id] && <div>{data.status}</div>}
</div>
);
})}
</div>
);
};
It would be a little more clean to abstract a Collapsible component that manages that state.
const CollapsibleDiv = ({ children }) => {
const [showCollapsible, setShowCollapsible] = useState(false);
return (
<>
<button onClick={() => setShowCollapsible((show) => !show)}>
Status
</button>
{showCollapsible && children}
</>
);
};
const App = () => {
const myDatas = [
{
id: 1,
fullName: "John Doe",
age: 28,
status: "On Duty"
},
{
id: 2,
fullName: "Jane Doe",
age: 27,
status: "Rest"
},
{
id: 3,
fullName: "James Doe",
age: 32,
status: "Take a leave"
}
];
return (
<div>
{myDatas.map((data) => {
return (
<div>
<p>{data.fullName}</p>
<p>{data.age}</p>
<CollapsibleDiv>
<div>{data.status}</div>
</CollapsibleDiv>
</div>
);
})}
</div>
);
};
I am trying to render an icon only if collection.masterAssetId === asset.id. I am using a getMaster function to find the collection.masterAssetId. The problem that I am having is that the collectionsarr can be undefined in my getMaster function, but also return a number. I have this error: Uncaught TypeError: Cannot read property 'masterAssetId' of undefined. Would be great if someone could fix this error for me?
Secondly, I am probably making this way too complicated, so feel free to suggest a different approach.
App.js
import React from 'react';
import './App.css';
import {collections} from "./data.js"
import {assets} from "./data.js"
import {FontAwesome, FaStar} from "react-icons/fa"
class App extends React.Component {
constructor() {
super()
this.state = {
collectionsarr: collections,
assetsarr: assets,
clickedassets: []
}
}
getMasterId(assetnr){
const assetnum = ""
if(this.state.collectionsarr.filter(element => element.masterAssetId === assetnr) === undefined){
const assetnum = 0
} else {
const assetnum = this.state.collectionsarr.filter(element => element.masterAssetId === assetnr)[0].masterAssetId
}
return assetnum
}
render(){
return (
<div className="App">
<h1>Sitecore coding challenge</h1>
<div className="left">
{this.state.collectionsarr.map(element =>
<div key={element.id}>
<p onClick={()=>this.handleAssetsClick(element.id)}>{element.name}</p>
<img src={this.getAssetPath(element.masterAssetId)} alt="pic"/>
<br></br>
</div>
)}
</div>
<div className="right">
{this.state.clickedassets.map(asset =>
<div key={asset.id}>
<img src={require(`./${asset.path}`)} alt="pic"/>
<p>{asset.name}</p>
<p>{asset.id}</p>
<button onClick={() => this.makeMaster(asset.id)}>Make master!</button>
<p>icon "this is the master</p>
{asset.id === this.getMasterId(asset.id) && <FaStar />}
<br></br>
</div>
)}
</div>
</div>
)
}
}
export default App
data.js
const collections = [
{
id: 1,
name: "The Simpsons",
masterAssetId: 13,
tags: {
name: "Cartoon",
subTag: {
name: "Simpsons family",
subTag: {
name: "2014",
},
},
},
},
{
id: 2,
name: "Super heroes",
masterAssetId: 24,
tags: {
name: "DC Super heroes",
subTag: {
name: "2014",
},
},
},
{
id: 3,
name: "Toy story",
masterAssetId: 31,
tags: {
name: "Disney",
subTag: {
name: "Pixar",
subTag: {
name: "Original movie",
subTag: {
name: "2010",
},
},
},
},
},
{
id: 4,
name: "Ninjago",
masterAssetId: 42,
tags: {
name: "Ninja",
subTag: {
name: "Secret Ninja Force",
subTag: {
name: "2017",
},
},
},
},
];
const assets = [
{
id: 11,
name: "Homer Simpson",
path: "Homer.jpg",
collectionId: 1,
},
{
id: 12,
name: "Lisa Simpson",
path: "Lisa.jpg",
collectionId: 1,
},
{
id: 13,
name: "Bart Simpson",
path: "Bart.jpg",
collectionId: 1,
},
{
id: 14,
name: "Marge Simpson",
path: "Marge.jpg",
collectionId: 1,
},
{
id: 15,
name: "Grampa Simpson",
path: "Grampa.jpg",
collectionId: 1,
},
{
id: 16,
name: "Maggie Simpson",
path: "Maggie.jpg",
collectionId: 1,
},
{
id: 21,
name: "Green Lantern",
path: "Green lantern.jpg",
collectionId: 2,
}
];
Is the collections data being set properly? What's the console.log() output of the state at render?
At any rate, I think the better approach for setting state is to do it in componentDidMount() lifecycle method:
import {getCollection} from "./data.js";
state = {
collectionsarr: [],
assetsarr: [],
clickedassets: []
},
componentDidMount = () => {
this.setState({
collectionsarr: getCollection()
});
}
data.js:
const collections = [...];
export function getCollection() {
return collections;
}
Change your getMasterId function
showIcon(assetnr) {
let index = (this.state.collectionsarr || []).findIndex(item => {
return item.masterAssetId === assetnr;
})
return index != -1;
}
This function will return true if assetId === masterId then You can render it as
{this.showIcon(asset.id) && <FaStar />}
I have the following code below which displays records from an array and is working fine. now I want to add ability to search data
and I have added the following script to enable the search
filterRecord = record =>
record.name.toUpperCase().indexOf(this.state.searchdata.toUpperCase()) >
-1 ||
record.Age.indexOf(this.state.searchdata) > -1 ||
record.gender.toUpperCase().indexOf(this.state.searchdata.toUpperCase()) >
-1;
I have also tried
filterRecord = (record) => (record.name.indexOf(this.state.searchdata) > -1 ||
record.Age.indexOf(this.state.searchdata) > -1 ||
record.gender.indexOf(this.state.searchdata) > -1);
both code give error unexpected token pointing at equal to (=) at this line filterRecord =
here is the screenshot
Here is the full code
class Application extends React.Component {
constructor(props) {
super(props);
this.filterRecord = this.filterRecord.bind(this);
this.handleChange = this.handleChange.bind(this);
this.state = {
rec: [
{ name: "Tony", Age: "18", gender: "male" },
{ name: "John", Age: "21", gender: "female" },
{ name: "Luke", Age: "78", gender: "male" },
{ name: "Mark", Age: "90", gender: "female" },
{ name: "Jame", Age: "87", gender: "female" },
{ name: "Franco", Age: "34", gender: "male" },
{ name: "Franco", Age: "34", gender: "male" },
{ name: "Biggard", Age: "19", gender: "male" },
{ name: "tom", Age: "89", gender: "female" }
],
value: "",
searchdata: ""
};
}
handleChange(event) {
this.setState({ [event.target.name]: event.target.value });
}
filterRecord = record =>
record.name.toUpperCase().indexOf(this.state.searchdata.toUpperCase()) >
-1 ||
record.Age.indexOf(this.state.searchdata) > -1 ||
record.gender.toUpperCase().indexOf(this.state.searchdata.toUpperCase()) >
-1;
render() {
return (
<div>
<div>
<h3>Search/Filter Records by name, Age and gender</h3>
<input
type="text"
placeholder="Search by name, Age and gender"
id="searchdata"
name="searchdata"
type="text"
value={this.state.searchdata}
onChange={this.handleChange}
/>
<ul>
{this.state.rec.filter(this.filterRecord).map((obj, i) => (
<li key={i}>
{obj.name} - {obj.Age} - {obj.gender}
</li>
))}
</ul>
</div>
</div>
);
}
}
It works well.
I think you didn't install babel and es6/es2015.
class App extends React.Component {
constructor(props) {
super(props);
this.filterRecord = this.filterRecord.bind(this);
this.handleChange = this.handleChange.bind(this);
this.state = {
rec: [
{ name: "Tony", Age: "18", gender: "male" },
{ name: "John", Age: "21", gender: "female" },
{ name: "Luke", Age: "78", gender: "male" },
{ name: "Mark", Age: "90", gender: "female" },
{ name: "Jame", Age: "87", gender: "female" },
{ name: "Franco", Age: "34", gender: "male" },
{ name: "Franco", Age: "34", gender: "male" },
{ name: "Biggard", Age: "19", gender: "male" },
{ name: "tom", Age: "89", gender: "female" }
],
value: "",
searchdata: ""
};
}
handleChange(event) {
this.setState({ [event.target.name]: event.target.value });
}
filterRecord = record =>
(record.name.toUpperCase().indexOf(this.state.searchdata.toUpperCase()) >
-1 ||
record.Age.indexOf(this.state.searchdata) > -1 ||
record.gender.toUpperCase().indexOf(this.state.searchdata.toUpperCase()) >
-1);
render() {
return (
<div>
<div>
<h3>Search/Filter Records by name, Age and gender</h3>
<input
type="text"
placeholder="Search by name, Age and gender"
id="searchdata"
name="searchdata"
type="text"
value={this.state.searchdata}
onChange={this.handleChange}
/>
<ul>
{this.state.rec.filter(this.filterRecord).map((obj, i) => (
<li key={i}>
{obj.name} - {obj.Age} - {obj.gender}
</li>
))}
</ul>
</div>
</div>
);
}
}
ReactDOM.render( < App / > , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I might be silly here but i think your syntax for arrow function is wrong. You didnt wrap your function body in curly braces.
Try this:
filterRecord = (record) => {
return (record.name.toUpperCase().indexOf(this.state.searchdata.toUpperCase()) > -1 ||
record.Age.indexOf(this.state.searchdata) > -1 ||
record.gender.toUpperCase().indexOf(this.state.searchdata.toUpperCase()) > -1);
}
Hope this helps!!
I am trying to create Simple Table with react.I am importing CustomerList and then looping through all the Object.keys to get the table header first and then the body part.
When console logging I can see all my customerList properties are there but when console.loging the Object.keys it shows 'undefined', I don't understand where I am making the silly mistake.
Will be gratefull for all the help I can get.
Thanks in Advance!
I have tried Google and youtube but not getting the answer I am looking for
export const customerList = [
{
name: "Anny Larsson",
age: 23,
id: 1,
title: "Title1",
accountNumber: "12345",
address: "Stockholm 14, Stockholm Sweden",
hobbyList:["coding", "writing", "reading", "skiing"],
emptyColumn: ""
},
{
name: "Helena hel",
age: 20,
id:2,
title: "Title2",
accountNumber: "22245",
address: "Stockholm City, Stockholm Sweden",
hobbyList:["coding", "Cooking", "games", "skiing"],
emptyColumn: ""
},
{
name: "Ayesha AAA",
age: 25,
id: 3,
title: "Title3",
accountNumber: "09845",
address: "Stockholm 21, Stockholm Sweden",
hobbyList:["coding", "Cooking", "games", "skiing"],
emptyColumn: ""
},
//more list goes here......
// ...............
];
export default customerList;
// My customerListTable.js
import React, { Component } from 'react';
import CustomerList from './CustomerList';
import CustomerTitle from './CustomerTitle';
class CustomerListTable extends Component {
state = {
customerList: CustomerList
}
componentDidMount(){
this.setState({
customerList: [...this.state.customerList] //copying the list
})
};
headerTitle = Object.keys(this.state.customerList[0]).map((header , index) => {
console.log("columnHeaderTitles ", this.headerTitle )
// return (
// <li>{header}</li>
// )
})
render() {
console.log("customer list", this.state.customerList)
console.log("table header", this. headerTitle);
return (
<div>
<h1>Customer table....</h1>
<div>
<CustomerTitle />
<table>
<thead>
<tr>
<th>{this.headerTitle}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
);
}
}
export default CustomerListTable;
const customerList = [
{
name: "Anny Larsson",
age: 23,
id: 1,
title: "Title1",
accountNumber: "12345",
address: "Stockholm 14, Stockholm Sweden",
hobbyList:["coding", "writing", "reading", "skiing"],
emptyColumn: ""
}
];
const headerTitle = Object.keys(customerList[0]).map((header , index) => header)
console.log(headerTitle)
In Thead Table, map headerTitle to create dynamic th:
<thead>
<tr>
{
this.headerTitle.map((item, index) => <th key={index}>{item}</th>)
}
</tr>
</thead>
I think you are overcomplicating your logic, but your code seems to work.
Only returning something inside your map function adds the headers to the component:
const CustomerList = [
{
name: "Anny Larsson",
age: 23,
id: 1,
title: "Title1",
accountNumber: "12345",
address: "Stockholm 14, Stockholm Sweden",
hobbyList: [
"coding", "writing", "reading", "skiing"
],
emptyColumn: ""
}, {
name: "Helena hel",
age: 20,
id: 2,
title: "Title2",
accountNumber: "22245",
address: "Stockholm City, Stockholm Sweden",
hobbyList: [
"coding", "Cooking", "games", "skiing"
],
emptyColumn: ""
}, {
name: "Ayesha AAA",
age: 25,
id: 3,
title: "Title3",
accountNumber: "09845",
address: "Stockholm 21, Stockholm Sweden",
hobbyList: [
"coding", "Cooking", "games", "skiing"
],
emptyColumn: ""
}
];
class CustomerListTable extends React.Component {
state = {
customerList: CustomerList
}
headerTitle = Object.keys(this.state.customerList[0]).map((header) => {
return (<li key={header}>{header}</li>)
})
render() {
return (<div>
<h1>Customer table....</h1>
<div>
<table>
<thead>
<tr>
<th>{this.headerTitle}</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>);
}
}
ReactDOM.render(<CustomerListTable/>, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="root"></div>
I'm working on a simple table using reactjs and ant design.
My plan is to add and remove a new item on the list on button click.
My problem is I don't know how to do that.
I tried to follow this thread but no luck.
Hope you understand me.
Thanks.
sample code
function remove() {
console.log("remove");
}
function add() {
console.log("add");
}
const columns = [
{
title: "Num",
dataIndex: "num"
},
{
title: "Name",
dataIndex: "name"
},
{
title: "Age",
dataIndex: "age"
},
{
title: "Address",
dataIndex: "address"
}
];
const data = [
{
key: "1",
num: 1,
name: "John Brown",
age: 32,
address: "New York No. 1 Lake Park"
},
{
key: "2",
num: 2,
name: "Jim Green",
age: 42,
address: "London No. 1 Lake Park"
},
{
key: "3",
num: 3,
name: "Joe Black",
age: 32,
address: "Sidney No. 1 Lake Park"
}
];
<Table pagination={false} columns={columns} dataSource={data} />
<Button type="primary" onClick={add}>
add
</Button>
<Button type="danger" onClick={remove}>
remove
</Button>
You need to use react state. State holds the data, when you want to add or remove, update this state and react with re-render the table.
I have updated your code. On click of add a new random row is added. On click of remove last row is removed.
CodeSandbox
import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Table, Button } from "antd";
function remove() {
console.log("remove");
}
const columns = [
{
title: "Num",
dataIndex: "num"
},
{
title: "Name",
dataIndex: "name"
},
{
title: "Age",
dataIndex: "age"
},
{
title: "Address",
dataIndex: "address"
}
];
let data = [
{
key: "1",
num: 1,
name: "John Brown",
age: 32,
address: "New York No. 1 Lake Park"
},
{
key: "2",
num: 2,
name: "Jim Green",
age: 42,
address: "London No. 1 Lake Park"
},
{
key: "3",
num: 3,
name: "Joe Black",
age: 32,
address: "Sidney No. 1 Lake Park"
}
];
export default class MyTable extends React.Component {
constructor(props) {
super(props);
this.state = {
data: data
};
}
add = () => {
var row = {
key: "99",
num: 99,
name: "I am New",
age: 32,
address: "New Address"
};
var newStateArray = [...this.state.data];
newStateArray.push(row);
this.setState(() => {
return {
data: newStateArray
};
});
}
remove = () => {
var newStateArray = [...this.state.data];
if(newStateArray.length > 1) {
newStateArray.pop();
}
this.setState(() => {
return {
data: newStateArray
};
});
}
render() {
return (
<div>
<Table
pagination={false}
columns={columns}
dataSource={this.state.data}
/>
<Button type="primary" onClick={this.add}>
add
</Button>
<Button type="danger" onClick={this.remove}>
remove
</Button>
</div>
);
}
}
ReactDOM.render(<MyTable />, document.getElementById("container"));