Conditional classname not changing even after value changes - javascript

I'm building a page with two tabs. When one tab is clicked, the other tab should have the className="nav-link active" and the other tab should switch to className="nav-link" and vice-versa.
Here's my code:
import react from 'react'
const account = () => {
const [activeTab, tabActive] = react.useState("true")
return (
<>
<div className='container my-5'>
<ul className="nav nav-tabs">
<li className="nav-item">
<button type="button" className={"nav-link " + (activeTab?'active':'')} onClick={() => tabActive("true")}>Profile details</button>
</li>
<li className="nav-item">
<button type="button" className={"nav-link " + (activeTab?'':'active')} onClick={() => tabActive("false")}>Select Colleges</button>
</li>
</ul>
</div>
<div className='container my-5'>
{
activeTab === "true" && <p>Value is true</p>
}
{
activeTab === "false" && <p>Value is false</p>
}
</div>
</>
)
}
export default account
The aforementioned code should be able to do what I expect, however, I can't get the active class removed and added to the buttons as expected. It's either being applied to both buttons at the same time or two none at all.

Non-empty strings are always truthy. Use booleans instead.
const account = () => {
const [activeTab, tabActive] = react.useState(true);
return (
<>
<div className='container my-5'>
<ul className="nav nav-tabs">
<li className="nav-item">
<button
type="button"
className={"nav-link " + (activeTab ? 'active' : '')}
onClick={() => tabActive(true)}
>
Profile details
</button>
</li>
<li className="nav-item">
<button
type="button"
className={"nav-link " + (activeTab ? '' : 'active')}
onClick={() => tabActive(false)}
>
Select Colleges
</button>
</li>
</ul>
</div>
<div className='container my-5'>
{activeTab ? <p>Value is true</p> : <p>Value is false</p>}
</div>
</>
)
};
Update
For more than 2 tabs use an index or GUID, anything that uniquely identifies a tab, to store in state for the active tab, and check this value for matching when rendering.
Example:
const account = () => {
const [activeTab, tabActive] = react.useState(0);
return (
<>
<div className='container my-5'>
<ul className="nav nav-tabs">
<li className="nav-item">
<button
type="button"
className={"nav-link " + (activeTab === 0 && 'active')}
onClick={() => tabActive(0)}
>
Profile details
</button>
</li>
<li className="nav-item">
<button
type="button"
className={"nav-link " + (activeTab === 1 && 'active')}
onClick={() => tabActive(1)}
>
Select Colleges
</button>
</li>
<li className="nav-item">
<button
type="button"
className={"nav-link " + (activeTab === 2 && 'active')}
onClick={() => tabActive(2)}
>
Select Something Else
</button>
</li>
</ul>
</div>
<div className='container my-5'>
{activeTab === 0 && <p>Active tab is 0</p>}
{activeTab === 1 && <p>Active tab is 1</p>}
{activeTab === 2 && <p>Active tab is 2</p>}
</div>
</>
)
};

Related

React Tabs - unable to move to next and previous tab programatically using buttons

