How to dynamically change the css style of a particular item inside a map function - html

I currently have two map functions to render a board for a chess game like this:
<div className='board'>
{rows.map((item) => (
<div key={item} className='row'>
{item.map((square) => (
# The square <div> => <div key={square[0]} className='square' onClick={() => {
board.select !== null &&
checkColour(board.select[1]) !== checkColour(square[1]) && dispatch(move(square))
}}>
{isNaN(square[1]) && <img src={square[1]} alt={square[1]}
onClick={() => { board.turns === checkColour(square[1]) && dispatch(select(square)) }}
className={board.select === square ? 'piece-selected' : 'piece'} />}
</div>
))}
</div>
))}
</div>
Now, I want to change the css style of certain squares <div> after I selected a pawn piece in order to forecast a shadow for showing the possible moves. I want to know is it possible to access the css style of that particular square <div> using the key of that <div>?
Feel free the drop a comment below if you have any insight or idea. Let me know if you want more info. Much appreciated.

Related

ReactJs App's mapped list of buttons from Json file only have the last value of json array

I am making list of button that will lead to different YouTube videos on ReactJs page. The issue is that when I map the links from json file (which contains video links), all the buttons get the last link of the mapped array. I need a way that all the rendered buttons will get their respective links. My code is below, I am using react ModalVideo to show my YouTube video.
<ul className="list-unstyled">
{datalist.lectures.map((value, index) => {
return (
<li key={index}>
<ModalVideo channel='youtube' autoplay isOpen={isOpen} videoId={value} onClose={() => setOpen(false)} />
<button className="play-icon" onClick={()=> setOpen(true)}> <i className="las la-play"></i> Lecture: {index+1}</button>
</li>
)})}
</ul>
All the links are coming from Json file where the code looks like this
"lectures": [
"BT4YihNXiYw",
"NSFLhnv2pQI",
"sEPxqpFZit8",
"fU8QhoUJ_sE",
"r3XFYOtvUng",
"MZAkMddxhpg"
]
I think the problem I have right now is that after the page render and mapping ends it only remembers what the last link is store in value, because of that no matter which button i click it shows me the last value of the mapped array
Just some quick ideas looking at the minimal snippets available.
let's not to render multiple ModalVideo component like above, move it out from the map.
Use another state to keep track the change of the youtube videos' ID.
For example
const [isOpen, setOpen] = useState(false);
const [videoId, setVideoId] = useState(null);
const playVideo = (vid) => {
setOpen(true);
setVideoId(vid);
};
return (
<div>
<ModalVideo
channel='youtube'
autoplay
isOpen={isOpen}
videoId={videoId}
onClose={() => setOpen(false)}
/>
<ul className="list-unstyled">
{
datalist.lectures.map((value, index) => {
return (
<li key={index}>
<button className="play-icon" onClick={() => playVideo(value)}>
<i className="las la-play"></i>
Lecture: {index + 1}
</button>
</li>
)
})
}
</ul>
</div>
);

When I try to change colour depends on the count it show's the error TypeError: Cannot read property 'style' of null

