how to make reactstrap dropdown not close when clicked on? - javascript

So basically, I have a functional component that shows a reactstrap dropdown.
Here's how it looks. according to the picture i want to be able to click on the box and the dots show in green (the dropdown box is shown in red) without closing the dropdown (by default, it closes when clicked on).
Right now, I'm using stopImmediatePropagation which is incorrect and throws an error:
Uncaught TypeError: e.stopImmediatePropagation is not a function
But meanwhile preserves the functionality i want (it prevents closing the dropdown which i assume has something to do with not letting event propagate to the parent)
And here's the code, Any insight or solution?
import React from "react"
import { ImAttachment } from "react-icons/im"
import { FiMoreVertical } from "react-icons/fi"
import { DropdownItem, DropdownMenu, DropdownToggle, UncontrolledDropdown } from "reactstrap"
import Avatar from "src/#core/components/avatar"
import { VscTriangleRight } from "react-icons/vsc"
import BpmsIconButton from "src/components/#bpms/Buttons/BpmsIconButton"
const Items = (props) => {
const {
title = "title",
subtitle = "subtitle",
itemAvatar,
color = "",
actions = null,
index = -1
} = props
const stopBubbling = (e) => {
e.stopImmediatePropagation()
}
return (
<DropdownItem tag="div" className="dropdown-item-custom" onClick={stopBubbling}>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex no-pointer">
<div className="d-flex cursor-pointer">
{!/\//.test(itemAvatar) ? ( // string containing / indicates of url
<Avatar
className="rounded"
color={`light-${color}`}
size="lg"
icon={<span>{itemAvatar}</span>}
/>
) : (
<Avatar
className="rounded rounded-circle"
color={color}
size="lg"
icon={<img src={itemAvatar} alt="item" />}
/>
)}
</div>
<div className="text-custom">
<div className="flex-column">{title}</div>
<div className="flex-column text-muted">{subtitle}</div>
</div>
</a>
<UncontrolledDropdown>
<DropdownToggle tag="a">
<span className="dropdown-file-type">
<span className="dropdown-file-type-text">
<BpmsIconButton icon={<FiMoreVertical size={20} />} />
</span>
</span>
</DropdownToggle>
<DropdownMenu className="dropdown-menu-inside-custom">
<DropdownItem tag="div" onClick={() => actions().edit(index)}>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex">
<div className="action-text-custom">ویرایش</div>
</a>
</div>
</div>
</DropdownItem>
<DropdownItem tag="div" onClick={() => actions().remove(index)}>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex">
<div className="action-text-custom">حذف</div>
</a>
</div>
</div>
</DropdownItem>
<DropdownItem tag="div" onClick={() => actions().view(index)}>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex">
<div className="action-text-custom">مشاهده</div>
</a>
</div>
</div>
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</div>
</div>
</DropdownItem>
)
}
const GeneralTab = (props) => {
const { general, items, settings } = props || {}
const {
Icon: HeaderIcon = ImAttachment,
ActionsIcon: MoreIcon = FiMoreVertical,
text = "اسناد و مدارک",
index,
generalActions = null,
itemActions = null
} = general || {}
const { color = "" } = settings || {}
const stopBubbling = (e) => {
e.stopImmediatePropagation()
}
return (
<UncontrolledDropdown>
<DropdownToggle tag="div" className="p-0 general-tab-hover">
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex me-5">
<HeaderIcon size={20} className="title-icons" />
<span>
{`${text}`}
{index && `(${index})`}
</span>
</a>
</div>
</div>
</DropdownToggle>
<DropdownMenu className={`mt-0 dropdown-menu-custom border-top border-${color}`}>
<DropdownItem
key="fixed"
tag="div"
className={`dropdown-item-custom text-${color}`}
onClick={stopBubbling}
>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex no-pointer">
<span className="dropdown-file-type">
<span className="dropdown-file-type-no-height">
<HeaderIcon size={20} className="" />
</span>
</span>
<span className="text-custom">{text}</span>
</a>
<div className="d-flex cursor-pointer">
<UncontrolledDropdown>
<DropdownToggle tag="a">
<span className="dropdown-file-type">
<span className="dropdown-file-type-no-height">
<MoreIcon size={20} />
</span>
</span>
</DropdownToggle>
<DropdownMenu className="dropdown-menu-inside-custom">
<DropdownItem tag="div" onClick={generalActions().newItem}>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex">
<div className="action-text-custom">جدید</div>
</a>
</div>
</div>
</DropdownItem>
<DropdownItem tag="div" onClick={generalActions().downloadAll}>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex">
<div className="action-text-custom">دانلود همه</div>
</a>
</div>
</div>
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</div>
</div>
</div>
</DropdownItem>
<div className="dropdown-scrollbar">
{Array.isArray(items) &&
items.map((item, idx) => (
<Items key={idx} {...item} actions={itemActions} />
))}
</div>
</DropdownMenu>
</UncontrolledDropdown>
)
}
export default GeneralTab