I have a div in which i have 3 tabs and 2 buttons "Back" and "Next".
What I want to acheive is that on click of "Next" button I should move to the next tab and on click of "Back" button I should move to the previous tab.
I have used the below code but it is not working
const [ins, setIns] = useState(false)
const [pre, setPre] = useState(true);
const [ques, setQues] = useState(false);
const [selectedTab, setSelectedTab] = useState(0);
const tabCount = 3
const onTabClick = (category, val) => {
updateTab([category], val);
}
const updateTab = (category, type) => {
if (type === 'ins') {
setSelectedTab(0)
setIns(true)
setPre(false
setQues(false)
}
if (type === 'pre') {
setSelectedTab(1)
setIns(false)
setPre(true)
setQues(false)
}
if (type === 'ques') {
setSelectedTab(2)
setQues(true)
setIns(false)
setPre(false)
}
<div>
<ul>
<li className="nav-item">
<button
type="button"
className={ins ? 'nav-link pb-3 active' : 'nav-link pb-3'}
onClick={() => { onTabClick('infoTabs', 'ins') }}>
Ins
</button>
</li>
<li className="nav-item">
<button
type="button"
className={pre ? 'nav-link pb-3 active' : 'nav-link pb-3'}
onClick={() => { onTabClick('infoTabs', 'pre') }}>
Pre
</button>
</li>
<li className="nav-item">
<button
type="button"
className={ques ? 'nav-link pb-3 active' : 'nav-link pb-3'}
onClick={() => { onTabClick('infoTabs', 'ques') }} >
Ques
</button>
</li>
</div>
<div>
<button
type="button"
onClick={() => setSelectedTab((selectedTab + tabCount - 1) % tabCount )}
>
Back
</button>
</div>
<div >
<button
type="button"
onClick={() => setSelectedTab((selectedTab + 1) % tabCount )}
>
Next
</button>
</div>
}

How to handle change of onClick on dropdown menu in react.js

I need your advice and suggest, I have here a react app that has three main component: search bar, cards, and filters. In the filters I have a drop down menu that contain at least 11 vlaues. so what I want that I create function that handle the change when I onclick one of the values and search for it.
I face two problems:
how to create on handle function for 11 elements
how to search for it after one click, because I try to test with one element and change after two clicks
The code:
//Function to create the cards with their property values
function CreateCards(doc) {
return (
<SimpleCard
key={doc.id}
theCardId={doc.id}
cardType={doc.approvetool}
cardNum={doc.num}
cardName={doc.name}
cardDate={format(new Date(doc.date), "dd/MM/yyyy")} // casting the system date to arabic date
// cardCategory={NCARMap.cardCategory}
// cardSource={NCARMap.cardSource}
cardDesc={doc.summary}
cardURL={doc.image}
/>
);
}
//create the class
export default class OfficialDocument extends Component {
//constructor elements
constructor(props) {
super(props);
//initially no data entered
this.state = {
NCARMap: [], // for print cards and changeable
NCARMapAS: [], // for print cards and unchangeable (Default value always)
search_query: "", // store the query word
search_query_drop: "", // to store the query word of drop down menu
noPlaceFound: false, // condition to print message when no result up
size_query: 0, // for set the size or number of docs to return
highlight: "",
};
this.handleChange = this.handleChange.bind(this);
this.DropDownChangeOne = this.DropDownChangeOne.bind(this);
}
componentDidMount() {
//Get NCARMap data, NCARMapAS used for filtering and sorting the cards once get the page
axios
.get(
"http://localhost:9200/ncar_index/ncar/_search?size=100&sort=date:desc"
) //size to define the total docs to get / sort: sort the data for which field you want: asc or desc (desc for reverse)
.then((resp) => {
console.log(resp);
this.setState({
NCARMap: resp.data.hits.hits,
NCARMapAS: resp.data.hits.hits,
});
});
}
//function that handle the onChange on searchbar
handleChange(event) {
console.log(event.target.value);
this.setState({
search_query: event.target.value,
highlight: event.target.value,
});
axios
.get(
`http://localhost:9200/ncar_index/ncar/_search?q=${this.state.search_query}&size=100&sort=date:desc&analyzer=whitespace`
)
.then((resp) => {
if (event?.target?.value == "") {
// if the searchbar empty set default cards
this.setState({
NCARMap: this.state.NCARMapAS,
noPlaceFound: false,
});
} else {
if (resp.data.hits.hits.length > 0 && this.state.search_query != "") {
// go for new search when there is a result and searchbar not empty
this.setState({
NCARMap: resp.data.hits.hits,
noPlaceFound: false,
});
console.log("Successful");
} else {
// if there is no result make noplacefount true to print a message and show no card
if (resp.data.hits.hits.length == 0) {
this.setState({ noPlaceFound: true });
console.log("Length is equal 0");
}
}
}
});
}
DropDownChangeOne(event) {
console.log("lol");
this.setState({
search_query_drop: "approvetool:أمر",
});
console.log(this.state.search_query_drop);
axios
.get(
`http://localhost:9200/ncar_index/ncar/_search?q=${this.state.search_query_drop}&size=100&sort=date:desc`
)
.then((resp) => {
if (this.state.search_query_drop == "") {
// if the searchbar empty set default cards
this.setState({
NCARMap: this.state.NCARMapAS,
noPlaceFound: false,
});
} else {
if (
resp.data.hits.hits.length > 0 &&
this.state.search_query_drop != ""
) {
// go for new search when there is a result and searchbar not empty
this.setState({
NCARMap: resp.data.hits.hits,
noPlaceFound: false,
});
console.log("Successful");
} else {
// if there is no result make noplacefount true to print a message and show no card
if (resp.data.hits.hits.length == 0) {
this.setState({ noPlaceFound: true });
console.log("Length is equal 0");
}
}
}
});
}
render() {
return (
//HTML FILE Converted to React
<div>
<meta charSet="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta httpEquiv="X-UA-Compatible" content="ie=edge" />
<title>منشآت</title>
<link
rel="shortcut icon"
href="/images/favicon.png"
type="image/x-icon"
/>
{/*============= ScrollToTop Section Starts Here =============*/}
<div className="overlayer" id="overlayer">
<div className="loader">
<div className="loader-inner" />
</div>
</div>
<a href="#0" className="scrollToTop">
<i className="fas fa-angle-up" />
</a>
<div className="overlay" />
{/*============= ScrollToTop Section Ends Here =============*/}
{/*============= Header Section Starts Here =============*/}
<header className="header-section">
<div className="container">
<div className="header-wrapper">
<div className="logo-area">
<div className="logo">
<a href="/">
<img src="/images/logo/logo.png" alt="logo" />
</a>
</div>
<div className="support headFont">
الصفحة الرئيسية
</div>
</div>
<ul className="menu headFont">
<li>
{/*Here we need to change the herf link*/}
الوثائق و المحفوظات
</li>
<li>
الأخبار
</li>
<li>
{/*Here we need to change the herf link*/}
التغريدات
</li>
{/*Here we need to change the herf link*/}
{/* I want to know the difference between the two below */}
<li className="d-md-none text-center">
<a href="#0" className="m-0 header-button">
تسجيل دخول
</a>
</li>
</ul>
<div className="header-bar d-lg-none">
<span style={{ backgroundColor: "#00A7CF" }} />
<span style={{ backgroundColor: "#00A7CF" }} />
<span style={{ backgroundColor: "#00A7CF" }} />
</div>
{/* <div class="header-right"> */}
{/*Here we need to change the herf link*/}
{/* تسجيل دخول
</div> */}
</div>
</div>
</header>
{/*============= Header Section Ends Here =============*/}
{/*============= Banner Section Starts Here =============*/}
<section
className="banner-2 bg_img"
data-background="/images/banner/background3.png"
>
<div className="container">
<div className="banner-content-2">
<h1 className="title cl-white">
مرحباً بك في قسم الوثائق والمحفوظات
</h1>
<p className=" cl-white">
يحتوي هذا القسم على الوثائق والمحفوظات المعتمدة من المركز الوطني
للوثائق والمحفوظات
</p>
<form className="search-form round">
<input
type="text"
style={{ textAlign: "right", color: "black" }}
onChange={this.handleChange}
placeholder="... ابحث هنا"
/>
<button type="submit">
<i className="flaticon-search" />{" "}
<span className="d-none d-sm-inline-block">ابحث</span>
</button>
</form>
</div>
</div>
</section>
{/*============= Banner Section Ends Here =============*/}
{/*============= How Search Section Starts Here =============*/}
<div className="how-search-section padding-bottom mt--93">
<div className="container">
<div className="row mb-30-none justify-content-center">
<div className="filter-rtl">
{/*begin::Body*/}
<div className="card-body filters">
{/*begin::Form*/}
<form>
{/*begin::Categories*/}
<div className="form-group mb-11">
<label className="font-size-h3 font-weight-bolder text-dark mb-7">
التنصيفات
</label>
{/* start dropdown menue */}
<div className="dropdown">
<button
className="btn btn-secondary dropdown-toggle"
type="button"
id="dropdownMenuButton"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
أداة الاعتماد
</button>
<div
className="dropdown-menu"
aria-labelledby="dropdownMenuButton"
>
<a
className="dropdown-item"
onClick={this.DropDownChangeOne}
>
أمر ملكي
</a>
<a className="dropdown-item" href="#">
مرسوم ملكي
</a>
<a className="dropdown-item" href="#">
قرار مجلس الوزراء
</a>
<a className="dropdown-item" href="#">
أمر سامي
</a>
<a className="dropdown-item" href="#">
قرار وزاري
</a>
<a className="dropdown-item" href="#">
قرار مجالس وهيئات
</a>
<a className="dropdown-item" href="#">
قرار إداري
</a>
<a className="dropdown-item" href="#">
توجيه سامي
</a>
</div>
</div>
<div className="dropdown">
<button
className="btn btn-secondary dropdown-toggle"
type="button"
id="dropdownMenuButton"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
فئة الوثيقة
</button>
<div
className="dropdown-menu"
aria-labelledby="dropdownMenuButton"
>
<a className="dropdown-item" href="#">
الاتفاقيات و المعادات الدولية العامة
</a>
<a className="dropdown-item" href="#">
الاتفاقيات الدولية الثنائية
</a>
<a className="dropdown-item" href="#">
الاتفاقيات الدولية متعددة الأطراف
</a>
</div>
</div>
</div>
{/* end dropdown menue */}
{/* Start: : DateRangePickerComponent */}
<DateRangePickerComponent></DateRangePickerComponent>
{/* End: : DateRangePickerComponent */}
{/*end::Categories*/}
<button
type="submit"
className="btn btn-primary font-weight-bolder mr-2 px-8"
>
إعادة ضبط
</button>
<button
type="reset"
className="btn-submit btn btn-clear font-weight-bolder text-muted px-8"
>
بحث
</button>
</form>
{/*end::Form*/}
</div>
{/*end::Body*/}
</div>
<div className="general-card">
{this.state.noPlaceFound ? (
<h3 className="noPlaceFound">
<i className="fas fa-exclamation-circle fa-sm WarnIcon"></i>
لا يوجد نتائج
</h3>
) : (
this.state.NCARMap.map((v) => CreateCards(v._source))
)}
{console.log(this.state.NCARMap)}
</div>
</div>
</div>
</div>
{/*============= How Search Section Ends Here =============*/}
{/*============= Footer Section Starts Here =============*/}
<footer className="footer-section pt-70-145">
<div className="dot-slider bg_img" />
<div className="container">
<div className="row mb--50 justify-content-between">
<div className="col-sm-8 col-lg-4">
<div className="footer-widget widget-about"></div>
</div>
</div>
</div>
<div className="footer-bottom cl-white">
<p>جميع الحقوق محفوظة © 2021</p>
</div>
</footer>
{/*============= Footer Section Ends Here =============*/}
</div>
);
}
}
Case 1: Using map in this case:
{
["أمر ملكي", ...].map((text, i) => {
return (
<a key="i" href="" className="dropdown-item" onClick={() => this.DropDownChangeOne("approvetool:أمر")}> // Your query for each element
{text}
</a>
);
});
}
Case 2: Pass query to DropDownChangeOne
DropDownChangeOne(query) {
this.setState({
search_query_drop: query,
});
axios
.get(
`http://localhost:9200/ncar_index/ncar/_search?q=${query}&size=100&sort=date:desc`
)
.then((resp) => {
...
});
}
Firstly change the onclick function
<a className="dropdown-item" onClick={(e) => this.DropDownChangeOne(e, 'approvetool:أمر')} >
Then in function:
DropDownChangeOne(event, value) {
console.log("lol");
this.setState({
search_query_drop: value,
});
console.log(value);
axios
.get(
`http://localhost:9200/ncar_index/ncar/_search?q=${value}&size=100&sort=date:desc`
)
.then((resp) => {
....
....
....
})
}

Removing li items with Button onClick

I'm trying to add an active "x" button to each li so that a user can click on it to remove the li from the list. I've added the button so that it appears with each list item, but I don't know what I would need to enter onClick to remove the corresponding li after clicking. Any suggestions?
<div>
<h5 className="col-lg-4 mt-4">Selected Files</h5>
<ul className="nobull text-sm">
{files.map((file) => (
<li key={file.path}>
<Button className="ml-3" close />
{file.path} - {(file.size / 1024).toFixed(1)} KB
</li>
))}
</ul>
</div>
In case it helps anyone, after further research, I was able to get my answer. I created the following const:
const remove = file => {
const newFiles = [...files]; // make a var for the new array
newFiles.splice(file, 1); // remove the file from the array
setFiles(newFiles); // update the state
};
Then I updated my code as such:
<div>
<h5 className="col-lg-4 mt-4">Selected Files</h5>
<ul className="nobull text-sm">
{files.map((file, i) => (
<li key={file.path} className="py-2">
<Button className="ml-3" onClick={() => remove(i)} close />
{file.path} - {(file.size / 1024).toFixed(1)} KB
</li>
))}
</ul>
</div>;
You can try something like this:
const handleDelete = (index) => {
let filesArr = [...files];
filesArr.splice(index, 1); // This will delete the element
// Update the state with this modified array
setFiles(filesArr); // like this
}
<div>
<h5 className="col-lg-4 mt-4">Selected Files</h5>
<ul className="nobull text-sm">
{files.map((file, fileIndex) => ( // fileIndex is added here to hold array element index
<li key={file.path}>
<Button className="ml-3" close />
{file.path} - {(file.size / 1024).toFixed(1)} KB
<button type="button" onClick={() => handleDelete(fileIndex)}
</li>
))}
</ul>
</div>;
You can create the key array that you want to remove.
function Files(){
const [dis, setDis] = useState([]);
const removeHandler = (key) => {
setDis(dis.push(key))
}
return(
<div>
<h5 className="col-lg-4 mt-4">Selected Files</h5>
<ul className="nobull text-sm">
{files.map((file, key) => (
!fruits.includes(key) && (
<li key={file.path}>
<Button className="ml-3" close onClick={()={removeHandler(key)}}/>
{file.path} - {(file.size / 1024).toFixed(1)} KB
</li>
)
))}
</ul>
</div>;
)
}
you could use a function like this const removeFile = id =>{ const updatedFiles = files.filter(file => file.id !== FileId)
setFiles(updatedFiles)
}
<Button className="ml-3" onClick={() => removeFile(id)} close />

Hide other previous div/dropdown React

I am wanting to hide other sibling divs (dropdowns in my case) when I click the statusPillDropdown
so far I click I am setting the status to true and opening the div,
{DropDown ${toggleStatusDropdown ? "open": ""}}
Do I just need to set the state to false for previously opened ones? Not sure how to do this.
thank you
import React, { useState } from "react";
import "./StatusPillDropdown.scss";
function StatusPillDropdown({
cellData,
rowItemId,
onStatusPillDropdownChange
}) {
const [toggleStatusDropdown, setToggleStatusDropdown] = useState();
const toggleDropdown = (action, rowItemId, e) => {
if (action === "pillClick") {
setToggleStatusDropdown(true);
} else {
onStatusPillDropdownChange(rowItemId, e.target.getAttribute("value"));
setToggleStatusDropdown(false);
}
};
const renderstatusPillDropdown = (cellData, rowItemId) => (
<React.Fragment>
<span
className="statusPillDropdown"
onClick={() => toggleDropdown("pillClick", rowItemId)}
>
<span className={`status-pill ${cellData.type}`}>{cellData.text}</span>
</span>
<div className="status">
<div className="dropdown-container">
<div className={`DropDown ${toggleStatusDropdown ? "open" : ""}`}>
<ul>
<li
value="Information only"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span></span>Information only
</li>
<li
value="Unresolved"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span className="unresolved"></span>Unresolved
</li>
<li
value="Partially Resolved"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span className="partyResolved"></span>Partially Resolved
</li>
<li
value="Fully Resolved"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span className="resolved"></span>Fully Resolved
</li>
</ul>
</div>
</div>
</div>
</React.Fragment>
);
return (
<React.Fragment>
{renderstatusPillDropdown(cellData, rowItemId)}
</React.Fragment>
);
}
export default StatusPillDropdown;

use React Hooks to change the elements class Name and siblings

I have this function component in react hooks.
and need when I click in any element in the list to change className to 'active'
and remove the className from the other elements
const SideBar = () =>{
const [activeClass, setClass] = useState('');
return (
<div className="sidebar">
<ul>
<li> <Link onClick={() => setClass('active')} className={activeClass} to="/"> Home </Link> </li>
<li> <Link to="/about"> About </Link> </li>
<li> <Link to="/form"> Form </Link> </li>
</ul>
</div>
)
}
I hope you must be using react-router-dom so you can use rect-router-dom api to determine the active item
import {
useLocation
} from "react-router-dom";
const SideBar = () =>{
const [activeClass, setClass] = useState('');
let { pathname } = useLocation();
return (
<div className="sidebar">
<ul>
<li> <Link className={pathname === '/' ? 'active' : ''} to="/"> Home </Link> </li>
<li> <Link to="/about" className={pathname === '/about' ? 'active' : ''}> About </Link> </li>
<li> <Link to="/form" className={pathname === '/form' ? 'active' : ''}> Form </Link> </li>
</ul>
</div>
)
}
import { NavLink } from 'react-router-dom';
const SideBar = () => {
const isActive = path => (match, location) => {
if (!match) {
return false;
}
return match.url === path;
};
return (
<div className="sidebar">
<ul>
<li> <NavLink isActive={isActive('/')} activeClassName="active" to="/"> Home </NavLink> </li>
<li> <NavLink to="/about" isActive={isActive('/about')} activeClassName="active"> About </NavLink> </li>
<li> <NavLink to="/form" isActive={isActive('/form')} activeClassName="active" > Form </NavLink> </li>
</ul>
</div>
)
}
So instead of maintaining only active/not active, you need to maintain which index in your links is active.
You can do this by this way:
const SideBar = () =>{
//setting the initial index as 0 to activate `/` route by default.
const [activeLinkIndex, setActiveLinkIndex] = useState(0);
return (
<div className="sidebar">
<ul>
<li> <Link onClick={() => setActiveLinkIndex(0)} className={activeLinkIndex === 0 ? 'active' : ''} to="/"> Home </Link> </li>
<li> <Link onClick={() => setActiveLinkIndex(1)} className={activeLinkIndex === 1 ? 'active' : ''} to="/about"> About </Link> </li>
<li> <Link onClick={() => setActiveLinkIndex(2)} className={activeLinkIndex === 2 ? 'active' : ''} to="/form"> Form </Link> </li>
</ul>
</div>
)
}

Categories

Resources