In the below I would like to change the colour to black if the count is === 0
if(Count === 0){
document.getElementById('value').style.color = 'black';
}
return(
<div className='container_new'>
<h1>Counter</h1>
<span id='value'>{Count}</span>
<div>
<button className="btn decrease" onClick={handleDecrement} >decrease</button>
<button className="btn reset" style={{color: 'black'}} onClick={() => handleReset()}>reset</button>
<button className="btn increase" onClick={() => handleIncrement()}>increase</button>
</div>
</div>
)
You can achieve what you wanted this way.
return(
<div className='container_new'>
<h1>Counter</h1>
<span id='value' style={{ color: Count === 0 ? 'black' : 'white' }}>{Count}</span>
<div>
<button className="btn decrease" onClick={handleDecrement} >decrease</button>
<button className="btn reset" style={{color: 'black'}} onClick={() => handleReset()}>reset</button>
<button className="btn increase" onClick={() => handleIncrement()}>increase</button>
</div>
</div>
)
in react.js i would approach this differently because it render and change the DOM (html tree)
so maybe instead of using
**document.getElementById('value').style.color = 'black';**
make a class in CSS and change the className based on the Count
like this
css class
.black {
color : black;
}
.green {
color : green;
}
react.js code
<span id='value' className={Count === 0 ? "black" : "green" } >{Count}</span> // tell me if this line is understandable
replace this line with your line and see if is working !
it would help me understand better if you show us the the handle increment function handle reset and handle decrement :)
Create a local state for the count and track the update. Based on the count value in the state, update the template style.
const [count, setCount] = useState(0);
return(
<div className='container_new'>
<h1>Counter</h1>
<span id='value'>{count}</span>
<div>
<button className="btn decrease" onClick={handleDecrement} >decrease</button>
<button className="btn reset" style={{color: (count === 0 ? 'black': 'green')}}
onClick={() => setCount(0)}>reset</button>
<button className="btn increase" onClick={() => handleIncrement()}>increase</button>
</div>
</div>
I believe, your react state is state = { Count: 0 }, If yes, when react starts initial rendering, you're trying to get the element by id, at this time, there no element(not rendered) with <span id='value'>{Count}</span> which returns null. That's why you're getting this error Cannot read property 'style' of null.
But, you can simply use following solution
<span id="value" style={{ color: Count === 0 ? 'black' : 'green' }}>{Count}</span>

Slide in animation in react js

I have a list of to-do task. I want to display one task per screen and when the user clicks the next button he should be able to see the next. I want to achieve it with slide animation. I came across react-transition-group package which can be used to for animation. But the slide animation is not working properly.
https://codesandbox.io/s/transitiongroup-component-zjzep
<CSSTransition
in={currentPage === 1}
key={1}
timeout={500}
classNames="item"
>
<ListGroup.Item>
<Button
className="remove-btn"
variant="danger"
size="sm"
onClick={() => {}}
>
×
</Button>
{'a'}
</ListGroup.Item>
</CSSTransition>
<CSSTransition
in={currentPage === 2}
key={2}
timeout={500}
classNames="item"
>
<ListGroup.Item>
<Button
className="remove-btn"
variant="danger"
size="sm"
onClick={() => {}}
>
×
</Button>
{'b'}
</ListGroup.Item>
</CSSTransition>
Finally, I manage to achieve it. Earlier I was using float to keep all the elements in one line. I change it with position absolute.
https://codesandbox.io/s/transitiongroup-component-zjzep

v-for loop display only unique items vue js

Am trying to display icons based on the v-for and v-if conditions , but the icons are displayed multiple times , i need to display only the unique ones.
I tried v-if = 'index === 0' but instead this doesn't work
<div v-for="(bits, index) in inv.auction.Bits" :key="index">
<div v-if="bits.iswin == true && bits.userid == d.userid">
<b-tooltip label="mine" position="is-right">
<b-icon class="iswinclass" icon="thumb-up" type="is-success"></b-icon>
</b-tooltip>
</div>
<div v-if="bits.iswin == false && bits.userid == d.userid">
<b-tooltip label="mine" position="is-right">
<b-icon class="iswinclass" icon="thumb-down" type="is-danger"></b-icon>
</b-tooltip>
</div>
</div>
I want one thumb-up and one thumb-down to display if the condition matches instead multiple icons are displayed
Sounds like you have multiple items in inv.auction.Bits that match d.userid but you only want to show one each of your icons if there are any matches.
I would, instead of looping inv.auction.Bits, create two computed properties to determine when to show your icons.
For example
computed: {
showThumbsUp() {
return this.inv.auction.Bits.some(({ iswin, userid }) =>
iswin && userid === this.d.userid)
},
showThumbsDown() {
return this.inv.auction.Bits.some(({ iswin, userid }) =>
!iswin && userid === this.d.userid)
}
}
and in your template (no v-for)
<div v-if="showThumbsUp">
<b-tooltip label="mine" position="is-right">
<b-icon class="iswinclass" icon="thumb-up" type="is-success"></b-icon>
</b-tooltip>
</div>
<div v-if="showThumbsDown">
<b-tooltip label="mine" position="is-right">
<b-icon class="iswinclass" icon="thumb-down" type="is-danger"></b-icon>
</b-tooltip>
</div>
References:
Array.prototype.some()

Best Approach to separate Form sections

I have the following view inside my Asp.net MVC web application :-
p class="b"> <i class="icon-th"></i>Network Info :</p>
<div>
<span class="f">IP Address</span>
#Html.TextBoxFor(model => model.NetworkInfo.IPADDRESS)
#Html.ValidationMessageFor(model => model.NetworkInfo.IPADDRESS)
|
<input type="CheckBox" name="IsIPUnique" value="true" #(Html.Raw(Model.IsIPUnique ? "checked=\"checked\"" : ""))/> IP Unique.
</div>
<div >
<span class="f">MAC Address</span>
#Html.TextBoxFor(model => model.NetworkInfo.MACADDRESS)
#Html.ValidationMessageFor(model => model.NetworkInfo.MACADDRESS) |
<input type="CheckBox" name="IsMACUnique" value="true" #(Html.Raw(Model.IsMACUnique ? "checked=\"checked\"" : ""))/> MAC Unique.
</div>
<div >
<span class="f"> ILOIP</span>
#Html.EditorFor(model =>model.Server.ILOIP)
#Html.ValidationMessageFor(model =>model.Server.ILOIP)
</div>
</p>
<p = class="b"><i class="icon-th"></i>Server Status :</p>
<div>
<span class="f">Server Status </span>
#Html.DropDownListFor(model =>model.Server.StatusID, ((IEnumerable<TMS.Models.TechnologyStatu>)ViewBag.TechStatus).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.Name),
Value = option.TechnologyStatusID.ToString(),
Selected = (Model != null) && (Model.Server != null) && (option.TechnologyStatusID == Model.Server.StatusID)
}), "Choose...")
#Html.ValidationMessageFor(model =>model.Server.StatusID)
</div>
<div>
<span class="f">Server Back Up Status</span>
#Html.DropDownListFor(model =>model.Server.BackUpStatusID, ((IEnumerable<TMS.Models.TechnologyBackUpStatu>)ViewBag.TechBackUpStatus).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.Name),
Value = option.TechnologyBackUpStatusID.ToString(),
Selected = (Model != null) && (Model.Server != null) && (option.TechnologyBackUpStatusID == Model.Server.BackUpStatusID)
}), "Choose...")
#Html.ValidationMessageFor(model =>model.Server.BackUpStatusID)
</div>
I tried to put each section header in a separate <p>, but the output was not very use-friendly. so which approach i can follow to separate each paragraph , so the user can understand each section fields better. as in the current output all the fields will be under each other without having space between each section?
This isn't really a question about MVC or Razor, but about HTML and CSS styling. And for that you have a lot of options:
You currently wrap all of your fields in div elements. You could style those div elements however you like. If you want to add vertical padding, you can use something like padding-top: 20px; or whatever ends up looking like you want it to look.
You said you tried a p element. This isn't really "paragraph" data, but the same concept as the div element applies. You can style it however you like.
You could wrap the fields in a fieldset element. Remember that this requires a legend element as its first child element, which could contain a heading for that grouping of fields. (Which would probably replace those span elements you currently use.) There's a good chance that the default styling for your MVC project has considerations for fieldset already in the CSS.
You may also want to consider using #Html.LabelFor() while styling this as well, to provide field-level labels. But it's hard to tell if you need that for the effect you're trying to achieve. Normally a default form would have a fieldset with a legend and then a series of labels and inputs therein.
The options could go on and on. The point is that you're working with HTML and CSS at this point, so you'll want to show the client-side code and perhaps either a screen shot or live example of what you're trying, how you expect it to look, and how it's not working as expected. That is, after you've tried tinkering with the styling of course.