I came across this post: HTML <ul> | Change particular <li> color onclick and other <li> in the same <ul> to default color
And it looks like what I'm looking for; but I was a bit confused as to how I'd do the same in a rails app (that's also using react/redux). In the rails apps that I've worked on so far, I have yet to see any jquery in them so I'm not sure where/how I'd implement the same idea. Any help is appreciated!
I thought about using the onClick
event for the li elements, and then making a function to add a class to the clicked element/remove the class from all other li elements, but I'm not sure if this is on the right track.
// this is my component rendering the ul element
import React from 'react';
import TrackIndexItem from './track_index_item';
const TrackDetail = ({ tracks }) => (
<ul>
{ tracks.map(track => <TrackIndexItem key={ track.id } track={track} />) }
</ul>
);
export default TrackDetail;
// this is my component rendering the li elements
import React from 'react';
const TrackIndexItem = ({ track }) => (
<li>
<div className="track-info">
<i className="music-note-icon"></i>
<div className="track-text">
<p>{track.title}</p>
<p>{track.artist} • {track.album}</p>
</div>
</div>
</li>
);
export default TrackIndexItem;
// this is my css for the li elements:
li {
display: flex;
flex-direction: row;
padding: 0 20px;
.track-info {
display: flex;
flex-direction: column;
position: relative;
.music-note-icon {
position: absolute;
content: image_url('music-note-icon.png');
width: 10px;
height: 15px;
top: 20px;
}
.track-text {
margin-left: 25px;
p {
font-family: 'ProximaNova-Regular';
}
p:first-of-type {
font-size: 18px;
color: $white;
}
p:last-of-type {
font-size: 16px;
color: $gray;
margin-top: -15px;
}
}
}
}
Anonymous Function Example
$(function() { $("li").click(function(e) { $(".clicked").removeClass(); $(this).addClass("clicked"); }); });
.clicked { border: 1px solid #CCC; border-radius: 3px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <ol> <li> <div className="track-info"> <i className="music-note-icon"></i> <div className="track-text"> <p>{track.title}</p> <p>{track.artist} • {track.album}</p> </div> </div> </li> <li> <div className="track-info"> <i className="music-note-icon"></i> <div className="track-text"> <p>{track.title}</p> <p>{track.artist} • {track.album}</p> </div> </div> </li> <li> <div className="track-info"> <i className="music-note-icon"></i> <div className="track-text"> <p>{track.title}</p> <p>{track.artist} • {track.album}</p> </div> </div> </li> </ol>
This specifically selects all clicked
class items, removes the class, and then adds it to the targeted element.
Here's a pure JS version that I was creating at the same time. It's also available on CodePen: https://codepen.io/edlucas/pen/LYEwjxO
Since you are using React, you could do something a bit different than the code example and add the onClick() directly in your JSX.
const TrackIndexItem = ({ track }) => (
<li onClick={e => highlight(e)}>
...
</li>
);
In that case, you could move the selectors into the highlight function (the only remaining place those variables would be used).
function highlight(e) {
const list = document.getElementById('trackList');
const items = list.querySelectorAll('li');
targetItem = e.target;
...
}
These functions could all all be added into your TrackIndexItem component file. removeClass()
and addClass()
are generic enough to move to a file containing helper/utility functions and imported into your TrackIndexItem file, if you prefer.
Working code snippet:
// Using pure JS, no jQuery const list = document.getElementById('trackList'); const items = list.querySelectorAll('li'); items.forEach((item) => { item.onclick = (e) => highlight(e); }); function highlight(e) { targetItem = e.target; // Remove the class from all items items.forEach((item) => { removeClass(item, 'active'); }); // Add the class to the "clicked" item addClass(targetItem, 'active'); } function removeClass(item, classVal) { classList = item.className.split(' '); item.className = classList.filter(item => item !== classVal).join(' '); } function addClass(item, classVal) { classList = item.className.split(' '); // Only add the class if it's not in the list if (!classList.includes(classVal)) { classList.push(classVal); } item.className = classList.join(' '); }
li { width: 100px; padding: 5px; margin-bottom: 5px; } li.bordered { border: 1px solid green; } li.active { background-color: yellow; }
<html> <body> <ul id="trackList"> <li class="bordered test">Test 1</li> <li class="bordered">Test 2</li> <li class="bordered">Test 3</li> </ul> </body> </html>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.