Filters - Vivid Component
Filters are a group of HoCs designed to handle the data-side of filtering & sorting. They have nothing to do with UI.
createEntityFilterer- simply factory to create your own high-levelwithFilteredEntityList,withFilteredQuery, etc.withWhereaboutsFilter- basic query param powered filtering & sorting, powered by @rexlabs/whereaboutswithStatefulFilter- an alternative to Whereabouts filtering that simply uses local statewithFilter- a dumb building block used to parse filter configs & build controlled filters. This is low level & unlikely to be used in your app.
Simple Example
@withWhereabouts()
@withWhereaboutsFilter(contactsFilter)
class RoutedFilters extends React.Component {
changeFilter = (e) => {
this.props.filters.setFilter({ id: 'name', value: e.target.value });
};
render() {
return (
<div>
<span>{this.props.filters.filterValues.name}</span>
<input type={'text'} onChange={this.changeFilter} />
</div>
);
}
}
Usage
Filter Configs
Filter configs are simply objects that contain 3 mandatory properties: namespace, sorting and filters.
sorting and filters are objects where each key represents a filterable (or sortable) field.
These field sub-objects can contain whatever extra data you want. Currently, only an optional initialValue field is used.
export default {
namespace: 'contacts',
// Sorting options
sorting: {
name: {
label: 'Name', // label does nothing, but it may be useful for your app!
initialValue: 'asc',
},
email: {
label: 'Email',
initialValue: 'asc',
},
},
// Filter options
filters: {
name: {
label: 'Name',
},
email: {
label: 'Email',
},
},
};
Props
All filter HoCs pass down the following object, accessible via this.props.filters:
setFilters(filterObject): Shallow merges in new filter values (e.g.{name: 'Tom'})setSorting(sortingObject): Shallow merges in new sorting values (e.g.{email: 'desc'})set(filtersAndSorting): Shorthand function expects an object with keysfiltersandsortingreset(): Restores filters and sorting to initial valuesfilterValues: Object of current filter values, keyed by filter field name as defined in configsortingValues: Object of current sorting values, keyed by filter field nameconfig: The current filter config object being used
withWhereaboutsFilter(filterConfig, namespace, options)
Basic query param filtering & sorting.
NOTE: This needs access to a
whereaboutsprop to work, so be sure to put it UNDERwithWhereabouts()
filterConfig: The filter config object to usenamespace(optional): A custom namespace override. Used as query param prefixes. Defaults to namespace defined in your config.options: Object of extra options:sortingSeparator(default:|): String to split filter vlaues & sorting values in the url e.g.Chris|ascurlSeparator(default:.): String to separate namespace & field names in query param keys e.g.contacts.emailonChange(optional): Function triggered on any filter/sorting changeinitialValues(optional): Object to instantiate initial filter & sorting values
@withWhereabouts()
@withWhereaboutsFilter(contactsFilter)
class RoutedFilters extends React.Component {
changeFilter = (e) => {
this.props.filters.setFilter({ id: 'name', value: e.target.value });
};
render() {
return (
<div>
<span>{this.props.filters.filterValues.name}</span>
<input type={'text'} onChange={this.changeFilter} />
</div>
);
}
}
Tip: use
onChange&initialValuesto hook into the filters to do things like local storage persistence
withStatefulFilter(filterConfig, namespace, options)
Exactly the same API as withWhereaboutsFilter, but uses React local state instead of query params.
filterConfignamespace(optional)options(optional)onChangeinitialValues
@withStatefulFilter(contactsFilter)
class LocalStateFilters extends React.Component {
changeFilter = (e) => {
this.props.filters.setFilter({ id: 'name', value: e.target.value });
};
render() {
return (
<div>
<span>{this.props.filters.filterValues.name}</span>
<input type={'text'} onChange={this.changeFilter} />
</div>
);
}
}
Tip: use
onChange&initialValuesto hook into the filters to do things like local storage persistence
createEntityFilterer(entityHoC, argsGetter)
A higher order function that generates a the 'withFilteredEntity' HoC: an entity filterer to be used across your app.
Under the hood, it implements withWhereaboutsFilter.
entityHoC: The HoC from model generator to use.argsGetter: Function that translatespropsintoargs. Theargsobject is used by model generator. This function will likely need to be changed on a per-project basis, depending on how your backend API expects to receive filtering & sorting values. A sensible default is provided.
This function returns a HoC with the following params:
queryOrModel: Query or model to use (it supports either!)filterConfigoptions(optional):urlSeparatorsortingSeparatoronChangeinitialValues
import { withEntityList } from '@rexlabs/model-generator';
import { createEntityFilterer } from '@rexlabs/filters';
import contactsModel from './contacts-model';
import contactsFilter from './contacts-filter';
// You'd only want to do this once per app.
const withFilteredList = createEntityFilterer(withEntityList, (props) => ({
...props.filters.filterValues,
sort: props.filters.sortingValues,
}));
@withFilteredEntityList(contactsModel, contactsFilter)
class App extends React.Component {
filterEmail = () => {
this.props.filters.setFilters({ email: 'abc' });
};
render() {
console.log(this.props.contacts.list.items);
return <button onClick={this.filterEmail}>Filter Emails</button>;
}
}
Install dependencies
$ yarn
Available Commands
$ yarn start # starts storybook, for visually testing filters
$ yarn test # runs all units tests
$ yarn test:watch # runs unit tests when files change
$ yarn build # bundles the package for production
Legal
Copyright © 2019 Rex Software All Rights Reserved.