i have a problem that i need to add the data from state and loop it using map. in my project im using redux and got the value from redux its self but in the state won't render again after map.
i already tried to using this.props.sendNameProduct in my array of map but when i added the new product the first product updated with the value of last product. i just want it to store the first product and then when im inputting the second product , the first product still there.
class OpenPositions extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
console.log(this.props, "ini porpoaspdopa")
console.log(this.props.sendNameProduct, "ini send name")
console.log(this.props.sendNameProduct.sendNameProduct," ini kirik");
let dapetItem = this.props.cobaSend == null ? [] : this.props.cobaSend
let cobaSend = [{qty: '123'}];
let getItem = localStorage.getItem('storage')
let newData =[];
let newDataBaru = [];
let newArr = [];
newArr.push(this.props.cobaSend);
newData = newDataBaru.concat(newArr)
console.log(newArr, "ini new array");
console.log(newData, "ini new Data")
return (
<div style={{height:'100%', overflow:'auto'}}>
<table className="borderline" cellspacing="0" cellpadding="0" border="0" style={{height:'100%'}}>
<tbody>
<tr>
<td>
<div>
<div>
<table style={{height:"100%", width:"100%"}}>
<tbody>
<tr align="center" className="fieldtitle fieldbg">
<td align="left">Items</td>
<td>Qty</td>
<td>Sold</td>
<td>Bought</td>
<td>Avail</td>
<td>Date</td>
<td>Options</td>
</tr>
</tbody>
<tbody className="divOP2">
{this.props.cobaSend.map((item, index) =>{
console.log(item, "ini item bois");
console.log(index, "ini index")
return(
<tr align="center" className="contentbg">
<td align="left" nowrap className="bggradientleft" style={{backgroundImage: ' url(https://demo.sgberjangka.com/images/background_gradientleft.gif)', backgroundRepeat: 'repeat-y', backgroundRepeatX: 'repeat', boxSizing: "border-box", border: "1px solid black", backgroundSize:"100%"}}><font color="#FFFFFF"><strong>{item.product}</strong></font></td>
<td>{item.qty}</td>
<td>{item.sell}</td>
<td>{item.buy}</td>
<td>{item.avail}</td>
<td>{item.date}</td>
<td>
<input
className="checkbox"
type="checkbox"
checked={this.state.isChecked}
onChange={this.handleCheckBox}
/>
</td>
</tr>
)})}
</tbody>
</table>
</div>
</div>
</td>
</tr>
<table className="normal" cellspacing="0" cellpadding="0" border="0" style={{height:'100%'}}>
<tbody>
<tr>
<td>
<button type="submit" className="normalButton wide">GTC Order (Liq)</button>
</td>
<td>
<button type="submit" className="normalButton wide">Buy/Sell (Liq)</button>
</td>
</tr>
</tbody>
</table>
</tbody>
</table>
</div>
)
}
};
function stateProps(state){
console.log(state.main.sendNameProduct, "ini send Name Product")
console.log(state.main.sendValueSell, "ini send sell Product")
console.log(state.main.sendValueBuy, "ini send buy Product")
console.log(state.main.sendQuantity, "ini send qty Product")
return {
sendNameProduct : state.main,
sendValueSell : state.main,
sendValueBuy : state.main,
sendQuantity : state.main
};
};
function dispatchProps(dispatch){
return {
}
}
export default connect(
stateProps,
dispatchProps
)(OpenPositions);
the result its when im updating with new data the first one changed and got same values with new data.
lets assume with this.props.cobaSend got the objects like {product: "HKK50_BBJ", qty: "12", sell: "28579", buy: "--", avail: "12", …}, in mapping got the value product, qty ,sell ,and etc. but when im inserting the new data the value in map not updateing with the new array.
Your newData.map loop on the newData array, but display this.props.sendNameProduct... values in your DOM.
Might just be an error on accessing those values, try call the item return by the map callback :
{
newData.map((item, index) =>{
console.log(item, "ini item bois");
console.log(index, "ini index")
return(
<tr align="center" className="contentbg">
<td align="left" nowrap className="bggradientleft"><font color="#FFFFFF"><strong>{item.item}</strong></font></td>
<td>{item.qty}</td>
<td>{item.sell}</td>
<td>{item.buy}</td>
<td>{item.date}</td>
<td>{item.avail}</td>
<td>
<input
className="checkbox"
type="checkbox"
checked={this.state.isChecked}
onChange={this.handleCheckBox}
/>
</td>
</tr>
)
});
}
class OpenPositions extends Component {
constructor(props) {
super(props);
this.state = {
newArr : []
};
}
render() {
console.log(this.props, "ini porpoaspdopa")
console.log(this.props.sendNameProduct, "ini send name")
console.log(this.props.sendNameProduct.sendNameProduct," ini kirik");
console.log(this.props.cobaSend," ini COBA SEND");
// let dapetItem = this.props.cobaSend == null ? [] : this.props.cobaSend
// let cobaSend = [{qty: '123'}];
// let getItem = localStorage.getItem('storage')
let newArr = this.state.newArr;
newArr.push(this.props.cobaSend);
console.log(newArr, "ini new array");
console.log(newData, "ini new Data")
//let newData = [];
//let newDataBaru = newData.concat(data);
//newData.push(data[0])
//console.log(newData, "ini new Data")
//console.log(newDataBaru,"ini data baru")
//newData = newDataBaru.concat(data)
// for(let i =0 ; i< 5; i++){
// }
//console.log(newData, "ini new Data")
return (
<div style={{height:'100%', overflow:'auto'}}>
<table className="borderline" cellspacing="0" cellpadding="0" border="0" style={{height:'100%'}}>
<tbody>
<tr>
<td>
<div>
<div>
<table style={{height:"100%", width:"100%"}}>
<tbody>
<tr align="center" className="fieldtitle fieldbg">
<td align="left">Items</td>
<td>Qty</td>
<td>Sold</td>
<td>Bought</td>
<td>Avail</td>
<td>Date</td>
<td>Options</td>
</tr>
</tbody>
<tbody className="divOP2">
{newArr.map((item, index) =>{
console.log(item, "ini item bois");
console.log(index, "ini index")
return(
<tr align="center" className="contentbg">
<td align="left" nowrap className="bggradientleft" style={{backgroundImage: ' url(https://demo.sgberjangka.com/images/background_gradientleft.gif)', backgroundRepeat: 'repeat-y', backgroundRepeatX: 'repeat', boxSizing: "border-box", border: "1px solid black", backgroundSize:"100%"}}><font color="#FFFFFF"><strong>{item.product}</strong></font></td>
<td>{item.qty}</td>
<td>{item.sell}</td>
<td>{item.buy}</td>
<td>{item.avail}</td>
<td>{item.date}</td>
<td>
<input
className="checkbox"
type="checkbox"
checked={this.state.isChecked}
onChange={this.handleCheckBox}
/>
</td>
</tr>
)})}
</tbody>
</table>
</div>
</div>
</td>
</tr>
<table className="normal" cellspacing="0" cellpadding="0" border="0" style={{height:'100%'}}>
<tbody>
<tr>
<td>
<button type="submit" className="normalButton wide">GTC Order (Liq)</button>
</td>
<td>
<button type="submit" className="normalButton wide">Buy/Sell (Liq)</button>
</td>
</tr>
</tbody>
</table>
</tbody>
</table>
</div>
)
}
};
im using state to store it there and then when im inputting the data its worked.
Related
I have a table that the user can edit the rows so i can save it into a state and save it inside a database but how can i get table row values and save it inside a state ? therefor the rows can be dynamic rows for example like grade i will fetch how many subjects inside a specific subject and the admin can put numbers inside rows so i can calculate how many grade does the user get for this subject
<table className="table-fill">
<thead>
<tr>
<th className="text-left">Subjects</th>
<th className="text-left">Grade</th>
</tr>
</thead>
<tbody className="table-hover">
<tr>
<td className="text-left" contentEditable="true">subject 1</td>
<td className="text-left" contentEditable="true">50</td>
</tr>
<tr>
<td className="text-left" contentEditable="true">subject 2</td>
<td className="text-left" contentEditable="true">40</td>
</tr>
<tr>
<td className="text-left" contentEditable="true">subject 3</td>
<td className="text-left" contentEditable="true">30</td>
</tr>
</tbody>
</table>
You should not use contentEditable="true" because it have no onChange event, so use input instead
import { useState } from "react";
export default function App() {
const [data, setData] = useState([
{ subject: "subject 1", grade: 50 },
{ subject: "subject 2", grade: 40 },
{ subject: "subject 3", grade: 30 }
]);
const onChangeRow = ({ type, index, value }) => {
const newData = data.map((item, idx) => {
if (idx === index)
return {
...item,
[type]: value
};
return item;
});
setData(newData);
};
const totalGrade = data.reduce((acc, cur) => {
acc += cur.grade;
return acc;
}, 0);
return (
<div className="App">
<table className="table-fill">
<thead>
<tr>
<th className="text-left">Subjects</th>
<th className="text-left">Grade</th>
</tr>
</thead>
<tbody className="table-hover">
{data.map((item, index) => (
<tr key={index}>
<td className="text-left">
<input
type="text"
defaultValue={item.subject}
onChange={(e) =>
onChangeRow({
type: "subject",
index,
value: e.target.value
})
}
/>
</td>
<td className="text-left">
<input
type="number"
defaultValue={item.grade}
onChange={(e) =>
onChangeRow({
type: "grade",
index,
value: parseInt(e.target.value || 0)
})
}
/>
</td>
</tr>
))}
</tbody>
</table>
<div>Total grade: {totalGrade}</div>
</div>
);
}
style.css
input {
border: none;
outline: none;
}
You can check in my codesandbox. Hope it help!
const SheetTable = ({ sheets }) => {
return (
<table className="sheetTableComponent">
<thead>
<tr>
<td>No</td>
<td>track</td>
<td>item</td>
</tr>
</thead>
<tbody>
{sheets.map((item, index) => (
<tr key={index}>
<td>{index}</td>
<td>
<div>{item.code}</div>
</td>
<td>
<div>{item.item}</div>
</td>
</tr>
))}
</tbody>
</table>
)
}
This is my table. After populate it got about 10 rows. I want if one row click, it will highlight, the other rows un-highlight
Hope it will solve your problem.
Are you looking for something like this?
changeColor = (id) => {
this.setState({ selected: id });
};
render() {
const { selected, arr } = this.state;
return (
<table className="sheetTableComponent">
<thead>
<tr>
<td>No</td>
<td>track</td>
<td>item</td>
</tr>
</thead>
<tbody>
{arr.map((item, index) => (
<tr
key={index}
style={{
color: selected === item.id ? "red" : ""
}}
onClick={() => this.changeColor(item.id)}
>
<td>{index}</td>
<td>
<div>{item.code}</div>
</td>
<td>
<div>{item.item}</div>
</td>
</tr>
))}
</tbody>
</table>
);
}
Live working demo
Couple of ways to do it, but most simple is to just use css
Assign tabindex to your rows and use :focus selector to highlight the row
<tr key={index} className="row" tabindex="0">
CSS:
.row:focus {
outline: none;
background: green;
}
I have table so I want to retrieve key/value of specific row in which button was clicked.
componentDidMount() {
let com = this;
firebase
.database()
.ref()
.child("bills")
.once("value", snap => {
let items = [];
snap.forEach(childD => {
items.push({
balance: childD.val().balance,
bill_num: childD.val().bill_num,
date: childD.val().date,
key: childD.val().key,
name: childD.val().name,
total: childD.val().total
});
});
Array.prototype.push.apply(com.state.products, items);
com.setState({
products: com.state.products
});
});
}
open = e => {
e.preventDefault();
console.log("kal" + this.state.value);
};
handleChange=event=>{
this.setState({value: event.target.value});
}
render() {
return (
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Bill number</th>
<th scope="col">Name</th>
<th scope="col">Date</th>
<th scope="col">Total</th>
<th scope="col">Balance</th>
<th scope="col">Delete</th>
<th scope="col">Open bill</th>
</tr>
</thead>
<tbody>
{console.log(this.state.products)}
{this.state.products.map((value, key) => (
<tr key={value.key}>
<th scope="row">{value.bill_num}</th>
<td>{value.name}</td>
<td>{value.date}</td>
<td>{value.total}</td>
<td>{value.balance}</td>
<td>
<form onSubmit={this.returnOrder}>
<input value={value.key} type="hidden" />
<button className="btn btn-danger" type="submit">
Return
</button>
</form>
</td>
<td>
<form onSubmit={this.open}>
<input value={value.key} onChange={this.handleChange} ref={ eKey => (this.inputeKey = eKey)} />
<button className="btn btn-info" type="submit">
Open
</button>
</form>
</td>
</tr>
))}
</tbody>
</table>
</div>
) : (
<Printout
keya={{
key: this.props.keyas
}}
/>
)}
);
}
}
Typically, tables in React are made from several components: whole table, row and for example buttons in row. So in table you place array of rows. Each row has it's child buttons. So you can send props to RowButtons child with information about clicked row.
I am trying to make a an accordion using React but and I receive my data from a Json API which I dynamically use to make the table. All that works.
However when I try to make the toggleHidden function, it opens every single view instead of the one I just clicked on. How can I target a specific component when clicking instead of just using this
<Table striped bordered condensed hover>
<thead>
<tr>
<th>Asset #</th>
<th>Description</th>
<th>Person</th>
<th>Username</th>
<th>Room</th>
<th>ID</th>
<th>Patches</th>
<th>Date</th>
<th>Java</th>
<th>AACV</th>
</tr>
</thead>
{this.state.items.map((data, key) => {
return (
<tbody>
<tr
id={data.name}
onClick=`{this.toggleHidden.bind(this)}
>`
<td>{data.name}</td>
<td >{data.height}</td>
<td>{data.mass}</td>
<td>{data.gender}</td>
<td >{data.birth_year}</td>
<td>{data.eye_color}</td>
<td >{data.birth_year}</td>
<td>{data.eye_color}</td>
<td >{data.birth_year}</td>
<td>{data.eye_color}</td>
</tr>
<td
className={data.name}
colSpan="10"
>
{!this.state.isHidden && <Filled/>}
</td>
</tbody>
)
})}
</Table>
toggleHidden (e) {
this.setState({
isHidden: !this.state.isHidden
})
}
I Would suggest you to use the power of components.
Create component for row inside the table, something like this:
export default class Row extends React.Component {
render() {
const { data } = this.props;
<tbody>
<tr
id={data.name}
onClick=`{this.toggleHidden.bind(this)}
>`
<td>{data.name}</td>
<td >{data.height}</td>
<td>{data.mass}</td>
<td>{data.gender}</td>
<td >{data.birth_year}</td>
<td>{data.eye_color}</td>
<td >{data.birth_year}</td>
<td>{data.eye_color}</td>
<td >{data.birth_year}</td>
<td>{data.eye_color}</td>
</tr>
<td
className={data.name}
colSpan="10"
>
{!this.state.isHidden && <Filled/>}
</td>
</tbody>
}
toggleHidden() {
this.setState(state => ({
isHidden: !state.isHidden
}));
}
}
and in your main component do something like this:
<Table striped bordered condensed hover>
<thead>
<tr>
<th>Asset #</th>
<th>Description</th>
<th>Person</th>
<th>Username</th>
<th>Room</th>
<th>ID</th>
<th>Patches</th>
<th>Date</th>
<th>Java</th>
<th>AACV</th>
</tr>
</thead>
{this.state.items.map((data, key) => <Row data={data} />}
</Table>
it's more readable, it's more react style, and it's let each row to handle their own state
(there might be some syntax error, but the concept is working)
Good Luck!
Well you need to make nested state for each key that means
const { Table, Icon } = semanticUIReact;
const ITEMS = [
{
asset: "Asset 1",
description: "Description"
},
{
asset: "Asset 2",
description: "Description2"
}
];
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { items: ITEMS };
this.renderRow = this.renderRow.bind(this);
}
render() {
return (
<Table striped bordered condensed selectable>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Asset</Table.HeaderCell>
<Table.HeaderCell>Description</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>{this.state.items.map(this.renderRow)}</Table.Body>
</Table>
);
}
renderRow(data, key) {
return (
<Table.Row onClick={() => this.toggleHidden(key)}>
<Table.Cell>{data.asset}</Table.Cell>
<Table.Cell textAlign="right">
{this.state[key] ? "This is hidden" : data.description}
</Table.Cell>
</Table.Row>
);
}
toggleHidden(key) {
this.setState({
[key]: !this.state[key]
});
}
}
ReactDOM.render(<Example />, document.getElementById("react"));
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.1/semantic.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/semantic-ui-react#0.79.1/dist/umd/semantic-ui-react.min.js"></script>
<div id="react"></div>
I'm trying to generate a pdf from an html div with html2canvas and pdfMake but always got a blank page or just part of the div! How can I get the entire div content?
Here is the js code :
$scope.PrintFiche = function () {
var prom = new Promise(function (resolve, reject) {
html2canvas(document.getElementById('DevisImpression'), {
onrendered: function (canvas) {
var data = canvas.toDataURL("image/png");
var docDefinition = {
content: [{
image: data
}]
};
resolve(docDefinition);
}
});
})
prom.then(function (docDef) {
pdfMake.createPdf(docDef).download($scope.FicheName + ".pdf");
})
}
And the html :
<div class="Partie" id="DevisImpression">
<div id="PartieInner">
<h2 id="TitreDevis">
<b>
Etablissement du devis
</b>
</h2>
<div id="ImgVoitureDevis">
<img id="ImgVoitureAdapt" src="../../Assets/Images/test.jpg" />
</div>
<div id="OptMult">
<table id="TableDevis">
<tr>
<td class="td1">
Modèle :
</td>
<td class="td2">
{{modele.displayName}}
</td>
</tr>
<tr>
<td class="td1">
Classe :
</td>
<td class="td2">
{{classe.displayName}}
</td>
</tr>
<tr>
<td class="td1">
Moteur :
</td>
<td class="td2">
{{moteur.displayName}}
</td>
</tr>
<tr>
<td class="td1">
Couleur :
</td>
<td class="td2">
{{couleur.displayName}}
</td>
</tr>
<tr>
<td class="td1">
Jantes :
</td>
<td class="td2">
{{jante.displayName}}
</td>
</tr>
</table>
</div>
<table id="Devis">
<tr>
<th class="tdDevis2">
Options
</th>
<th class="tdDevis2">
Prix
</th>
</tr>
<tr ng-repeat="optionDev in optionsDevis">
<td class="td3">
{{optionDev.displayName}}
</td>
<td class="td4">
{{optionDev.prix}} €
</td>
</tr>
</table>
</div>
<h2 id="TotalTitre">
<b>
TOTAL
</b>
</h2>
<input type="text" id="Total" value="{{total}} €" disabled />
<br />
</div>
I have a simple solution. Try this.
$scope.downloadQuotation = function () {
html2canvas(document.getElementById('rosterPrintView'), {
onrendered: function (canvas) {
var data = canvas.toDataURL();
var docDefinition = {
content: [{
image: data,
width: 500
}]
};
pdfMake.createPdf(docDefinition).download("Roster.pdf");
}
});
};