I am trying to create a custom filter pane in React.JS as practice, but I am lost and do not know where to begin. I looked online and saw that you could create a filter bar online with a search bar, and while that is nice, I wanted to have multiple buttons to filter different things. For example, if I were to filter an option for shirts, I would like to filter the prospects for the price, graphics on the shirt or without, and the brand of the shirt. Any ideas are welcome! I don't have any code to display because I don't know where to start other than a button and handleChange method.
Thats very abstract situation, but here is how I would do it.
Plan what filters you want to have, try to imagine how it should look and work.
Get some data set from backend or from hardcoded data, so you will have what to work with.
Create component that will display that items.
Create UI for filters
Then you add logic for filters. On select some filter, you will filter data that comes into your component that provides data to component that display items. Filter that data and your component will display filtered data.
So all structure might look like this:
const ParentComponent = () => {
const [filters, setFilters] = useState({})
const data = ...
const filteredData = applyFilters(data, filters)
return (
<div>
<DisplayItems data={filteredData} />
<Filters ... />
</div>
)
}
Its just a basic example for little understanding.
Hope it helps
Related
I'm trying to build a Dashboard with React Js and I would like to know how you could display multiple components, but as widgets, which mean you need to be able to add them in any order and in any quantity. My problem is that I can't find a way to render a map of components.
The user may be able to add a widget to his dashboard by clicking a button, or remove them the same way, so I won't know how many of what components will be rendered
I would like to do something like, when the user clicks on a widget, it adds it to the dashboard, but I don't know how to do that.
I've tried to store components in a map, then with a forEach loop display them all by returning a div containing the component:
import Weather from '...'
import Currency from '...'
import News from '...'
const map = [Weather, Currency, News]
const runAll = () => {
map.forEach((fcn) => {
let runner = fcn
runner()
})
}
runAll()
I've searched many stack and other forums questions, without finding what I needed
Do you guys have an idea of what I could do to solve this ?
So you need to be able to easily render 2 things:
a list of widgets that the user can click and add in the dashboard
the actual dashboard. All selected widgets in a list (with a remove capability)
Let's first figure out what our state should be that also feeds the components 1 and 2.
For the 1st one we need the full list of available widgets. Since this is static (we have 3 widgets available) this can be expresses through a static mapping (a simple javascript object) declared once.
For the 2nd one we need an array of the user selected widgets. That's the dynamic part. We need to be able to set the initial widgets shown and have the capability to add and remove widgets from this list, allowing the same widget appearing more that once.
Static widget mapping
This should be a mapping between an identifier and the react widget component and should look like this:
import News from "./News";
import Weather from "./Weather";
import Currency from "./Currency";
const widgetsMapping = {
news: News,
weather: Weather,
currency: Currency
};
Widgets state
This is an array of widget identifiers (the keys from the static mapping) that the user wants in the dashboard. Also we need add and remove methods. Using useState we can write this like below:
const [widgets, setWidgets] = useState(["weather", "news"]);
const addWidget = (widget) => {
setWidgets([...widgets, widget]);
};
const removeWidget = (index) => {
const updated = [...widgets];
updated.splice(index, 1);
setWidgets(updated);
};
Rendering
Dashboard
Then we can render the dashboard by iterating our widget state array:
{widgets.map((widget, index) => {
const Widget = widgetsMapping[widget];
return (
<Widget
key={`${widget}${index}`}
removeWidget={() => removeWidget(index)}
/>
)
})}
removeWidget prop can be used to let a widget remove itself when sth is clicked.
List of available widgets
Here we will iterate through all available widgets from our static mapping and render all of them with the add functionality bound to them.
{Object.keys(widgetsMapping).map((widget) => (
<button key={widget} onClick={() => addWidget(widget)}>
{widget}+
</button>
))}
You can find a full working example in this code sandbox. Some assumptions were made about how you want to add and remove widgets but the main idea remains the same.
Keep a state (array) that holds widgets added by user. Define constants for widgets and save these constants to your persistance storage.
const widgets = {weather : 1, news: 2}
save these values to database as json with properties configured by user if needed, and then retrieve this json and render components based on it
sample JSON structure to save - [{type: 1, prop1: "val"},{type: 2, prop1: "val"}]
const renderWidgets = (array) => {
const widgets = [];
array.foreach((widget) => {
switch(widget) {
case widgets.weather:
widgets.push(<Weather ...props/>);
break;
.
.
.
etc
}
});
return widgets;
}
I am making a table on my react website with react-bootstrap-table-next (also known as react-bootstrap-table-2) and am trying to get an icon component to show up in the rows as data instead of what I have now, which is an x, like this:
A sample of what I currently have for data is:
const tools = [{key: 'Android Mobile', qual: "x"}]
But what I want to do is something like:
const tools = [{key: 'Android Mobile', qual: <CheckIcon/>}]
Where CheckIcon is const CheckIcon = () => <Icon icon={check} size={10}/> (where Icon is being imported from react-icons-kit).
Currently the entire page does not render when I do something like that, and I haven't been able to find much information on how to insert a component into an object with React. If there are any tips or tricks anyone has, that would be much appreciated!
Here is a stackblitz for anyone that wants to play around with the code
I think column.formatter can help you. there's a online demo: this
First, make sure that react-bootstrap-table-next props data accept React Component.
So far what I've found it does not support render a React Component inside the data object.
https://github.com/react-bootstrap-table/react-bootstrap-table2/blob/master/packages/react-bootstrap-table2/src/bootstrap-table.js#L118
Feel free if you want to submit a new feature at https://github.com/react-bootstrap-table/react-bootstrap-table2/issues/new
I ended up coming to the same conclusion as #Roman Masyhar and ended up taking the cheater's route for now until I end up just making my own table and just using the "✔" character in place of x's and just styling them for the same effect
In case anyone is curious I did also open a feature request here
i have kinda big issue in my project, working with angular 2 (changeDetection onPush) & ngrx, my project has 3 dumb components and one smart component that managing them, its looks something like this:
Sorry for the UX, im not a designer
So i have 1 reducer for the Tags and the other one for the items, the lists has the same type of item its just depends if the item is finished or not to be included of each list.
Until now sounds good, but my problem is that the Tags can filter cross over the application and the lists filter of the search box effects just on the self list and the map, on the ngOnChanges of the lists im execute the search filter and emit to the smart component the filtered items, and the smart component dispatch to store to change the "isFiltered" property.
Where's my problem is ?
I cant manage both of the filters, 'cause i added "isFiltered" property on the type of item, but its effects different for the filters, i mean i have a combineLatest that managing the filter of items looks something like that:
Rx.Observable.combineLatest(
items,
tags,
(items, tags) => {
return items.map((item) => {
item.isFiltered = item.isFiltered && tags.includes(item.tagId);
return item;
})
})
its not working well, and its kinda problem cause its a routine that the refernce to the observable changed the ngOnChange jumps and calling the dispatch again, tryed alot of things, at first i added the UPDATE_TAGS action in the items reducer and handle it there, but i read that its not the best practice to listen to the same action in 2 reducers.
After that i tryed to handle it in the same reducer but i cant know which items filtered from the tags and which from the search box.
The only way i thought about and it will work is another property on the item of isFilteredTags, and isFilteredLists.
Let me know if u have an answer for me, its will help me.
Thank you.
My idea is to mantain the list of filtered users (suggestions) as state on the component, when the input changes, the state is updated.
How can I display the filtered list below the text box?
One option is 'datalist' tag (HTML5), but the list is already filtered, and part of the functionality of this tag is filtering.
I can't use any library or framework.
English is not my native language, sorry if you find some mistake.
Thanks.
Try a component from a design library, like the Material-UI autocomplete component http://www.material-ui.com/#/components/auto-complete
The dataSource attribute represents the array of autocomplete options.
How I did it was to pass in the dataList array as a prop and filterByField prop so that you can change what to filter, then add an event listener to the input (onChange) that passes the value to a function that filters the dataList.
onChangeInput(e) {
const { dataList, filterByField } = this.props;
const filteredDataList = dataList.filter(items => items[filterByField].toLowerCase().startsWith(e.target.value.toLowerCase()) );
// update internal component state to trigger render of dropdown list
this.setState({filteredList: filteredDataList});
}
I also added a check for no matches found so I can show a message:
if (filteredDataList.length === 0) {
this.setState({noMatchFound: true});
}
Then in my render() I simply check if filteredList isn't null and show an unordered list that I use css to display below the input.
{this.state.filteredList !== null
<ul className="autocomplete-list">
{this.filteredListMarkup()}
</ul>
}
filteredListMarkup() then uses map to return an <li> for each item with the necessary event handlers to update the selected item into the input and close the autocomplete-list by this.setState({filteredList: null});
You might also find this one useful:
https://github.com/reactjs/react-autocomplete
Even if you could use dependencies, I tried a bunch of the top current ones and personally wasn't happy with any of them (added dependencies like jQuery, not lightweight to use/understand/customize, css challenges, etc).
In then end, I found this lightweight vanilla React typeahead tutorial (no, I didn't write the tutorial). It's quick, simple, and three's no added dependency tree weight (eg: jQuery) or dependency maintenance. This solution also easily adjusted to the newer React patterns & the libraries I was using, and I'm guessing the same would be true of the patterns/libraries you may be using. Maybe this will help you or someone else like it did me.
Using React-Select in v1.0.0-beta10, I'd like to keep selected items in menu in order to be able to implement a dropdown behaving similar as the multi-select at MaterializeCss
here's a screenshot:
how to achieve this behavior?
Just to have this complete as you asked in react-select on GitHub this was made possible using removeSelected={false} in this pull request. Now (mid 2019) the solution is:
hideSelectedOptions={false}
You have access to a prop called filterOptions that accepts a function that takes the properties options, searchFilter and selectedOptions.
You should just be able to always return options that match the search filter instead of stripping out the selectedOptions something like below (if you are using underscrore/lodash. Or write your own method.
const filterOptions = (options, searchFilter, selectedOptions) => {
return _.filter(options, options => _.includes(option.value, searchFilter));
}
and then
<Select {...props} filterOptions={filterOptions} />
Hope this example helps.