How can I make my React app render Bootstrap tables with crud - reactjs

I'm using the following code to generate a simple UI, and I'm trying to convert it to use Bootstrap.
This is my original code (using Skeleton);
render:function(){
return (
<div className="grocery-item row">
<div className="six columns">
<h4 className={this.props.item.purchased ? "strikethrough" : "" }>
{this.props.item.name}
</h4>
</div>
<form onSubmit={this.togglePurchased} className="three columns">
<button className={this.props.item.purchased ? "btn btn-danger" : "button-primary"}>{this.props.item.purchased ? "unbuy" : "buy"}</button>
</form>
<form className="three columns" onSubmit={this.delete}>
<button>×</button>
</form>
</div>
)
}
I tried doing something like this;
render:function(){
return (
<table class="table table-striped">
<thead>
<tr>
<th>Column 1</th>
<th>Columan 2</th>
<th>Columan 3</th>
</tr>
</thead>
<tbody>
<tr>
<h4 className={this.props.item.purchased ? "strikethrough" : "" }>{this.props.item.name}</h4>
<form onSubmit={this.togglePurchased} className="three columns">
<button className={this.props.item.purchased ? "btn btn-danger" : "button-primary"}>{this.props.item.purchased ? "unbuy" : "buy"}</button>
</form>
<form className="three columns" onSubmit={this.delete}>
<button>×</button>
</form>
</tr>
</tbody>
</table>
)
}
But it's not working like I expect. I'm using react-express-examplar as my starting point.
How can I get Bootstrap tables working in my React app?

I think you'll have an easier time if you start your app using create-react-app. They even give instructions on how to use Bootstrap with React.
You said you're new to React. There are a lot of moving parts that can be overwhelming to figure out at first. Using create-react-app will take out a lot of the learning curve and make it a lot easier for you to get started with as little friction as possible.
Good luck!

From my understanding, you want the name and buy/unbuy buttons to come as a row , under respective columns.
In the tr tag, give each html part as a td tag
Please refer below html snippet:
<td>
<h4 class="strikethrough">
name
</h4>
</td>
<td>
<form class="three columns">
<button class="btn btn-info">buy</button>
</form>
</td>
<td>
<form class="three columns">
<button>×</button>
</form>
</td>
Please try to modify the html in your component render method, similarly.

You added table to wrong Component. It must be on GroceryItemList.jsx
Caution: Form is not allowed inside table. I'm just providing the structure and UI and code is not tested.
::: structure should something like-
GroceryItemList.jsx Component::::
render:function(){
return (
<div>
<table className="table">
<thead>
<tr>
<th>Column 1</th>
<th>Columan 2</th>
<th>Columan 3</th>
</tr>
</thead>
<tbody>
{this.props.items.map((item,index)=>{
return (
<GroceryItem item={item} key={"item"+index} />
)
})}
<GroceryListAddItem />
</tbody>
</table>
</div>
)
}
GroceryItem.jsx Component::::
render:function(){
return (
<tr>
<td>
<h4 className={this.props.item.purchased ? "strikethrough" : "" }>
{this.props.item.name}
</h4>
</td>
<td>
<form onSubmit={this.togglePurchased}>
<button className={this.props.item.purchased ? "" : "button-primary"}>{this.props.item.purchased ? "unbuy" : "buy"}</button>
</form>
</td>
<td>
<form onSubmit={this.delete}>
<button>×</button>
</form>
</td>
</tr>
)
}

Related

React UI doesn't get updated, why?

