I have a div mapped so it would render any number of times according to data sent from the database. I'm setting a background color in the div when clicking on the div. How can i revert the changes if i click the div again?
My code
handleClick(id) {
let el = document.getElementById(id);
if (el) {
el.style.backgroundColor = "#0b97c4";
el.style.color = "#FFFFFF";
this.setState({
voteCount: this.state.voteCount + 1
})
}
this.props.submitvote(vote_object)
}
render() {
let {contents, submitvote, postId, voted_id} = this.props
return (
<div className="txt_vote_bar_div" id={this.props.contents.post_poll_content_id}>
<p className="txt_vote_choice" id={this.props.contents.post_poll_content_id}
onClick={() => {this.handleClick(this.props.contents.post_poll_content_id);}}>
{contents.content}
</p>
<p className="txt_tot_votes"> {this.props.contents.votes_percentage}%
({this.state.voteCount} Votes)
</p>
</div>
);
};
using the above code i'm changing the background of the div successfully. How can i remove the background color if i select the same div again (remove background color or change it to another color)
I would make txt_vote_choice "old" CSS name, and txt_vote_clicked is new className that you want to change. By onClick, toggle the className between these 2 classes would do the trick.
handleClick(id) {
let el = document.getElementById(id);
if (el) {
if el.class == "txt_vote_choice" ? "txt_vote_clicked": "txt_vote_choice";
this.setState({
voteCount: this.state.voteCount + 1
})
}
this.props.submitvote(vote_object)
}
render() {
let {contents, submitvote, postId, voted_id, voted_css} = this.props
return (
<div className="txt_vote_bar_div"
id={this.props.contents.post_poll_content_id}>
<p className={voted_css}
id={this.props.contents.post_poll_content_id}
onClick={() => {this.handleClick(this.props.contents.post_poll_content_id);}}>
{contents.content}
</p>
<p className="txt_tot_votes">
{this.props.contents.votes_percentage}%({this.state.voteCount} Votes)
</p>
</div>
);
};
Then update the CSS accordingly
if it is just an "on-off" feature, you can check for the "active" style already on your div like this : if (el.style.backgroundColor == "#0b97c4";) //if the style is already there: then you run some code that put your div the right color
if (el)
{
if (el.style.backgroundColor == "#0b97c4";) //if the style is already there:
{
el.style.backgroundColor = "#FF0000";
el.style.color = "#000000"; //put theese 2 colors to the "unactivated" ones
//other code when you unselect goes here like this.state.voteCount - 1
}
else
{
el.style.backgroundColor = "#0b97c4";
el.style.color = "#FFFFFF";
this.setState({
voteCount: this.state.voteCount + 1
})
}
}
Related
I have list of items and I am changing the background color when I clicked on that item...
I need to change only the current Selected Item only , Previous selected Item should deselect... Now here, all items are getting changed when I clicked on each item... How can I solve this?? Can anyone help me in this ??
Here is my code
const Time = () => {
const [selectedItem, setSelectedItem] = React.useState();
const handleSelect = (event,selectedItem) => {
setSelectedItem(selectedItem);
event.target.style.backgroundColor = 'black';
event.target.style.color = 'white';
};
const dataTime = useMemo(() => TimeData, []);
const chunks = useMemo(() => {
const _chunks = [];
const tmp = [...dataTime];
while (tmp.length) {
_chunks.push(tmp.splice(0, 3));
}
//console.log(_chunks);
return _chunks;
}, [dataTime]);
return (
<div className="Main-Section">
<div className="First-Section">Time</div>
<div className="Second-Section">
<div className="date_title">Wednesday , June 13</div>
<div className="time_Slots">
{chunks.map((timeslot) => {
return (
<div key={timeslot} className="inline">
{timeslot.map((time) => {
return <p className='timeslots target' key={time}
onClick={(event) => handleSelect(event,time)}>{time}</p>;
})}
</div>
);
})}
</div>
<div>{selectedItem}</div>
<div className='new_Date'>PICK A NEW DATE</div>
</div>
</div>
);
};
U can struct Ur time data to an object like this...
{text:"",selected:false}
and use selected property flag in data then assign a class conditionally into items based on that flag. then in clicking iterate Ur list and make all the flags false except the selected one.
function selectFn(selectedItem) {
data.forEach((item) => {
item.selected = false;
});
selectedItem.selected = true;
}
and UR template be some
...
{chunks.map((timeslot) => {
return (
<div key={timeslot} className="inline">
{timeslot.map((time) => {
return <p className={`timeslots target ${time.selected ? "selectedClass" : ""}`} key={time.text}
onClick={(event) => selectFn(time)}>{time.text}</p>;
})}
</div>
);
})}
...
the css stuff..
.selectedClass{
background:black;
color:white;
}
you have to first change color for all the element to default color. Then you have to change the current element color to desired color.
I have the following element with onclick event that will color the clicked paragraph to red if user clicked on:-
<p
onClick={(e)=> e.currentTarget.style.color = "red"}
>
Click here
</p>
<p
onClick={(e)=> e.currentTarget.style.color = "red"}
>
Another Paragraph
</p>
<p
onClick={(e)=> e.currentTarget.style.color = "red"}
>
Another Paragraph
</p>
How can reset the color back to it original black color if user clicked else where on the page or clicked on another paragraph.
You can write an eventhandler for the <body> element. Click events 'bubbles' up to the <body> if they're not cancelled. You should cancel your events, so they don't 'bubble' up to the <body>:
<p onClick={(e)=> e.currentTarget.style.color = "red"; e.stopPropagation();}>
Click here
</p>
Now just set the color of all <p> elements:
<body onClick = {() => e.target.nodeName == "DIV" && (e.target.style.color = "black");}>
You really shouldn't be modifying the DOM directly from a React app. Use state instead:
function Paragraph (props) {
const [selected, setSelected] = React.useState();
const style = selected ? { color: red } : undefined;
return (
<p {...props} style={style} />
)
}
To reset it when the user clicks elsewhere, you could add an event listener to document.body while it's in the selected state. Something like this:
function Paragraph (props) {
const [selected, setSelected] = React.useState();
const style = selected ? { color: red } : undefined;
React.useEffect(() => {
if (selected) {
// you'd probably want to check to see if the click target
// is the current element; omitted here for simplicity
const onClick = () => setSelected(false);
document.body.addEventListener('click', onClick);
// remove the listener on unmount or when selected state changes
return () => document.body.removeEventListener('click', onClick);
}
}, [selected])
return (
<p {...props} style={style} />
)
}
Even better, use a className instead of an inline style:
<p {...props} className={selected ? 'selected' : ''} />
.selected { color: red; }
You can use something else then classes. Also keep in mind this way you have event click on all elements on page, so if you need it later just expand this...
Also this can be re-written in many ways to suit the needs.
const click = document.querySelectorAll(".click");
[...document.querySelectorAll('body')].forEach(el => {
el.addEventListener('click', event => {
if (event.target.className.includes("click") === true) {
click.forEach(p => {
p.style.color = "black";
})
event.target.style.color = "red";
} else {
click.forEach(p => {
p.style.color = "black";
})
}
})
})
div {
width: 100% height:100%
}
<div>test div
<p class="click"> dont Click here
</p>
test div1
</div>
<p class="click"> dont Click here
</p>
<div>test div2
<p class="click"> dont Click here
</p>
</div>
I'm creating a gameBoard, and having trouble toggling background colors for button divs. The toggle works for individual clicks on the "buttons" (styled divs), but when I click adjacent buttons it requires two clicks to get the next button to change its background color. How can I get adjacent buttons to toggle on first click? I've read some related posts like (Changing style of a button on click) but still struggling to get this working -
Related code below,
full code: https://jsfiddle.net/lydiademi/kt2qgfpr/
TY!
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
color: '#FFF',
color_white: true,
currentWord: '',
board1: [],
row1: ["aaafrs","aaeeee","aafirs","adennn","aeeeem"],
}
this.clicked = this.clicked.bind(this);
}
componentWillMount() {
let letter1 = '';
this.state.row1.forEach(die => {
letter1 = die[Math.floor(Math.random() * 6)].toUpperCase();
if (letter1 === 'Q') {
this.state.board1.push("Qu")
} else {
this.state.board1.push(letter1);
}
})
}
clicked(event) {
//change background color
let newColor= this.state.color === "#FFF" ? "#ACCEEC" : "#FFF";
this.setState({ color: newColor });
event.target.style.backgroundColor = newColor;
}
render () {
return (
<div id="board">
<div className="row">
{
this.state.board1.map((letter, index) => {
return (
<div className="btn" onClick={(e) => {this.clicked(e)}}>
{letter}
</div>
)
})}
</div>
)
}
Issue is :
You are maintaining one variable for all the elements bg toggle,
So the code is working as it should,
There is no need for maintaining state for that.
What you can do is :
Set extra attribute data-color like this
<div className="btn" data-color='#FFF' onClick={(e) => {this.clicked(e)}}>
And change bg color and attr based upon data-color , onClick like this
clicked(event) {
// get current color of element
let currentColor = event.target.attributes['data-color'].value;
// apply condition based upon currentColor
let newColor = currentColor === "#FFF" ? "#ACCEEC" : "#FFF";
// set the bg color
event.target.style.backgroundColor = newColor;
// change the data-color value to currentColor
event.target.setAttribute('data-color' , newColor);
// add letter to state.currentWord
let letter = event.target.innerText;
this.setState({ currentWord: this.state.currentWord + letter })
}
Here is the link to working fiddle :
https://jsfiddle.net/vivekdoshi2/kt2qgfpr/2/
So i have an array like this const divs = ["Text 1","Text 2","Text 3"].
I create divs (a small menu) from this array in my render function
var createThreeDivs = divs.map((category) => {
return <div key={category} onClick={this.handleClick} className="myDivClass">{category}</div>
});
I want to style one of these divs when i click on them, and the remove the styling on the rest of them. So when i select one of the divs it gets a color and removes the color on the rest of them
In normal javascript with no virtual DOM i could do like this:
handleClick(e) {
//remove styling from others
var allDivs = document.getElementsByClassName("myDivClass");
for(var i = 0; i < allDivslength; i++) {
allDivs[i].classList.remove("myDivClass-styled");
}
//Add styling class to selected,
e.target.classList.add("myDivClass-styled");
}
But this manipulate the DOM directly. How do i do something like this in React?
I have seen examples of how this can be done using state with only one element and by not having an array creating the divs. But i can't come up with a good solution for this scenario. Any suggestions?
Using the component's state you can update the color based on the active div. Update the index of the active div when the user clicks, and when the index equals the div that was clicked on update the color of that div.
See example below.
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
active: 0
};
}
render() {
const divs = ["Text 1", "Text 2", "Text 3"];
const updateActiveDiv = (value) => {
this.setState(() => {
//this line will reset the value to
//null if same element is clicked twice
if(value === this.state.active) {
value = null;
};
return {
active: value
}
});
};
let divText = divs.map((div, i) => {
let color = this.state.active === i ? 'red' : 'black';
return <div style={{ color }} onClick={() => updateActiveDiv(i)}>{div}</div>;
});
return (
<div>
{ divText }
</div>
);
}
}
ReactDOM.render(<Example />, document.getElementById('root'));
<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>
<div id="root"></div>
Pass current text from html
handleClick = (text)=>{
this.setState({activeText:text})
}
Inside create div function add class dynamically
Div className = { stat condition ? Class : no class }
On hover of any of the above items I want to surround item with a box having grey color background.
and onclick I want to change it to something like below (surround with a box having background color as text color, change text color to white and have a x in the box). Clicking on x should bring it back to the normal state as depicted in image 1.
Current code:
export default class GridSummary extends Component {
renderJobStateSummary() {
const jobCountSummaryDiv = [];
if (this.props.jobStateCount.size !== 0) {
jobCountSummaryDiv.push('Summary: ');
for (const state of ['Total', ...jobStatesPriorityOrder]) {
if (this.props.jobStateCount.has(state) &&
this.props.jobStateCount.get(state) !== 0) {
const cssClass = `${JOB_STATES_CSS_CLASS[state]} clickable`;
jobCountSummaryDiv.push(
<span
className={cssClass}
role="link"
tabIndex="-1"
key={state}
>
{JOB_STATE_DISPLAY_NAME[state]}: {this.props.jobStateCount.get(state)}
</span>
);
jobCountSummaryDiv.push(' | ');
}
}
}
return jobCountSummaryDiv;
}
render() {
return (
<div className="summary-panel">
{ this.renderJobStateSummary() }
</div>
);
}
}
Try with pseudo class combination of :hover and :active. For guest it likes button.
In style border option use combination of inset and outset, it gives very good visuel.