Related

Make Submenu on sidebar component Nextjs

So it to loop and subMenu on sidebar component, but instead of the subMenu showUp under the parents menu, it showUp on the Right side of the parents menu as pic below:
here is my code on how i try to loop the subMenu and The parents item to the react component:
return (
<div className=" my-4 border-gray-100 pb-4">
{items.map(({ icon: Icon, iconArrow: IconArrow, ...item }, index) => {
if (item.subMenu) {
return (
<div>
<Link href={item.link}>
<a
onClick={(e) => onMouseClick(e, item.link)}
className="flex mb-2 justify-start items-center gap-4 pl-5 hover:bg-gray-900 p-2 rounded-md group cursor-pointer hover:shadow-lg m-auto"
>
<Icon className="text-2xl text-white group-hover:text-red" />
<h3 className="text-base text-white group-hover:text-red font-semibold ">
{item.label}
</h3>
{item.subMenu && dropdown ? (
<>
<IconArrow className="pl-0 text-2xl text-white group-hover:text-red" />
</>
) : (
<></>
)}{" "}
{item.subMenu && dropdown ? (
<div>
{item.subMenu.map((subitem, index) => {
return <>makan</>;
})}
</div>
) : (
<></>
)}
</a>
</Link>
</div>
);
} else {
return (
// eslint-disable-next-line react/jsx-key
<div>
<Link href={item.link}>
<a
onClick={(e) => onMouseClick(e, item.link)}
className="flex mb-2 justify-start items-center gap-4 pl-5 hover:bg-gray-900 p-2 rounded-md group cursor-pointer hover:shadow-lg m-auto"
>
<Icon className="text-2xl text-white group-hover:text-red" />
<h3 className="text-base text-white group-hover:text-red font-semibold ">
{item.label}
</h3>
</a>
</Link>
</div>
);
}
})}
</div>
);
};
Can Some one tell me where did i do wrong here, here is where i call the sidebar component into the sidebar:
return (
<div className="h-full px-4 pt-8 bg-yellow flex flex-col peer-focus:left-0 peer:transition ease-out delay-150 duration-200">
<div className="flex flex-col justify-start item-center mb-4">
<Image src={Logo_Nabati} width={123} height={75} alt="logo Nabati" />
</div>
<Sidebarcomponent items={menuItems} />;
</div>
);
try this:
return (
<div className=" my-4 border-gray-100 pb-4 relative">
{items.map(({ icon: Icon, iconArrow: IconArrow, ...item }, index) => {
if (item.subMenu) {
return (
<div className="absolute top-full left-0">...</div>
);
} else {...})}
</div>
);
};
I assume you want to display the submenu under the "Master Data"? Put the component under it. Then in the anchor tag you have a flex. Add flex-col to change the direction of flex, top-bottom.

Passing props to reactjs-popup component