I have a component, called Bucket, each bucket can have multiple challenges, it looks like this,
The code I have is like this, (much-simplified version)
class CLL_Bucket extends Component {
constructor(props) {
super(props);
this.state = {};
this.state = {
…
bucketChallengesIdx: 0, // to track the index of challegnes
bucketChallenges: this.props.bucket.bucketChallenges || [],
…
};
…
this.onBucketChallengeAdd = this.onBucketChallengeAdd.bind(this);
this.onBucketChallengeIDChanged = this.onBucketChallengeIDChanged.bind(this);
this.onBucketChallengeWeightChanged = this.onBucketChallengeWeightChanged.bind(this);
}
render() {
const bucketIdx = this.props.idx;
return (
<div style={styles.container}>
<div key={bucketIdx} className="row" style={styles.bucketStyle}>
<div className="col-md-2">
…
</div>
<div key={bucketIdx} className="col-md-4">
<div>
<label>
<span className="text-center">Challenges<span>
</label>
<button type="button" className="btn btn-success btn-sm" onClick={() => this.onBucketChallengeAdd()}>Add Challenge</button>
</div>
<table className="table table-bordered table-striped show">
<thead>
<tr>
<th>Challenge ID</th>
<th>Weight</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{this.state.bucketChallenges.map(this.renderBucketChallenges.bind(this))}
</tbody>
</table>
</div>
…
</div>
</div>
);
}
renderBucketChallenges(bucketIdx, idx){
return (
<tr key={idx}>
<td className="col-xs-3 input-group-sm">
<Select
options={challengeIDOptions}
defaultValue={challengeIDOptions[0]}
onChange={this.onBucketChallengeIDChanged.bind(this, idx)}
value={this.state.bucketChallengesID}
isSearchable={true}
/>
</td>
<td className="col-xs-1 input-group-sm">
<input type="text" className="form-control" value={this.state.bucketChallengesWeight}
onChange={(e) => this.onBucketChallengeWeightChanged(idx, e)} disabled={this.props.readOnly}>
</input>
</td>
<td className="col-xs-1 input-group-sm">
…
</td>
<td className="col-xs-1 input-group-sm">
<input className="btn btn-danger btn-sm" id="deleteButton" type="button" value="Delete" onClick={() => this.onDeleteChallenge.bind(this, bucketIdx, idx)} />
</td>
</tr>
);
}
onBucketChallengeAdd(){
var newChallengeIndex = this.state.bucketChallengesIdx + 1;
console.log("onBucketChallengeAdd(): " + newChallengeIndex);
this.setState({bucketChallengesIdx: newChallengeIndex});
this.props.onAddChallenge(this.props.idx, newChallengeIndex);
}
The problem I’m having is, when I click the “Add Challenge” button, I can see from the React developer tool that a new challenge is being added, even though the UI is not updated. When I go to a different tab of my app and come back, the UI is added (a new row for the added challenge is there). Why? Any suggestion on how to fix this? Thanks!
The bigger question is, am I on the right track to make this happen? or i should extract challenge portion to a different component?

Bootstrap modal in React is not opening

I have a table whose items I render through a list. The idea is that, on clicking the name of a row, a modal will open and that will print certain values retrieved from the backend server.
Initially, for the modal, my data-target was the ID of my modal. After looking at this answer I realised that I might be doing something wrong and changed that data-target to the ID of the row. Now the problem is that the modal is not opening at all.
Edit: I realised I was doing something wrong when ID of my modal was fixed because irrespective of whichever name I clicked, the same information was loading. Through console.log I could see that the right values were being passed but only was being displayed.
What am I doing wrong here?
The rendered code for the table is as follows:-
<table className="table">
<thead>
<tr>
<th>S. NO.</th>
<th>NAME</th>
<th>ADDRESS</th>
<th>TELEPHONE</th>
<th>EMAIL</th>
<th>AGE</th>
<th></th>
</tr>
</thead>
<tbody>
{this.state.personData.map((pRow, idx) => (
<>
<PersonModal id={pRow.id} />
<tr key={pRow.id}>
<td>{idx + 1}</td>
<td data-toggle="modal" data-target={pRow.id}>{pRow.name}</td>
<td>{pRow.address}</td>
<td>{pRow.phone}</td>
<td>{pRow.email}</td>
<td>{pRow.age}</td>
<td>
{" "}
<DeleteButton id={pRow.id} onDelete={this.onDelete} />{" "}
</td>
</tr>
</>
</tbody>
</table>
This is the rendered code for the modal:-
render() {
console.log("Component rendered");
return (
<React.Fragment>
<div className="modal" id={this.props.id}>
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-body">
{this.props.id}
</div>
<div className="modal-footer">
<button type="button" className="btn optionsButton" data-dismiss="modal">CLOSE</button>
</div>
</div>
</div>
</div>
</React.Fragment>
);
}

React table misaligns table header columns with table row columns

I'm trying to figure out why my header and body rows aren't in sync. I'm using semantic ui for the css. Is it because my body rows are rendered in a different component? I tried moving them all to 1 and it didn't make any difference.
<table className="ui celled table" border="1">
<thead>
<tr>
<th >Status</th>
<th >Service Date of Visit</th>
<th >Claim ID</th>
<th >Insurance Plan</th>
</tr>
</thead>
<tbody>
{this.state.claims.map ( claim => <ClaimRow claim= { claim } /> ) }
</tbody>
and inside the component.
const ClaimRow = ( {claim} =this.props ) => (
<Form.Field>
<tr >
<td >
<input type="radio" name={claim._id} label="That Was Me" value="valid" checked={claim.status === 'valid'} />
Valid? <br />
<input type="radio" name={claim._id} label="Looks Like Fraud" value="fraud" checked={claim.status === 'fraud'} />
Fraud? <br />
<input type="radio" name={claim._id} label="Looks Like Fraud" value="notselected" checked={!claim.status && "defaultchecked"} />
Not Yet Sure
</td>
<td > {claim.claimDate} {claim.status}</td>
<td > {claim.claimID} </td>
<td > {claim.carrier} </td>
</tr>
</Form.Field>
);
ClaimRow.propTypes = {
claim: PropTypes.string.isRequired
};
export default
and the table footer
<tfoot className="full-width">
<tr>
<th colspan="4">
<div className="ui small button">
Approve
</div>
<div className="ui small button">
Approve All
</div>
<div className="ui right floated button" >
Next
<i class="right arrow icon"> </i>
</div>
<div className="ui right floated button" >
<i class="left arrow icon"></i>
Prev
</div>
</th>
</tr>
</tfoot>
</table>
Rows should be returning a <tr> at the top level, not a <Form.Field>.
for me adding this class worked.
.ReactTable .rt-tbody .rt-td{
margin-left: 0;
}

Error in using angularjs data in form action link in spring mvc web app project

I m using angularjs to retrieve my data in my spring web app project. it is able to retrieve and display the data in all places i have passed it using {{ }} but in my form-action link it is not able to read the value passed . what is wrong with the syntax?
<div class="container text-center" ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="product in Data" >
<div class=col-lg-5>
<center>
<img src="<c:url value='/resource/image/{{product.name}}.jpg'/>" />
</center>
</div>
<div class=col-lg-7>
<table class="table table-striped">
<tr>
<h1>{{product.name}}</h1>
</tr>
<tr>
<th>Description</th>
<td>{{product.description}}</td>
</tr>
<tr>
<th>Category</th>
<td>{{product.category}}</td>
</tr>
<tr>
<th>Price</th>
<td>Rs.{{product.price}}</td>
</tr>
^
till here it displays the data using angular js
</table>
</div>
<form:form method="POST" modelAttribute="cart" action="${pageContext.request.contextPath}/user/addtocart?productId={{product.id}}">
^
here it doesnt read the data passed using angularjs
<sec:authorize access="hasRole('ROLE_USER')">
<input type="submit" class="btn btn-info btn-lg" value="Add to Cart" />
</sec:authorize>
</form:form>
Change your HTML to below way,because your ng-controller <div> tag ended before the form as the angular scope is restricted to that </div> tag itself your {{}} expression in action is not evaluated.
<div class="container text-center" ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="product in Data">
<div class=col-lg-5>
<center>
<img src="<c:url value='/resource/image/{{product.name}}.jpg'/>" />
</center>
</div>
<div class=col-lg-7>
<table class="table table-striped">
<tr>
<h1>{{product.name}}</h1>
</tr>
<tr>
<th>Description</th>
<td>{{product.description}}</td>
</tr>
<tr>
<th>Category</th>
<td>{{product.category}}</td>
</tr>
<tr>
<th>Price</th>
<td>Rs.{{product.price}}</td>
</tr>
</table>
<form:form method="POST" modelAttribute="cart" action="${pageContext.request.contextPath}/user/addtocart?productId={{product.id}}">
<sec:authorize access="hasRole('ROLE_USER')">
<input type="submit" class="btn btn-info btn-lg" value="Add to Cart" />
</sec:authorize>
</form:form>
</div>
</div>
</div>

Trigger ngInfiniteScroll correctly when using a scrolling table

I have a table inside a bootstrap-modal which has overflow set to auto so that it scrollable. However I need to load a lot of data so I would like to implement lazy-loading using ngInfiniteScroll. I have tried using the infinite-scroll-container attribute but it's still triggering constantly. Here is a code-snippet:
<div class="modal-body">
<table class="table" id="msds-table" ng-show="vm.modalViewLoaded" infinite-scroll="vm.log()" infinite-scroll-container='"#msds-table"'
infinite-scroll-disabled="!vm.modalViewLoaded">
<thead>
<tr>
<th>CODE</th>
<th>TYPE</th>
<th>PRODUCT</th>
<th>ONBOARD</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="sheet in vm.datasheets | filter:onboardQuery | filter: (notOnBoardOnly ? {onboard:false} : {onboard:any})">
<td>{{sheet.code}}</td>
<td>{{sheet.type}}</td>
<td>{{sheet.product}}</td>
<td>
<span class="checkbox">
<input type="checkbox" data-ng-model="sheet.onboard" data-ng-value="sheet.onboard">
</span>
<span data-ng-show="!sheet.onboard">Click to select</span>
<us-list-select ng-model="sheet.located"
data-ng-show="sheet.onboard"
options="{list:vm.storageLocations}">
</us-list-select>
</td>
</tr>
</tbody>
</table>
<div ng-show="!vm.modalViewLoaded" style="text-align:center;padding-top:20px;">
<img src="images/ajax-loader.gif">
</div>
</div>
Any ideas?

Resources