I'm new in React and I have to create a CRUD table for my DB.
I created a simple table as you can see:
class ListPromoCatalog extends React.Component {
constructor(props) {
super(props);
this.state = {
promos: [],
message: null
};
this.refreshPromo = this.refreshPromo.bind(this)
}
componentDidMount() { //React defines a component lifecycle
this.refreshPromo();
}
refreshPromo() {
PromoCatalogService.retrieveAllPromo(PRIZES)//this would make the call to the REST API.
.then(
response => {
console.log(response);
this.setState({promos: response.data.viaggio})
}
)
}
PromoOffClicked(id) {
PromoCatalogService.promoOff(PRIZES, id)
.then(
response => {
console.log(response);
this.setState({message: `Promo ${id} OFF Successful`});
this.refreshPromo();
}
)
}
updatePromoClicked(id) {
console.log('update ' + id);
this.props.history.push(`/promos/${id}`);
}
addCourseClicked() {
this.props.history.push(`/promos/-1`);
}
render() {
return (
<div className="container">
<h3>All Promo</h3>
<div className="row">
<FileUploader/>
</div>
{this.state.message && <div className="alert alert-success">{this.state.message}</div>}
<div className="container">
<table className="table">
<thead>
<tr>
<th>Id</th>
<th>Item</th>
<th>Title</th>
<th>Description</th>
<th>Delete</th>
<th>Update</th>
</tr>
</thead>
<tbody>
{
this.state.promos.map(
promo =>
<tr key={promo.promoId}>
<td>{promo.promoId}</td>
<td>{promo.ijCod}</td>
<td>{promo.title}</td>
<td>{promo.description}</td>
<td>
<button className="btn btn-warning"
onClick={() => this.PromoOffClicked(promo.promoId)}>OFF
</button>
</td>
<td>
<button className="btn btn-success"
onClick={() => this.updatePromoClicked(promo.promoId)}>Update
</button>
</td>
</tr>
)
}
</tbody>
</table>
<div className="row">
<button className="btn btn-success" onClick={this.addCourseClicked}>Add</button>
</div>
</div>
</div>
)
}
}
export default ListPromoCatalog
I would like to do the same thing with a Material Table but I don't know how to put data and methods in my new class.
I would like to do the same thing with a Material Table but I don't know how to put data and methods in my new class.
render() {
return (
<>
<PanelHeader size="sm"/>
<div className="content">
<Row>
<Col xs={12}>
<Card>
<CardHeader>
<CardTitle tag="h4">Simple Table</CardTitle>
</CardHeader>
<CardBody>
<MDBDataTable
striped
bordered
small
data={data} //DATA SHOULD CONTAIN HEADERS AND COLUMNS
/>
</CardBody>
</Card>
</Col>
</Row>
</div>
</>
);
}
Related
can you please help me? i read that in routes the components need to change to elements but it still doesn't
render.
the page will not render the root path at localhost:3000/.
error message
react-dom.development.js:26091 Uncaught Error: Target container is not a DOM element.
App.js
import { render } from "react-dom";
import {
BrowserRouter,
Routes,
Route,
} from "react-router-dom";
import App from "./App";
import CreateBook from "./components/CreateBook";
import ShowBookDetails from "./components/ShowBookDetails";
import UpdateBookInfo from "./components/UpdateBookInfo";
const rootElement = document.getElementById("/");
render(
<BrowserRouter>
<Routes>
<Route path="/" element={<ShowBookDetails />} />
<Route path="create-book" element={<CreateBook />} />
<Route path="edit-book" element={<UpdateBookInfo />} />
</Routes>
</BrowserRouter>,
rootElement
);
export default App;
components/ShowBookDetails.js
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import '../App.css';
import axios from 'axios';
class showBookDetails extends Component {
constructor(props) {
super(props);
this.state = {
book: {}
};
}
componentDidMount() {
// console.log("Print id: " + this.props.match.params.id);
axios
.get('http://localhost:8082/api/books/'+this.props.match.params.id)
.then(res => {
// console.log("Print-showBookDetails-API-response: " + res.data);
this.setState({
book: res.data
})
})
.catch(err => {
console.log("Error from ShowBookDetails");
})
};
onDeleteClick (id) {
axios
.delete('http://localhost:8082/api/books/'+id)
.then(res => {
this.props.history.push("/");
})
.catch(err => {
console.log("Error form ShowBookDetails_deleteClick");
})
};
render() {
const book = this.state.book;
let BookItem = <div>
<table className="table table-hover table-dark">
{/* <thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead> */}
<tbody>
<tr>
<th scope="row">1</th>
<td>Title</td>
<td>{ book.title }</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Author</td>
<td>{ book.author }</td>
</tr>
<tr>
<th scope="row">3</th>
<td>ISBN</td>
<td>{ book.isbn }</td>
</tr>
<tr>
<th scope="row">4</th>
<td>Publisher</td>
<td>{ book.publisher }</td>
</tr>
<tr>
<th scope="row">5</th>
<td>Published Date</td>
<td>{ book.published_date }</td>
</tr>
<tr>
<th scope="row">6</th>
<td>Description</td>
<td>{ book.description }</td>
</tr>
</tbody>
</table>
</div>
return (
<div className="ShowBookDetails">
<div className="container">
<div className="row">
<div className="col-md-10 m-auto">
<br /> <br />
<Link to="/" className="btn btn-outline-warning float-left">
Show Book List
</Link>
</div>
<br />
<div className="col-md-8 m-auto">
<h1 className="display-4 text-center">Book's Record</h1>
<p className="lead text-center">
View Book's Info
</p>
<hr /> <br />
</div>
</div>
<div>
{ BookItem }
</div>
<div className="row">
<div className="col-md-6">
<button type="button" className="btn btn-outline-danger btn-lg btn-block" onClick={this.onDeleteClick.bind(this,book._id)}>Delete Book</button><br />
</div>
<div className="col-md-6">
<Link to={`/edit-book/${book._id}`} className="btn btn-outline-info btn-lg btn-block">
Edit Book
</Link>
<br />
</div>
</div>
{/* <br />
<button type="button" class="btn btn-outline-info btn-lg btn-block">Edit Book</button>
<button type="button" class="btn btn-outline-danger btn-lg btn-block">Delete Book</button> */}
</div>
</div>
);
}
}
export default showBookDetails;
you should write components name with uppercase:
class showBookDetails extends Component - class ShowBookDetails extends Component
TableItem component added without any data in UI. Could somebody help on this. On refereshing the UI, added data is shown with details in TableItem component.
Table Component Code
import TableItem from "./TableItem";
function Table({ searchWord }) {
const dispatch = useDispatch();
const dictData = useSelector((state) => state.dictionary);
useEffect(() => {
dispatch(getDictionaryAsync());
}, [dispatch]);
return (
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Word</th>
<th scope="col">Description</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{dictData &&
dictData
.filter((e) =>
searchWord === ""
? e
: e.word &&
e.word.toLowerCase().includes(searchWord.toLowerCase())
)
.map((item) => (
<TableItem item={item} key={item.id} searchWord={searchWord} />
))}
</tbody>
</table>
);
}
export default Table;
Below is the TableItem Component Code which i am trying to update,
When i add a word to dictionary it will fetch the details from the server and display it in the React app.
function TableItem({ item }) {
const [modal, setModal] = useState(false);
const openModal = () => {
setModal(true);
};
return (
<>
<tr key={item.id}>
<td style={{ textTransform: "capitalize" }}>{item.word}</td>
<td>
<b style={{ textTransform: "capitalize" }}>
{item.items && item.items[0].category} -{" "}
</b>
{item.items && truncate(item.items[0].definitions[0])}
</td>
<td>
<button className="btn btn-danger btn-sm " onClick={openModal}>
View
</button>
</td>
</tr>
<Modal isOpen={modal} ariaHideApp={true}>
<div className="modal-header">
<h3 className="modal-word-header">
{item.word && item.word.toUpperCase()}
</h3>
<button
className="btn btn-danger btn-sm"
onClick={() => setModal(false)}
>
<i class="fa fa-times" aria-hidden="true"></i>
</button>
</div>
<div className="model-content">
<p>
{item.items &&
item.items.map((e) => {
return (
<>
<i>{e.category}</i>
<ul>
{e.definitions.map((def) => {
return <li>{def}</li>;
})}
</ul>
</>
);
})}
</p>
</div>
</Modal>
</>
);
}
Better add your TableItem component code!
Below code works fine and updated the UI on change in the Data in TableItem,
useEffect(() => {
dispatch(getDictionaryAsync());
}, [dispatch, dictData]); *<--updated code*
I got a table, filled by data coming from my API, I'm learning React and come to the solution in several tries.
Now I got the data printed in my table, but, these data is repeated three times (as the rows number multiplied by row number).
Here is my code:
import React from "react";
// reactstrap components
import {Card, CardHeader, CardBody, Row, Col, Breadcrumb, BreadcrumbItem, CardTitle, Button, Table} from "reactstrap";
// core components
import PanelHeader from "components/PanelHeader/PanelHeader.jsx";
class Registries extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoaded: false,
error: null,
articles: [],
};
}
componentDidMount() {
fetch('http://127.0.0.1:8004/api/articles/all/')
.then(results => {
return results.json();
})
.then(data => {
let articles = data.map((row) => {
return(
<tr key={row.id}>
<td>{row.id}</td>
<td>{row.name}</td>
<td>{row.category}</td>
<td style={{width:"106px"}}>
<Button size={"sm"} color={"warning"}>
<i className={"fa fa-edit"} />
</Button>
<Button size={"sm"} color={"danger"}>
<i className={"fa fa-trash"} />
</Button>
</td>
</tr>
)
});
this.setState({
isLoaded: true,
articles: articles
});
console.log(articles);
})
}
render() {
return (
<>
<PanelHeader size="sm" />
<div className="content">
<Row>
<Col xs={12}>
<Card>
<CardHeader>
<Breadcrumb>
<BreadcrumbItem>Home</BreadcrumbItem>
<BreadcrumbItem active>Articoli</BreadcrumbItem>
</Breadcrumb>
<Row>
<Col xs="10">
<CardTitle tag="h4">Articoli</CardTitle>
</Col>
<Col xs="2">
<Button icon="ui-1_simple-add" size="lg" color="success" outline className={"btn-block"}>
<i className={"fa fa-plus"} /> Nuovo
</Button>
</Col>
</Row>
</CardHeader>
<CardBody>
<Table data={this.state.articles} responsive className={"table-hover"}>
<thead className="text-primary">
<tr>
<th>ID</th>
<th>Nome</th>
<th>Categoria</th>
<th style={{width:"106px"}}>Opzioni</th>
</tr>
</thead>
<tbody>
{this.state.articles.map((prop, key) => {
if(this.state.error) {
return(<div>Error: {this.state.error.message}</div>);
}
else if(this.state.isLoaded === false) {
return(
<div>
<i className={"fa fa-spin fa-spinner"}/>
<br/>
Caricamento...
</div>
);
}
else if(this.state.articles) {
return (
<>
{this.state.articles.map((prop, key) => {
return <>{prop}</>;
})}
</>
);
}
})}
</tbody>
</Table>
</CardBody>
</Card>
</Col>
</Row>
</div>
</>
);
}
}
export default Registries;
Here is how the table looks like:
The goal is to get only 3 rows, as the API return
You are calling this.state.articles.map in another this.state.articles.map in your render function.
Try to refactor this part of code:
{this.state.articles.map((prop, key) => {
if(this.state.error) {
return(<div>Error: {this.state.error.message}</div>);
}
else if(this.state.isLoaded === false) {
return(
<div>
<i className={"fa fa-spin fa-spinner"}/>
<br/>
Caricamento...
</div>
);
}
else if(this.state.articles) {
return (
<>
{this.state.articles.map((prop, key) => {
return <>{prop}</>;
})}
</>
);
}
})}
One of possible refactorings could be like this:
{
this.state.error ?
(<div>Error: {this.state.error.message}</div>) :
(
this.state.isLoaded === false ?
(
<div>
<i className={"fa fa-spin fa-spinner"}/>
<br/>
Caricamento...
</div>
) :
(
this.state.articles && this.state.articles.map((prop, key) => {
return (<>{prop}</>);
})
)
)
}
My aim is to have my modal dialog box pop up on click. However, I receive this error every time I execute:
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See fb.me/react-invalid-hook-call for tips about how to debug and fix this problem
May I have some direction on where I am going wrong with this?
import React from 'react';
import { connect } from 'react-redux';
import { myActions } from './actions/my.actions';
import { Modal, Button } from 'react-bootstrap';
class LoadTable extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
Search: "Search",
visible: false
}
this.doSearch = this.doSearch.bind(this);
this.handleShow = this.handleShow.bind(this);
this.handleClose = this.handleClose.bind(this);
this.runstuff = this.runstuff(this);
}
componentDidMount() {
this.props.getstuff()
.then((res) => {
this.setState({
data: res.results.response || [], <--IT shows in the error that it breaks here.
visible: false
})
});
}
doSearch(e) {
const { name, value } = e.target;
this.setState({ [name]: value });
console.log("Search");
}
handleShow() {
this.setState({ visible: true });
}
handleClose() {
this.setState({ visible: false });
}
runstuff() {
}
render() {
const { data, Search } = this.state;
return data.length > 0 ? (
<div className="row row-centered">
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12 col-centered">
<div id="Search" className="row col-xs-5 col-lg-2">
<div className="form-group">
<input className='form-control' type="text" placeholder="Search" name="Search" value={Search} onChange={this.doSearch} autoFocus />
</div>
</div>
<table className="table table-striped">
<thead>
<tr>
<td>Name</td>
<td>stuff</td>
<td>Start</td>
<td>End</td>
<td>Status</td>
<td></td>
<td></td>
</tr>
</thead>
<tbody>
{
data.map((dt) => {
return (
<tr>
<td>{dt.name}</td>
<td>{dt.stuff}</td>
<td>{dt.start}</td>
<td>{dt.end}</td>
{ dt.status ?
<td>
<div className="alert alert-success" role="alert"></div>
</td>
:
<td>
<div className="alert alert-danger" role="alert"></div>
</td>
}
<td><button type="button" className="btn btn-primary" onClick={this.runStuff}>Run Stufff</button></td>
<td><button type="button" className="btn btn-info" onClick={this.displayLog}><View Stuff</button></td>
<Modal
show={this.state.visible}
onHide={this.handleClose}
>
<Modal.Header closeButton>
<Modal.Title>Run Stuff for Stuff</Modal.Title>
</Modal.Header>
<Modal.Body>
<div>{dt.lotsofstuff}</div>
</Modal.Body>
<Modal.Footer>
<Button
variant="secondary"
onClick={this.handleClose}
>
Close
</Button>
<Button variant="primary" onClick={this.handleClose}>
Download
</Button>
</Modal.Footer>
</Modal>
</tr>
);
})
}
</tbody>
</table>
</div>
</div>
) :
<div className="row">
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>No Data to Display at the moment</p>
</div>
</div>;
}
}
function mapStateToProps(state) {
return {
};
}
const mapDispatchToProps = dispatch => ({
getstuff: () => dispatch(myActions.getstuff())
});
export default connect(mapStateToProps, mapDispatchToProps)(myLoad);
There is a 'Print' button on SaleInvoice.js which shows the Modal containing Report.js.
Report.js is created only to describe how and what should be displayed in the printed page.
Report.js has a button 'Print' which opens the Print Preview in the browser.
How do I make the 'Print' button on SaleInvoice.js directly open the Print Preview in the browser?
SaleInvoice.js
...
<button
style={{marginRight: '200px'}}
onClick={() => this.setState({printView: true})}>
Print
</button>
{this.state.printView ? (
<Modal
type="Print"
{...this.props}
show={this.state.printView}
modalClosed={() => this.setState({printView: false})}
/>
) : null}
...
Report.js
import React from 'react';
import styles from './SaleInvoice.module.css';
const SaleInvoice = props => {
const {customerName} = props;
const rows = props.lineItems;
const alignRightMarginRight = [styles.alignRight, styles.marginRight].join(
' ',
);
const {amountBeforeFreight, freight, amountAfterFreight} = props;
const reverseDateString = date => {
let [yyyy, mm, dd] = date.split('-');
return dd + '-' + mm + '-' + yyyy;
};
const renderContent = () => {
let i = 0;
let contentRows = (i, d) => {
return (
<React.Fragment>
<td className={styles.serialNumber}>{i}</td>
<td className={styles.productName}>{d.product_name}</td>
<td className={alignRightMarginRight}>{d.product_qty}</td>
<td className={alignRightMarginRight}>{d.product_unit}</td>
<td className={alignRightMarginRight}>{d.product_rate}</td>
<td className={alignRightMarginRight}>{d.product_disc}</td>
<td className={alignRightMarginRight}>{d.sub_total}</td>
</React.Fragment>
);
};
return rows.map(d => {
i++;
if (i === rows.length) {
return null;
}
if (i % 10 === 0) {
return (
<tr key={i} className={styles.pagebreak}>
{contentRows(i, d)}
</tr>
);
} else {
return <tr key={i}>{contentRows(i, d)}</tr>;
}
});
};
return (
<React.Fragment>
<div className={styles.all}>
<div className={[styles.header].join(' ')}>
<button className={styles.hideInPrint} onClick={window.print}>
Print
</button>
<button className={styles.hideInPrint} onClick={props.modalClosed}>
Close
</button>
<h5 className={styles.docTitle}>Estimate</h5>
<h6 className={styles.customerName}>
{customerName}
<span className={styles.date}>
{reverseDateString(props.date.split('T')[0])}
</span>
</h6>
</div>
<table className={styles.content}>
<thead>
<tr>
<td>No</td>
<td>Name</td>
<td className={alignRightMarginRight}>Qty</td>
<td className={alignRightMarginRight}>Unit</td>
<td className={alignRightMarginRight}>Rate</td>
<td className={alignRightMarginRight}>Disc</td>
<td className={alignRightMarginRight}>Total</td>
</tr>
</thead>
<tbody className={styles.content}>{renderContent()}</tbody>
</table>
<div className={styles.footer}>
<div className={styles.foot}>
<label>Amount:</label>
<label className={styles.amount}>
{amountBeforeFreight.toFixed(2)}
</label>
</div>
<div className={styles.foot}>
<label>Freight:</label>
<label className={styles.amount}>
{freight ? freight.toFixed(2) : 0}
</label>
</div>
<div className={styles.foot}>
<label>Final Amount:</label>
<label className={styles.amount}>
{amountAfterFreight.toFixed(2)}
</label>
</div>
</div>
</div>
</React.Fragment>
);
};
export default SaleInvoice;
in your file SalesInvoice.js, we would be changing the event onClick, instead of what action does(setting modal view to true in your state) we want it to open the print window in the browser.
as follows
<button
style={{marginRight: '200px'}}
onClick={window.print} >
Print
</button>
you will not need this part I guess?
{this.state.printView ? (
<Modal
type="Print"
{...this.props}
show={this.state.printView}
modalClosed={() => this.setState({printView: false})}
/>
) : null}