How to delete an entire row from html table using ReactJS? - reactjs

I want to delete an entire row (text & button) from html table on button click. How can I do that using ReactJS instead of using simple JavaScript?
code:
var RecordsComponent = React.createClass({
render : function() {
return (
<div>
<table>
<tr>
<td>row 1</td>
<td><button onClick={deleteRow}>DELETE</button></td>
</tr>
<tr>
<td>row 2</td>
<td><button onClick={deleteRow}>DELETE</button></td>
</tr>
<tr>
<td}>row 3</td>
<td><button onClick={deleteRow}>DELETE</button></td>
</tr>
</table>
</div>
);
},
deleteRow : function() {
//how to delete row using ReactJS?
},
});
React.render(<RecordsComponent/>, document.getElementById('display'))

You should to know how to make a react components.
Below is one of example to delete items.
class RecordsComponent extends React.Component {
constructor() {
super();
this.state = {
rows: ['row 1', 'row 2', 'row 3'],
};
}
deleteRow = (index) => {
// make new rows. note: react state is immutable.
const newRows = this.state.rows.slice(0, index).concat(this.state.rows.slice(index + 1));
this.setState({
rows: newRows,
});
};
render() {
const rows = this.state.rows.map((row, index) => (
<tr key={row}>
<td>{row}</td>
<td><button onClick={() => { this.deleteRow(index); }}>DELETE</button></td>
</tr>
));
return (
<div>
<table>
{rows}
</table>
</div>
);
}
}

Related

react mapping function not working

hey all i have this array of objects
this.state = {
users :[{
userid:'1',
fullName :'eddyabikhalil',
dob:'10/03/1994',
gender:'M',
loan:[{
loanid:'1',
date:'20/7/2012',
loanValue:'100$',
},
{
loanid:'2',
date:'21/4/2014',
loanValue:'200$',
},
{
loanid:'3',
date:'20/12/2015',
loanValue:'300$',
}]
},
userid:'2',
fullName :'joe salloum',
dob:'11/04/1993',
gender:'M',
loan:[{
loanid:'4',
date:'20/7/2012',
loanValue:'500$',
},
{
loanid:'5',
date:'21/4/2017',
loanValue:'600$',
},
{
loanid:'6',
date:'20/12/2012',
loanValue:'700$',
}
],
}]
}
}
so i wrote this function to map inside of this array of object:
renderTable(userValue) {
let HTML = [];
let groupedVals = groupBy(userValue, 'userid');
let usersObj = [];
map(groupedVals, (value, key) => {
let userss = {
FullName: value.fullName,
dob: value.dob,
gender: value.gender,
loans: []
}
map(value, (subValue) => {
userss.loans.push(subValue.loanValue)
})
usersObj.push(userss);
})
map(usersObj, (val) => {
HTML.push(<tr>
<td>
{val.FullName}
</td>
<td>
{val.dob}
</td>
<td>
{val.gender}
</td>
<td>
{val.loans.join(',')}
</td>
</tr>
)
})
return HTML;
}
i want to make a table with the following fields: fullName, dob, gender and loan
i want to show that userid = 1 have multiple loan value in one td
so i created this table:
render() {
return (
<div className="container">
<table className="table table-striped">
<thead>
<tr>
<td>FullName</td>
<td>dob</td>
<td>gender</td>
<td>loans</td>
</tr>
</thead>
<tbody>
{
this.state.users &&
this.renderTable(this.state.users)
}
</tbody>
</table>
</div>
);
}
any help guys? thanks in advance
render() {
return (
<div className="container">
<table className="table table-striped">
<thead>
<tr>
<td>FullName</td>
<td>dob</td>
<td>gender</td>
<td>loans</td>
</tr>
</thead>
<tbody>
{
this.state.users.map((user) => (
<tr>
<td>{user.fullName}</td>
<td>{user.dob}</td>
<td>{user.gender}</td>
<td>{user.loan.map((loan) => { return (loan.id + ",") })}</td>
</tr>
))
}
</tbody>
</table>
</div>
);
}

How to set State when value is derived from Array in React App