I'm working on a Docusaurus project which is based on React, I wanted to add a popup modal with a title and an image inside.
For the Modal I use reactjs-popup, eveything works fine only the title and image do not appear.
This is where I import the Modal:
import Modal from '../../components/Modal.js';
<Modal image="img/test.png" title="test" />
This is the Modal component:
const Modal = ({ image, title }) => (
<Popup
trigger={
<button type="button" className="button">
Vezi exemplu!
</button>
}
modal
contentStyle={contentStyle}
nested
>
{close => (
<div className="modal">
<button className="close" onClick={close}>
×
</button>
<div className="content">
<h1>{title}</h1>
<img src={image} />
</div>
<div className="actions">
<button
type="button"
className="button"
onClick={() => {
console.log('modal closed ');
close();
}}
>
close
</button>
</div>
</div>
)}
</Popup >
);
Modal.propTypes = {
image: PropTypes.string,
title: PropTypes.string
}
instead of const Modal = ({ image, title }) => ( , type as
const Modal = props => {const {image = "", title = ""} = props;
then make a return function
return( <Popup
trigger={
<button type="button" className="button">
Vezi exemplu!
</button>
}
modal
contentStyle={contentStyle}
nested
>
{close => (
<div className="modal">
<button className="close" onClick={close}>
×
</button>
<div className="content">
<h1>{title}</h1>
<img src={image} />
</div>
<div className="actions">
<button
type="button"
className="button"
onClick={() => {
console.log('modal closed ');
close();
}}
>
close
</button>
</div>
</div>
)}
</Popup >);
}
your all code should look like this.
const Modal = props => {const {image = "", title = ""} = props;
return( <Popup
trigger={
<button type="button" className="button">
Vezi exemplu!
</button>
}
modal
contentStyle={contentStyle}
nested
>
{close => (
<div className="modal">
<button className="close" onClick={close}>
×
</button>
<div className="content">
<h1>{title}</h1>
<img src={image} />
</div>
<div className="actions">
<button
type="button"
className="button"
onClick={() => {
console.log('modal closed ');
close();
}}
>
close
</button>
</div>
</div>
)}
</Popup >);}

Change boolean value onClick in React

I'm trying to change the value of a boolean from an object imported from a JSON file in React. I want the offers.availability value to change to false after clicking on the "add to cart" button.
Here's my code:
function App() {
class App {
constructor () {
this.state = {
offers: [],
}
this.handleToggle = this.handleToggle.bind(this);
}
componentDidMount() {
this.state.setState({ offers: Data });
}
handleToggle (offers) {
this.setState(prevState => ({
offers: prevState.offers.map(prevOffer => {
if (prevOffer.availability === offers.availability) {
return {
availability: prevOffer.availability,
isTrue: !prevOffer.isTrue
}
}
return prevOffer;
})}));
}
}
return (
<div className="container">
<div className="row">
{Data.offers.map(offers => {
return(
<div key={offers.make + offers.model + offers.engine + offers.photo} className="col-sm-4">
<div className="card" >
<img src={offers.photo} className="card-img-top" alt={offers.make + ' ' + offers.model } width="100%"/>
<div className="card-body pt-0 px-0">
<div className="d-flex flex-row justify-content-between mb-0 px-3 p-3 mid">
<div className="d-flex flex-column">
<h4>{offers.make} {offers.model}</h4>
</div>
<div className="d-flex flex-column">
<button type="button" className="btn btndelete"><FaTrash /></button>
</div>
</div>
<div className="d-flex flex-row justify-content-between px-3">
<div className="d-flex flex-column"><span className="text-muted">Engine: {offers.engine}</span></div>
<div className="d-flex flex-column">
{offers.availability.toString()}
</div>
</div>
<div className="mx-3 mt-3 mb-2 d-grid gap-2">
{offers.availability
? <button type="button" className="btn btn-primary addtocartbtn" onClick={() => Data.offers.handleToggle(offers)}>
<small>Add to cart</small>
</button>
: <button type="button" className="btn btn-disabled" onClick={console.log('???')}><small>Currently unavailabe</small></button>
}
</div>
</div>
</div>
</div>
)
}) }
</div>
</div>
)}
export default App;
I tried to toggle the boolean value but I currently get a ".offers.handleToggle is not a function" error after clicking.
I'm new to this so please don't judge if I did something really stupid here :) What could be the possible solution to this?
You should not use Data.offers.handleToggle. From what I see, Data.offers is an array of objects which they don't have a function handleToggle defined.
However, you are defining a function handleToggle on the App component that looks good. It should work if you change onClick={() => Data.offers.handleToggle(offers)} with either onClick={() => handleToggle(offers)} or onClick={() => this.handleToggle(offers)}
UPDATE
After running your code I saw the component is defined as a mix of a functional component and a class component. First, decide what you are going to use and then fix the errors 1 by 1. The constructor for example is missing the props, there are onclicks that are not well defined and a few more things.
Here is your code if used as a class component.
import { Component } from "react";
export class App extends Component<{}, { offers: any[] }> {
constructor(props: {}) {
super(props);
this.state = {
offers: [],
};
this.handleToggle = this.handleToggle.bind(this);
}
componentDidMount() {
this.setState({ offers: Data });
}
handleToggle(offers: any) {
this.setState((prevState) => ({
offers: prevState.offers.map((prevOffer) => {
if (prevOffer.availability === offers.availability) {
return {
availability: prevOffer.availability,
isTrue: !prevOffer.isTrue,
};
}
return prevOffer;
}),
}));
}
render() {
return (
<div className="container">
<div className="row">
{this.state.offers.map((offers) => {
return (
<div
key={offers.make + offers.model + offers.engine + offers.photo}
className="col-sm-4"
>
<div className="card">
<img
src={offers.photo}
className="card-img-top"
alt={offers.make + " " + offers.model}
width="100%"
/>
<div className="card-body pt-0 px-0">
<div className="d-flex flex-row justify-content-between mb-0 px-3 p-3 mid">
<div className="d-flex flex-column">
<h4>
{offers.make} {offers.model}
</h4>
</div>
<div className="d-flex flex-column">
<button type="button" className="btn btndelete">
<FaTrash />
</button>
</div>
</div>
<div className="d-flex flex-row justify-content-between px-3">
<div className="d-flex flex-column">
<span className="text-muted">
Engine: {offers.engine}
</span>
</div>
<div className="d-flex flex-column">
{offers.availability.toString()}
</div>
</div>
<div className="mx-3 mt-3 mb-2 d-grid gap-2">
{offers.availability ? (
<button
type="button"
className="btn btn-primary addtocartbtn"
onClick={() => this.handleToggle(offers)}
>
<small>Add to cart</small>
</button>
) : (
<button
type="button"
className="btn btn-disabled"
onClick={() => console.log("???")}
>
<small>Currently unavailabe</small>
</button>
)}
</div>
</div>
</div>
</div>
);
})}
</div>
</div>
);
}
}
You just need to define the offers type and a FaTrash component

