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"));
Related
I'm trying to convert a class-based component to a functional component. I believe I have the fundamentals for functional-based components in place, but for some reason, useState is not flipping the boolean value when the button is clicked.
Working code:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import BootstrapTable from "react-bootstrap-table-next";
import "bootstrap/dist/css/bootstrap.min.css";
import "react-bootstrap-table-next/dist/react-bootstrap-table2.min.css";
import "./styles.css";
import { Button } from "react-bootstrap";
const products = [
{ id: 1, name: "Item 1", price: 100 },
{ id: 2, name: "Item 2", price: 102 }
];
class App extends Component {
constructor() {
super();
this.state = {
// For displaying data
columns: [
{
dataField: "id",
text: "id",
sort: true
},
{
dataField: "name",
text: "Name",
sort: true
},
{
dataField: "price",
text: "Product Price"
},
{
dataField: "follow",
text: "Follow",
formatter: this.linkFollow,
sort: true
}
],
isFollow: true
};
this.onFollowChanged.bind(this);
}
onFollowChanged() {
this.setState({ isFollow: !this.state.isFollow });
console.log(this.state.isFollow);
}
linkFollow = (cell, row, rowIndex, formatExtraData) => {
return (
<Button
onClick={() => {
this.onFollowChanged(row);
}}
>
Follow
</Button>
);
};
render() {
return (
<div style={{ padding: "20px" }}>
<h1 className="h2">Products</h1>
<BootstrapTable
keyField="id"
data={products}
columns={this.state.columns}
/>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Working demo in sandbox
Non-Working Code:
import React, { useState } from "react";
import BootstrapTable from "react-bootstrap-table-next";
import "bootstrap/dist/css/bootstrap.min.css";
import "react-bootstrap-table-next/dist/react-bootstrap-table2.min.css";
import { Button } from "react-bootstrap";
export default function App() {
function onFollowChanged() {
setIsPresent(!isPresent);
console.log(isPresent);
}
let buttonFollow = (cell, row, rowIndex, formatExtraData) => {
return <Button onClick={() => onFollowChanged(row)}>Present</Button>;
};
const [isPresent, setIsPresent] = useState(true);
const students = [
{
id: 100,
fName: "John",
lName: "Doe",
grade: "first"
},
{
id: 200,
fName: "Jane",
lName: "Doe",
grade: "second"
},
{
id: 300,
fName: "Peter",
lName: "Paker",
grade: "third"
},
{
id: 400,
fName: "Clark",
lName: "Kent",
grade: "fourth"
},
{
id: 500,
fName: "LeBron",
lName: "James",
grade: "fifth"
}
];
const columns = [
{
dataField: "id",
text: "id",
sort: true
},
{
dataField: "fName",
text: "First Name",
sort: true
},
{
dataField: "lName",
text: "Last Name"
},
{
dataField: "grade",
text: "Grade",
sort: true
},
{
dataField: "present",
text: "Present",
formatter: buttonFollow
}
];
return (
<div>
<BootstrapTable keyField="id" data={students} columns={columns} />
</div>
);
}
With my code, when I click the "Present" button the console log keeps printing the initial value of isPresent. I'm expecting it to toggle between true/false.
Non-working demo in sandbox.
You are nearly there, I grabed your code from the sandbox:
const [isPresent, setIsPresent] = useState(true);
function toggleValue() {
setIsPresent(!isPresent);
console.log(isPresent);
}
return (
<div>
<BootstrapTable keyField="id" data={students} columns={columns} />
<button onClick={toggleValue}>Test</button>
{isPresent ? "true" : "false"} // conditional render string value
</div>
);
Resource recommendation: React beta docs
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 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 have json array with id and name property after submiting the form I am getting NaN I want to convert converter code from typescript to Javascript
I created a Playground example
file : Data.js
{ id: 123, name: 'Zootopia' },
{ id: 217, name: 'Captain America' },
{ id: 324, name: 'The Jungle Book' }
];
export class MovieConverter {
constructor(_movies) {
this._movies = _movies;
}
convertFrom(id) {
return this._movies.filter((movie) => movie.id === id)[0].name;
}
convertTo(name) {
return this._movies.filter((movie) => movie.name === name)[0].id;
}
}
Test.vue
<template>
<Page>
<ActionBar :title="Simple">
<NavigationButton text="Back" android.systemIcon="ic_menu_back"
#tap="onNavigationButtonTap"></NavigationButton>
</ActionBar>
<StackLayout>
<Button text="Button" #tap="onSubmit" />
<RadDataForm :source="ticket" :metadata="ticketMetadata" />
</StackLayout>
</Page>
</template>
<script>
import Home from "./Home";
import {
Movies,
MovieConverter
} from "../Data";
//const movies = getMovies();
export default {
methods: {
onNavigationButtonTap() {
this.$navigateTo(Home);
}
},
mounted() {
console.log("movies", Movies);
Movies.map(Movie => {
console.log(Movie.name);
});
},
data() {
return {
ticket: {
movie: 123,
date: "2016-04-06",
time: "20:00",
type: "2D",
price: 9.5,
numberOfTickets: 2,
contactName: null,
contactPhone: null,
contactEmail: null,
agreeTerms: false
},
ticketMetadata: {
isReadOnly: false,
commitMode: "Immediate",
validationMode: "Immediate",
propertyAnnotations: [{
name: "movie",
displayName: "Movie Name",
index: 0,
editor: "Picker",
valuesProvider: Movies.map(Movie => Movie.name),
converter: new MovieConverter(Movies)
},
{
name: "date",
displayName: "Date",
index: 1,
editor: "DatePicker",
hintText: "This is a hint for you"
},
{
name: "time",
displayName: "Time",
index: 2,
editor: "TimePicker"
},
{
name: "type",
displayName: "Type",
index: 3,
editor: "SegmentedEditor",
valuesProvider: ["2D", "3D"]
},
{
name: "price",
displayName: "Price",
index: 4,
editor: "Decimal",
readOnly: true
},
{
name: "numberOfTickets",
displayName: "Number Of Tickets",
index: 5,
editor: "Stepper",
editorParams: {
minimum: 0,
maximum: 20,
step: 2
}
},
{
name: "contactName",
displayName: "Contact Name",
index: 6,
editor: "Text"
},
{
name: "contactPhone",
displayName: "Contact Phone",
index: 7,
editor: "Phone"
},
{
name: "contactEmail",
displayName: "Contact Email",
index: 8,
editor: "Email"
},
{
name: "agreeTerms",
displayName: "I Agree with Terms",
index: 9,
editor: "Switch"
}
]
}
};
},
methods: {
onSubmit() {
console.log("submit", this.ticket.movie);
}
}
};
</script>
<style>
</style>
after onSubmit() of the form I should get 'submit' 123
but getting 'submit' NaN.
I check out the documentation of converter it showing a class with 2 methods convertFrom() & convertTo() which I think is proper not understand as all the documentation is in typescript and I am using javascript.
I'm starting to program in React Native and I have an array like this:
state = {
territories: [
{
id: 1,
number: 1,
title: 'Territory 1',
streets: [
{
id: 1,
name: 'Name of street 1',
houses: [
{
id: 1,
number: '11',
},
{
id: 2,
number: '689',
},
{
id: 3,
number: '117a',
},
],
},
{
id: 2,
nome: 'Name of street 2',
houses: [
{
id: 4,
number: '02',
},
{
id: 5,
number: '655',
},
{
id: 6,
number: '11b',
},
],
},
],
},
],
};
And I want to iterate it with .map() function in order to create a Section List like this example
But I can't iterate house's number array within streets array.
Is there a way to do that with React Native?
Thank you very much in advance
You need a map to iterate through the territories then through streets and houses.
Copy paste the code in codesandbox.io react sandbox. You can fix the html to use a table
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const state = {
territories: [
{
id: 1,
number: 1,
title: "Territory 1",
streets: [
{
id: 1,
name: "Name of street 1",
houses: [
{
id: 1,
number: "11"
},
{
id: 2,
number: "689"
},
{
id: 3,
number: "117a"
}
]
},
{
id: 2,
name: "Name of street 2",
houses: [
{
id: 4,
number: "02"
},
{
id: 5,
number: "655"
},
{
id: 6,
number: "11b"
}
]
}
]
}
]
};
function App() {
return state.territories.map(territory => {
return territory.streets.map(street => {
return (
<div>
<p>{street.name}</p>
{street.houses.map(house => <div>{house.number} </div>)}
</div>
);
});
});
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
I would start by writing a streetRender function, which will get a single street object and render it, by doing street.map, iterating by house. This should be a simple map call.
Now I would write a territoryRender function, which gets a single territory, performing territory.map, iterating by street, and for each street perform
return (streetRender(street));
Last step will be to perform territories.map, and for each territory perform
return (territoryRender(territory))