I create custom dropdowns and handle through states in react.js
I used the below link code when I apply for two dropdowns then it's not working
When I apply on two dropdowns the 2nd dropdown value is changed and 1st dropdown value is not changeable
This is working on single dropdown but in multiple dropdown not working
How to close multiple dropdowns when clicking outside in reactjs
https://stackoverflow.com/questions/32553158/detect-click-outside-react-component
Without seeing your code, it is difficult to determine how to answer your question.
Your dropdowns are presumably controlled by state within the component.
Something like this?
const Dropdown = () => {
const [open, setOpen] = useState(false);
...
}
Then you have a parent component rendering the dropdowns.
const Parent = () => {
return (
<>
<Dropdown />
<Dropdown />
</>
)
}
Since the state is held within the components, we can't modify both at once. The solution is to lift state.
const Dropdown = ({ open }) => {
...
}
const Parent = () => {
const [openDropdowns, setOpenDropdowns] = useState({});
}
Related
I'm trying to create a filter button by ReactJs, spent a lot of times but still do not know why it's doesn't work
Here are my codePen: https://codepen.io/tinproht123/pen/gOxeWpy?editors=0110
const [menuItems, setMenuItems] = React.useState(menu);
const [categories, setCategories] = React.useState(allCategories);
const filterItems = (category) =>{
if(category === 'all'){
setMenuItems(menu);
return;
}
const newItems = menu.filter((item)=> item.category === category)
setMenuItems(newItems);
}
return(
<section className='container'>
<div className='title'>
<h1>Our menu</h1>
</div>
<Categories categories={categories} filterItems={filterItems}/>
<Menu menu={menuItems}/>
</section>
)
}~~~
I checked your code and the problem isn't in the part that you showed to us.
Instead please check your codes 103th line, on codepen. Your code seems like that:
const Menu = () =>{
return(
<div className='menu-container'>
{menu.map((menuItem) => {
....
Be careful to the first line, since your all menu items stays in menu variable, even though you made correct filtering, you're printing the result for all menus.
I saw that you're sending a prop to a <Menu menu={menuItems}>....
but you're not using it. To use this prop you should add a parameter to your Menu function;
const Menu = ({menu}) =>{
return(
<div className='menu-container'>
{menu.map((menuItem) => {
Just like above.
In the Menu component, you're not passing any props but just rendering the const value declared on top of the file.
You're filtering exactly by categories but rendering is not showing the updated one. :)
I'm currently using Material-table . It displays data normally however, Pagination and Row per Page dropdown is not working. Nothing happens upon clicking, next button and selected number of rows.
See below codes:
import MaterialTable from 'material-table'
const tableIcons = {
/*table icons*/
}
function Test(){
const [data, setData] = useState([]);
const getDatas = async() => {
await axios.get('/API')
.then(response => {
setData(response.data)
}
}
const columns = [
{.....} //columns
]
return(
<div>
<MaterialTable
icons = {tableIcons}
columns = {columns}
data = {data}
title = 'List of data'
actions = {[{
//add button properties
}]}
>
</MaterialTable>
</div>
)
}
export default Test;
I'm getting the following error on console upon onload and clicking pagination buttons.
On load:
On click of next button
Please help me with this. Thank you in advance.
First of all, keep in mind that the original project was discontinued, and the new direction can be found in this repository (it's a fork of the original). There will be a lot of refactorings and breaking changes, so you might want to check them out first.
Now, on your question,
since you are working with remote data you could check out the official example on how to handle this kind of data.
If your requirements don't allow you to do this, you will need to do all the handling by yourself. That means you should provide your own implementation of the Pagination component, in which you define your own behavior of onChangePage and other callbacks.
The customisation will look something like:
Pagination: (properties: any) => {
return (
<TablePagination
{...properties}
count={currentPage.total}
onChangePage={(event: any, page: number) => {
onChangePage(page);
}}
page={currentPage.startIndex / pageSize}
/>
);
}
where total, startIndex etc. will be provided by the API you consume, along with the actual data that you show in the table.
These components overrides should be provided under the components property of the material table.
Hello I have table component taken from ant design's table and I want to change what happens when you change your current page.
function DefaultTable<T extends Entity>(props: TableProps<T>): JSX.Element {
const { pagination } = props;
const [currentPage, setCurrentPage] = useState(1);
const [currentPageSize, setCurrentPageSize] = useState<number>();
return (
<Form>
<Table
{...props}
pagination={
pagination !== false && {
onChange: e => setCurrentPage(e),
defaultCurrent: currentPage,
onShowSizeChange: (_current, newSize) => setCurrentPageSize(newSize),
pageSize: currentPageSize,
...pagination
}
}
/>
</Form>
);
}
However, when I change the page, the filters, sorters and some other configurations are also gone. I think it is because of this onChange function onChange: e => setCurrentPage(e), the default behaviour is ignored. Is there a way to extend the default onChange, and then add my current setCurrentPage(e) to it?
I've been looking on Table and Pagination implementation on antd and there is no evidence which explains why adding onChange would prevent the default behavior.
https://codesandbox.io/s/customized-filter-panel-antd4123-forked-1nwro?file=/index.js
I also have been playing around the Table example provided by antd docs, where I add a onChange handle and the filtering behavior remains the same.
Try to isolate the code and provide more info - this way we could help you better.
I have a column list of elements, and each of them has hidden div, I want to show hidden element on click, but when I'm clicking another div, I want to hide current and show the one I clicked last, how can I do it correctly?
You could have two specific classes, one that hides element and one that shows element. when clicking on the element you can use jQuery or JavaScript to toggle the class that shows element for the hidden div of that specific element and hide everything for any other div.
The component you're rendering could take in an active prop and only render the second div if this prop is true.
With this, you could then keep track of which element is selected in the parent.
I threw together a working example with very simple content
import React, { useState } from 'react';
const ListItem = ({id, isActive, handleClick}) => {
return (
<div id={id} onClick={handleClick}>
Here is the element
{!!isActive && <div>I am the selected element</div>}
</div>
);
};
export const List = () => {
const [selectedItem, setSelectedItem] = useState();
const items = ['one', 'two', 'three'];
const handleClick = (event) => {
setSelectedItem(event.target.id);
}
return (
<div>
{items.map(item => (
<ListItem id={item} isActive={item===selectedItem} handleClick={handleClick}/>
))}
</div>
)
}
I have started an application which I want to work same as weather.com next 36 hours section. The idea is when you click on each weatherCard which has a seperate component in my app you will update the below section which is my weatherDetails component based on the selected weatherCard /weather box. So I made the entire component clickable by giving it the click event via props from my stateful component which is my weatherLocation component. This is my WeatherCard component:
const WeatherCard = (props) => (
<div id={props.date} className="weatherCard" onClick={props.clicked}>
<h2 className="cardDate">{props.date}</h2>
<h4>{props.forcast}</h4>
<div className="minmaxDeg">
<data>{props.min}</data>
<data>{props.max}</data>
</div>
<data>{props.rain}</data>
</div>
);
And here in render method in WeatherLocation component I loop through data coming from state and give props the WeatherCard component:
const WeatherCards = this.state.reports.map( report => {
return(
<WeatherCard
key={report.id}
{...report}
clicked={() => this.handleCardClick(event)}
/>
);
});
And this is the handleCardClick that I added for it just for testing:
handleCardClick = event => {
// const { reports , selectedCardInfo , activeCard } = this.state;
const selectedDate = document.getElementById(event.target.id);
console.log(event.target.id);
}
I don't want to use anchor tag as I don't need href. The click works fine by itself. But because I need to get the id of the parent which is the div with the class of weatherCard. At the moment when I click on other elements inside the card I cannot get the id because they are not the parent. The reason I need its id is when I get data with from the API I need a unique value for each card so that when you click on the card the data for that card will be shown in the other component which is the WeatherDetails component. But for now I need to be able to somehow choose that selected card and pull out the state for that unique card. Could someone help me out? Thanks.
You just need to pass the Parent component ID to your onClick function in Weather Card.
Here is your WeatherCard - Component
const WeatherCard = (props) => (
<div id={props.date} className="weatherCard" onClick={event => props.clicked(event, props.id)}>
<h2 className="cardDate">{props.date}</h2>
<h4>{props.forcast}</h4>
<div className="minmaxDeg">
<data>{props.min}</data>
<data>{props.max}</data>
</div>
<data>{props.rain}</data>
</div>
);
You can see that I have added props.id to your onClick function and with help of event now you can access that id from the parent component.
Now here is your Parent Component- WeatherCards
const WeatherCards = this.state.reports.map( (report, i) => {
return(
<WeatherCard
key={report.id}
id={i}
{...report}
clicked={this.handleCardClick}
/>
);
});
You can see in the code I am passing index number as id to your child component.
So this will give you an id (for now it's an index number) of the card in your onClick handler.
and Finally, here is your on click handler.
handleCardClick = (event, weatherCardID) => {
console.log(weatherCardID)
}
As of now, I am using the index as id if you want to use a unique identifier, you can change that easily.
General JavaScript solution is to differentiate the elements and .stopPropogation after you've captured the event you are targeting. A nested unordered list, <ul>would be an example. Tag the containing <li> with an .opened class upon rendering/displaying each level of nesting, tag those <li> elements accordingly, e.g. a dataset attribute such as data-make, then data-model, then data-option. You then attach and fire event listeners on the different level <li>'s.
Thank you #RutulPatel. I made your answer as the answer. But I changed your code a bit as I got your point so I wrote an answer as it is long. I think we might not need to change the WeatherCard at all and I don't pass event or any logic there. so it will be intact:
const WeatherCard = (props) => (
<div id={props.date} className="weatherCard" onClick={event => props.clicked(event, props.id)}>
<h2 className="cardDate">{props.date}</h2>
<h4>{props.forcast}</h4>
<div className="minmaxDeg">
<data>{props.min}</data>
<data>{props.max}</data>
</div>
<data>{props.rain}</data>
</div>
);
But I use your tip changing my weatherCards array to look like this:
const weatherCards = this.state.reports.map( report => {
return(
<WeatherCard
key={report.id}
id={report.date}
{...report}
clicked={() => this.handleCardClick(event, report.date)}
/>
);
});
So I use the report.date which is a unique value as my id. Also I don't pass event as a parameter to the arrow function I just pass it with the report.date to the handler:
clicked={() => this.handleCardClick(event, report.date)}
And the handler will be the same as you did:
handleCardClick = (event, weatherCardID) => {
console.log(weatherCardID)
}
I might even remove event later on from both if there was no need fo that.
Thank you again.