.active class issue when mapping a boostrap carousel item !! (REACT)

i'm trying to map some bootstrap carousel items but I think my issue is with the .active class,
They are mapping one over the other without being able to let me slide them drop the code below, hope someone can help me hehe...
<div id="charactersCards" className="carousel slide border border-warning rounded-lg" data-ride="carousel">
<div className="carousel-inner text-warning">
{!!store.character &&
store.character.results.map((char, i) => (
<div key={i} className="carousel-item text-center active">
<div className="card d-block w-100">
<img src="https://place-hold.it/400x200" className="card-img-top" alt="Image" />
<div className="card-body">
<h5 className="card-title">{char.name}</h5>
<p className="card-text text-white">{bio}</p>
<Link
className="btn text-warning border border-warning"
onClick={() => actions.currentCharId(i + 1)}
to={`/iPeopleCard/${i + 1}`}>
Learn More!
</Link>
<i
className="fas fa-heart mt-3 pt-4 ml-3"
onClick={() => actions.setCharToFav(i)}
style={
actions.characterFindInFav(i) ? { color: "yellow" } : { color: "white" }
}
/>
</div>
</div>
</div>
))}
</div>
You need to set 'active' class conditionally. Because now all of your carousel items have 'active' class. You can do something like this:
// instead of <div key={i} className="carousel-item text-center active">
// write the code below:
<div
key={i}
className={i === 0 ? "carousel-item text-center active" : "carousel-item text-center" }>

How can I call a function inside of a .map of arrays?

I am passing down a function through props that capitalizes a few items being mapped over. I am getting an error on the item portion of item.creator.I am just wondering why I am recieving the error and not able to just call the function inside of the map. Thanks for your help.
Error message is Line Parsing error: Unexpected token, expected ",".
PARENT COMPONENT
export default function MainContent() {
const techContent = useSelector(displayTechContent);
const designContent = useSelector(displayDesignContent);
const makeCapital = (words) => words.replace(/^\w/, (c) => c.toUpperCase());
return (
<div className="container">
<div className="topics-list">
<div className="topic-row mb-5">
<h2 className="topic-heading mb-4">Software Development</h2>
<ContentCard data={techContent} capitalize={makeCapital} />
</div>
CHILD COMPONENT
export default (props) => (
<div>
<div className="resource-list">
{props.data.map((item) => (
<a key={item.id} href={item.link} className="resource-card-link mr-3">
<div className="card resource-card mb-2">
<div className="card-header">
<h4 className="resource-title">{item.title}</h4>
<span className="resource-creator">by: ***{props.capitalize({item.creator})}***.</span> <--this function
</div>
<div className="card-body py-3">
<div className="resource-description mb-2">
{item.description}
</div>
<div className="resource-type mb-2">
<i className="fas fa-book"></i> {item.type}
</div>
The curly braces around of item.creator are redundant.
export default (props) => (
<div>
<div className="resource-list">
{props.data.map((item) => (
<a key={item.id} href={item.link} className="resource-card-link mr-3">
<div className="card resource-card mb-2">
<div className="card-header">
<h4 className="resource-title">{item.title}</h4>
<span className="resource-creator">by: ***{props.capitalize(item.creator)}***.</span> <--this function
</div>
<div className="card-body py-3">
<div className="resource-description mb-2">
{item.description}
</div>
<div className="resource-type mb-2">
<i className="fas fa-book"></i> {item.type}
</div>

Categories

Resources