I have a react App, which renders a table from an array in the state.
I am trying to have an "EDIT MODE" which transforms some fields into textbox's so that I can update each row in the table.
I'm not sure how I can handle the onChange event when the value is derived from an element inside an array in the state.
here is my code, I have explained the problem in the comments:
class AddProjectType extends Component {
constructor(props) {
super(props);
this.state = {
editMode: false
}
this.changeEditMode = this.changeEditMode.bind(this); //Bind This so I can use this.setState
this.changeProjectName = this.changeProjectName.bind(this); //Bind This so I can use this.setState
}
componentDidMount() {
this.props.fetchProjectTypes(); //This fetched the table from the nodejs server
}
changeEditMode() {
this.setState({ editMode: !this.state.editMode }); //Convert into edit mode and change rows in the table to inputs
}
changeProjectName(event){
//this.setState - Unsure how to set state of a particular array HERE IS THE PROBLEM
}
render() {
if (!this.props.projectTypes) {
return (
<CenterLoader /> //loading the table from server - show loader
)
}
else
return (
<div className="container">
<table className="ProjectType-Table">
<tbody>
<tr>
<th>
Id
</th>
<th>
Project Type
</th>
<th>
</th>
</tr>
{this.props.projectTypes.map((projectType, i) => { //RENDER ALL ROWS
return (
<tr key={i}>
<td>
{projectType._id}
</td>
<td>
{this.state.editMode ?
<input type="text" className="browser-default" defaultValue={projectType.name} onChange={this.changeProjectName}/> //On change, I need to save back to the state this value
:
projectType.name
}
</td>
<td>
<button className="btn btn-small mr-1" onClick={this.changeEditMode}>Edit</button>
<button className="btn btn-small">Delete</button>
</td>
</tr>
)
}
)}
</tbody>
</table>
</div>
);
}
}
function mapStateToProps(state) {
return { projectTypes: state.quizz.projectTypes };
}
export default connect(mapStateToProps, actions)(AddProjectType);
Attach data-idx={i} in the input like this,
<input type="text" className="browser-default" defaultValue={projectType.name} onChange={this.changeProjectName} data-idx={i}/>
In your changeProjectName(event) handler,
var index = event.target.dataset.idx; // Here you will get index

Reactjs - Splitting table row into two rows - fields are not aligning properly

Am trying to split table row into two rows. So, i writting two tr tag in my render() method. Am able to split the rows but, its alignment is not coming properly.
All the fields are rendering in the first column itself. How can i split the table properly.
Am using Reactjs V 15.6.1
class Details extends React.Component {
constructor(props) {
super(props);
this.state = { item: props.item };
}
render() {
return (
<table className="table table-bordered" style={{fontsize: '8'}}>
<thead>
<tr>
<th>Line Number</th>
<th>Product Code</th>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
</tr>
</thead>
<DetailsList items={ this.state.item.order_items } />
</table>
);
}
}
class DetailsList extends React.Component {
constructor(props) {
super(props);
this.state = { };
}
render() {
return (<tbody>{ this.props.items.map((item) => <DetailsItem key={
item.line_id } item={ item } />) }
</tbody>);
}
}
class DetailsItem extends React.Component {
constructor(props) {
super(props);
this.state = { item: props.item };
}
render() {
return (<tbody>
<tr>
<td><input name="line_number" type="text"
value={ this.state.item.line_number } /> </td>
<td><input name="product_code" type="text"
value={ this.state.item.product_code } /></td>
<td><input name="product_description" type="text"
value={ this.state.item.product_description } /> </td>
</tr>
<tr>
<td>{ this.state.item.product_quantity } </td>
<td>{ this.state.item.unit_net_price } </td>
</tr>
</tbody>
);
}
}
Please find my output screenshot below. All fields are rendered in the same column. Its happening while am adding second table row tag.
Also, if remove <tbody> tag from the return() method also its throwing error Adjacent JSX elements must be wrapped in an enclosing tag.
ReactJS V 15.x.x only allow one components within render() method. Its not possible to return multiple <tr> tag. This has been addressed from ReactJS 16+ https://reactjs.org/docs/jsx-in-depth.html.

how to add row to a table using ReactJS on button click

