i want to add a table row by clicking Add, and remove a table row by clicking the small red div inside the table, while retaining the color change option when table is clicked on.
I've been trying for hours, but i'm still new to ReactJS, maybe someone could give me a hint, how to do this, for example with help of an array, a boolean or a for loop? I can't get the right way yet, would be thankful for your input.
i've been thinking about this kind of logic, but haven't been able to implement it yet..
{Boolean(this.state.rows.length) && (
<div onClick={this.handleRemoveRow}></div>
)}
https://jsfiddle.net/mattighof/0uop13kd/
Do the following:
Maintain a state say list and store all your items
Create onClick handlers for adding and removing items in the table
update the state when you add/remove
iterate and render this.state.list
Make sure to do event.stopPropagation() in the remove handler. this way your colour change functionality still works.
See here the implementation of adding and removing item
Code Snippet:
class Table extends React.Component {
constructor(props) {
super(props);
this.state = {
tableColor: true,
list: []
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
tableColor: !this.state.tableColor
});
}
addItem() {
this.setState({ list: this.state.list.concat("item") });
}
removeItem(e, index) {
e.stopPropagation();
this.setState({ list: this.state.list.filter((_, i) => index !== i) });
}
render() {
return (
<div className="container">
<button onClick={this.addItem} type="button">
Add
</button>
<table>
{this.state.list.map((item, index) => {
return (
<tr>
<td
className={this.state.tableColor ? "trRed" : "trBlack"}
onClick={this.handleClick}
>
{item}
<div
onClick={e => this.removeItem(e, index)}
className="innerDiv"
/>
</td>
</tr>
);
})}
</table>
</div>
);
}
}
This is one of the ways you can do it:
class Table extends React.Component {
constructor(props){
super(props)
this.state ={
rows:[{id:8,name:'item8',tablecColor:'trBlack'}],
tableColor: true
}
this.handleClick = this.handleClick.bind(this);
this.handleAdd = this.handleAdd.bind(this);
this.renderRows = this.renderRows.bind(this);
}
handleClick(clickedRow){
const {rows} = this.state;
let newRows = rows.map(row => {
if(row.id === clickedRow.id) {
row.tableColor = 'trRed'
return row
}
return row;})
this.setState({rows:newRows})
}
handleAdd() {
const {rows} = this.state;
const count = rows.length;
rows.push({id:count,name:count,tablecColor:'trBlack'})
this.setState({rows:rows})
}
renderRows() {
return this.state.rows.map(row => {
return (<tr>
<td className={row.tableColor}>
<div>{row.name}
<div onClick={() => this.handleClick(row)}
className="innerDiv">
</div>
</div>
</td>
</tr>)
});
}
render(){
return (
<div className="container">
<button type="button">Add</button>
<table>
{this.renderRows()}
</table>
</div>
)
}
}
ReactDOM.render(<Table />, document.querySelector("#app"));
Related
I would like to explain my problem of the day.
the code works correctly ,
the only problem is
when i click on my navbar to select a tab ,
my activeclassname works fine except that when i click elsewhere on the same page i lose my activeclassname
I would like him to be active permanently
Do you have an idea of how to fix this?
class MainHome extends Component {
constructor(props) {
super(props);
this.state = {
};
// preserve the initial state in a new object
this.toggle = this.toggle.bind(this);
this.cgtChange1= this.cgtChange1.bind(this);
this.cgtChange2= this.cgtChange2.bind(this);
}
cgtChange1() {
console.log('bière clicked')
this.setState({
cgt : 1
})
}
cgtChange2() {
console.log('cocktails clicked')
this.setState({
cgt :2
})
}
render() {
let addedItems = this.props.items.length ?
(
this.props.items.filter(item => item.ctg === this.state.cgt).map(item => {
return (
<div key={item.id}>
{item.title}
</div>
)
})) :
(
<div></div>
)
return (
<div>
<Header text='Carte'/>
<NavBar
onClick1={this.cgtChange1}
onClick2={this.cgtChange2}
/>
{addedItems}
</div>
)
}
}
NavBar
export default class FocusOnSelect extends Component {
render() {
return (
<div>
<button onClick={this.props.onClick1}
activeClasseName="selected" className='inactive' > Bières
</button>
</div>
<div >
<button onClick={this.props.onClick2} activeClasseName="selected" className='inactive' > Cocktails </button>
</div>
</div>
);
}
}
I have three buttons that when clicking show and individual div but this is done in reactjs
import React, { Component } from 'react';
export class ModeExtended extends Component {
constructor() {
super();
this.busButton = this.busButton.bind(this);
this.trainButton = this.trainButton.bind(this);
this.tramButton = this.tramButton.bind(this);
this.state = {
isHidden: false,
}
}
busButton(){
console.log('Bus Button Was Pressed');
this.setState((prevState) => {
return{
isHidden: !prevState.isHidden
};
});
}
trainButton(){
console.log('Train Button Was Pressed');
this.setState((prevState) => {
return{
isHidden: !prevState.isHidden
};
});
}
tramButton(){
console.log('Tram Button Was Pressed');
this.setState((prevState) => {
return{
isHidden: !prevState.isHidden
};
});
}
render() {
return (
<div>
<h5>Mode Extended</h5>
<button onClick={this.busButton}>Bus</button>
<button onClick={this.trainButton}>Train</button>
<button onClick={this.tramButton}>Tram</button>
{this.state.isHidden && (
<div>
<h6>You can show Bus Data Now....</h6>
</div>
)}
{this.state.isHidden && (
<div>
<h6>You can show Train Data Now....</h6>
</div>
)}
{this.state.isHidden && (
<div>
<h6>You can show Tram Data Now....</h6>
</div>
)}
</div>
)
}
}
export default ModeExtended
When I click any of the buttons it shows all bus, tram and train data - how do I get them to just show one thing at a time and making sure that the other states are closed. I am really missing something here and need a pointer or two or three…
How can I add an ID to make each button open separate from each other and when one is clicked how can I close the rest of the divs - or open state, I am so lost here. Please help me out.
Cheers as always!
Here is a REPL of my code:
You need to have 3 different isHidden properties to control your divs. You can do it like this:
this.state = {
isHiddenBus: false,
isHiddenTrain: false,
isHiddenTram: false,
}
and then in your render like this:
{this.state.isHiddenBus && (
<div>
<h6>You can show Bus Data Now....</h6>
</div>
)}
{this.state.isHiddenTrain && (
<div>
<h6>You can show Train Data Now....</h6>
</div>
)}
{this.state.isHiddenTram && (
<div>
<h6>You can show Tram Data Now....</h6>
</div>
)}
also your buttons have to change to state accordingly to this.
busButton(){
console.log('Bus Button Was Pressed');
this.setState((prevState) => {
return{
isHiddenBus: !prevState.isHiddenBus
isHiddenTram: false
isHiddenTrain: false
};
});
}
trainButton(){
console.log('Train Button Was Pressed');
this.setState((prevState) => {
return{
isHiddenTrain: !prevState.isHiddenTrain
isHiddenBus: false
isHiddenTram: false
};
});
}
tramButton(){
console.log('Tram Button Was Pressed');
this.setState((prevState) => {
return{
isHiddenTram: !prevState.isHiddenTram
isHiddenTrain: false
isHiddenBus: false
};
});
}
you can do somthing like this:
import React, { Component } from 'react';
export class ModeExtended extends Component {
constructor() {
super();
this.state = {
curDivIndex:0,//currently visible div index
// isHidden: false,
}
}
renderDiv=()=>{
switch(this.state.curDivIndex){
case 1:return <div> <h6>You can show Bus Data Now....</h6> </div>
case 2:return <div> <h6>You can show Train Data Now....</h6> </div>
case 3:return <div> <h6>You can show Tram Data Now....</h6> </div>
}
return null
}
setVisibleDiv=(index)=>{
this.setState({curDivIndex:index})
}
render() {
return (
<div>
<h5>Mode Extended</h5>
<button onClick={()=>{this.setVisibleDiv(1)} }>Bus</button>
<button onClick={()=>{this.setVisibleDiv(2)}}>Train</button>
<button onClick={()=>{this.setVisibleDiv(3)}}>Tram</button>
{this.renderDiv()}
</div>
)
}
}
export default ModeExtended
EDIT
you want to have three different buttons, on click of each certain div
needs to be visible.
you can achieve this by maintaining the index of currently visible div.
when user clicks any button you have to set the index of div to be visible
which in the above code is achieved by using setVisibleDiv(index) call.
and you can at rendering time use curDivIndex to decide visible div.
Or you can achieve this by declaring state properties for all case:
this.state = {
hiddenBus: false,
hiddenTrain: false,
hiddenTram: false,
}
providing a name attribute to your buttons like so:
<button name="hiddenBus" onClick={toggleDisplay}>Bus</button>
<button name="hiddenTrain" onClick={toggleDisplay}>Train</button>
<button name="hiddenBus" onClick={toggleDisplay}>Tram</button>
then by defining the toggleDisplay function to toggle their display:
toggleDisplay = (event) => {
event.preventDefault(); // default behavior of a clicked button is to send a form so let's prevent this
const { name } = event.target; // find the clicked button name value
this.setState((prevState => ({
[name]: !prevState[name],
}));
}
Setting[name] enables us to target the state prop via the nameattribute value and update it based on the previous state.
Try this
import React, { Component } from "react";
export default class Create extends Component {
constructor(props) {
super(props);
this.state = {
currentBtn: null
};
}
clickedButton = e => {
this.setState({ currentBtn: e.target.id });
};
showDivElem = () => {
const { currentBtn } = this.state;
switch (currentBtn) {
case "A":
return <div>A</div>;
break;
case "B":
return <div>B</div>;
break;
case "C":
return <div>C</div>;
break;
default:
return <div>ABC</div>;
break;
}
};
render() {
console.log(this.state.currentBtn);
return (
<div>
<button id="A" onClick={e => this.clickedButton(e)}>
A
</button>
<button id="B" onClick={e => this.clickedButton(e)}>
B
</button>
<button id="C" onClick={e => this.clickedButton(e)}>
C
</button>
{this.showDivElem()}
</div>
);
}
}
Fairly new with react. I'm creating a dropdown button for a Gatsby project. The button toggle works, but I'm having trouble getting the selected value to the parent where I need it.
-Tried lifting the state up, but this resulted in the button not appearing at all. I was a bit confused here so maybe I was doing something wrong.
-Also tried using refs although I wasn't sure if this was the right use case, it worked, however it seems the value is grabbed before it's updated in the child component and I'm not sure how to change or work around this. (the code is currently set up for this)
Are either of these options right? or could anybody steer me in the right direction, thanks.
Dropdown in parent:
this.dropdownRef1 = React.createRef();
componentDidUpdate(){
console.log("Color Option:" + this.dropdownRef1.current.state.ColorOption)
}
<DropdownBtn ref={this.dropdownRef1} mainText="Color" options={this.props.pageContext.colors || ['']} />
DropdownBtn:
export default class refineBtn extends React.Component {
constructor(props) {
super(props);
}
state = {
open: false,
[this.props.mainText + "Option"]: "all",
};
dropdownBtnToggle = () => {
this.setState((prevState)=> {
return{open: !prevState.open};
});
};
optionClickHandler = (option) => {
this.setState(() => {
console.log(this.props.mainText + " updated to " + option)
return {[this.props.mainText + "Option"] : option}
});
};
render(){
const options = this.props.options
console.log("open: " + this.state.open)
return(
<div>
<button onClick={this.dropdownBtnToggle} >
{this.props.mainText}:
</button>
<div className={this.state.open ? 'option open' : "option"} >
<p key={"all"} onClick={() => this.optionClickHandler("all")}> all</p>
{options.map(option => (
<p key={option} onClick={() => this.optionClickHandler(option)}>{option}</p>
))}
</div>
</div>
);
}
}
You can respond to selection by allowing your component to accept a callback.
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.state = {open: false, value: ''}
}
render() {
return (
<div>
<div onClick={() => this.setState({open: true})}>{this.state.value}</div>
<div style={{display: this.state.open ? 'block' : 'none'}}>
{this.props.options.map((option) => {
const handleClick = () => {
this.setState({open: false, value: option})
this.props.onChange(option)
}
return (
<div key={option} onClick={handleClick} className={this.state.value === option ? 'active' : undefined}>{option}</div>
)
})}
</div>
</div>
)
}
}
<MyComponent onChange={console.log} options={...}/>
I am new to react and I am working on a flight project.
I am attempting to update a shopping cart when items are selected. I am aware the structure of the code might not be the best way, but this is what I have so far.
Export class DestinationPrices extends React.Component {
constructor(props) {
super(props);
this.state = {
flightData: [],
checked:false,
data:'',
cart:[]
};
this.handleClick = this.handleClick.bind(this);
this.handleAddToCart = this.handleAddToCart.bind(this);
}
NavCart() {
return (
<div className="Nav" >
<Card body >
<CardTitle ><h3><b>Flights Selected : </b></h3></CardTitle>
<CardText >
<span className="fa fa-cart-plus fa-2x"> {this.props.cart.length}</span>
</CardText>
</Card>
</div>
)
}
That is the cart itself which should update number of items when selected.
Below is the Select method which you can select the different cards.
Select(FD) {
this.state={route:''};
return (
<div>
{FD.FlightID}
<label>
<Checkbox id={FD.FlightID}
name={FD.FlightID}
checked={this.setState.route}
onChange={(()=> this.handleCheckboxChange(FD.FlightID))}
handleClick={()=>{this.handleClick(FD.FlightID)}}
/>
<span>Select</span>
</label>
</div>
)
}
These are the functions I have to handle the changes
handleCheckboxChange =(id) =>{
var data;
const selected = (e => e.FlightID = id);
this.handleAddToCart(id);
};
handleAddToCart(flight) {
const cartItem = this.state.cart.find(x => x.id === flight.id);
this.setState({cart: [...this.state.cart, flight]})
}
handleClick(flight) {
this.handleAddToCart(flight)
}
If anyone is able to help it would be greatly appreciated.
I'm having issues with setting my input text fields to be blank using Refs. You could think of my UI that of a mail inbox app. When I click on the side panel, using the func openIssue() to display the issues in <IssueDetails/> by clicking on an issue from <IssueList/>. My problem is that when I enter values into the input text field. That value is carried on into the next issue's text input value after I click on a new issue in the <IssueList/>.
I've used the following as a guide: Clear an input field with Reactjs?, https://reactjs.org/docs/refs-and-the-dom.html however, what I get hit with is TypeError: Cannot set property 'value' of undefined, how do I over come this?
class App extends Component {
constructor(props) {
super(props);
this.state = {
isLoaded: false,
issues: [],
counter: 0,
selectedIssueId: 0,
currentSection: "inbox",
showIssueBox: true
};
this.sendThru = this.sendThru.bind(this);
}
openIssue(id) {
const issues = this.state.issues;
let copyOfStateIssues = issues.slice();
let modifiedStateWithHighlight = copyOfStateIssues.map(obj => {
if (obj.id !== id) {
obj.highlighted = false;
} else {
obj.highlighted = true;
}
return obj;
});
this.setState({
selectedIssueId: id,
modifiedStateWithHighlight,
issues: modifiedStateWithHighlight
});
this.sendThru();
}
sendThru(el) {
this.inputTitle.value = "";
}
render() {
return (
<div className="App">
{this.state.showIssueBox ? (
<IssueBox
issues={this.state.issues}
selectedIssueId={this.state.selectedIssueId}
onIssueSelected={id => {
this.openIssue(id);
}}
inputRef={el => (this.inputTitle = el)}
/>
) : (
<div />
)}
</div>
);
}
}
class IssueBox extends Component {
render() {
const currentIssue = this.props.issues.find(
x => x.id === this.props.selectedIssueId
);
return (
<div className="wrapper">
<div className="inbox-container">
<IssueList
issues={this.props.issues}
onIssueSelected={this.props.onIssueSelected}
selectedIssueId={this.props.selectedIssueId}
/>
<IssueDetails
issues={this.props.issues}
issue={currentIssue}
onInputRef={this.props.inputRef}
/>
</div>
</div>
);
}
}
class IssueDetails extends Component {
constructor(props) {
super(props);
this.state = {
currentPage: 1,
urlsPerPage: 5,
activeItem: 0
};
}
render() {
const issueDummy = currentURLs.map((obj, i) => {
const noIssueID = (
<input
ref={this.props.onInputRef}
type="text"
onChange={this.props.onInputUpdate.bind(this, obj)}
/>
);
return (
<tr role="row" key={i}>
<td role="cell" style={td4Styles}>
{issue.verified === true ? hasIssueID : noIssueID}
</td>
</tr>
);
});
return (
<div className="issue-content">
<div className="issue-content__message">
<div className="url_div_container">
<form
onSubmit={this.props.onVerifiationSubmission.bind(this, issue)}
>
<table>
<tbody className="group-row">{issueDummy}</tbody>
</table>
</form>
</div>
</div>
</div>
);
}
}
My goal is to clear the text input field of the previously entered after I click on a new issue from <IssueList>, which is triggered by openIssue(). Thus rendering a new set of issues and text input field for < IssueDetails>