I have a table and I want to add a row to it when ADD button is clicked. How can I do that using ReactJS instead of simple JavaScript?
code:
var RecordsComponent = React.createClass({
render : function() {
return (
<div>
<table>
<tr>
<td>row 1</td>
</tr>
<tr>
<td>row 2</td>
</tr>
<tr>
<td}>row 3</td>
</tr>
</table>
<button id="addBtn" onClick={addRow}>ADD</button>
</div>
);
},
addRow : function() {
//how to add row using ReactJS?
},
});
React.render(<RecordsComponent/>, document.getElementById('display'))
You need to make your React component have a state and render the component accordingly based on that data. Forget the old "DOM modification" paradigm where you are playing directly with HTML elements.
Untested but should carry the idea across:
var RecordsComponent = React.createClass({
getInitialState: {
return {
rows: ['row 1', 'row 2', 'row 3']
}
},
render : function() {
return (
<div>
<table>
{rows.map((r) => (
<tr>
<td>{r}</td>
</tr>
))}
</table>
<button id="addBtn" onClick={addRow}>ADD</button>
</div>
);
},
addRow : function() {
var rows = this.state.rows
rows.push('new row')
this.setState({rows: rows})
},
});
React.render(<RecordsComponent/>, document.getElementById('display'))
If you're just starting to learn React with your own test apps I would recommend using the most recent version of React, along with, among a lot of other things, the React ES6 class definitions.
Try something like this
var RecordsComponent = React.createClass({
getInitialState: function () {
return {
tablerows:[
{fname:"Tom",lname:"Moody",age:23}
]
};
},
addRow: function() {
// add new data from here
var newdata = {fname:"Tom",lname:"Moody",age:23}
//take the existing state and concat the new data and set the state again
this.setState({ tablerows: this.state.tablerows.concat(newdata ) });
},
rows:function(){
return this.state.tablerows.map(function(row,i){
return (<tr key={i}>
<td>{row.fname}</td>
<td>{row.lname}</td>
<td>{row.age}</td>
</tr>);
});
},
render : function() {
return (
<div>
<table>
<tr>
<td> row 1 </td>
</tr>
<tr>
<td> row 2 </td>
</tr>
<tr>
<td> row 3 </td>
</tr>
{this.rows()}
</table>
<button id= "addBtn" onClick={this.addRow}>ADD</button>
</div>
);
}
});
React.render(<RecordsComponent/>, document.getElementById('display'))

Render table when getting data asynchronous

I have some data which i get in state when componentDidMount.
I am trying render table using this data.
In my case rows not rendering.
How i can send data to tbody ?
export default class App extends Component {
constructor(props) {
super(props);
this.state={rows:null}
}
componentDidMount(){
var rows=[]
Meteor.http.call("GET", url ,function(error,result){
$.each(JSON.parse(result.content), function(key, value){
rows.push(value)
});
this.setState({
rows:rows});
})
}
renderRows(){
$.each(this.state.rows, function(d){
return(
<tr>
<td>{d[0]}</td>
<td>{d[1]}</td>
<td>{d[2]}</td>
<td>{d[3]}</td>
</tr>
)
})
}
render(){
return(
<Table>
<thead>
<tr>
<th>col1</th>
<th>col2</th>
<th>col3</th>
<th>col4</th>
</tr>
</thead>
<tbody>
{this.renderRows}
</tbody>
</Table>
)
}
}
Another option, not using JQuery and avoiding having a separate render function, is to use .map
React likes it if you have a unique key on each element in a list, so hopefully one of the fields on your row can serve this purpose.
render(){
return(
<Table>
<thead>
<tr>
<th>col1</th>
<th>col2</th>
<th>col3</th>
<th>col4</th>
</tr>
</thead>
<tbody>
{this.state.rows.map(d => (
<tr key={d[0]}>
<td>{d[0]}</td>
<td>{d[1]}</td>
<td>{d[2]}</td>
<td>{d[3]}</td>
</tr>
)}
</tbody>
</Table>
)
}
You'll also need to set your initial state for rows to be [] rather than null, in order for the first render to work.
renderRows is a function so you need to execute it. Also you will need to update that function a bit:
export default class App extends Component {
// ...
componentDidMount(){
var rows=[];
var self = this;
Meteor.http.call("GET", url ,function(error,result){
$.each(JSON.parse(result.content), function(key, value){
rows.push(value)
});
self.setState({
rows: rows
});
});
}
renderRows(){
const rows = this.state.rows || [];
return rows.map(d => {
return(
<tr>
<td>{d[0]}</td>
<td>{d[1]}</td>
<td>{d[2]}</td>
<td>{d[3]}</td>
</tr>
);
});
}
render(){
return(
<Table>
{/* ... */}
<tbody>
{this.renderRows()}
</tbody>
</Table>
)
}
}

Resources