custom-filter-react
v1.6.4
Published
A library for filtering data
Downloads
24
Readme
Props to pass in
1. filterConfigurations
- Required to pass in
- Format: Array of objects
- Used for displaying desired filters
- E.g:
const filterConfigurations = [
{
type: "Dropdown",
placeholder: "Select Category",
multiSelect: true,
field: "Country",
dropdownStyles: { border: "1px solid #ccc" },
className: "custom-dropdown",
style: { width: "200px" },
},
{
type: "NumberInput",
range: true,
field: "Number",
placeholder: "Number",
},
{
type: "DateInput",
range: true,
field: "Dateline",
formatStyle: "large",
firstPlaceHolder: "Start Date",
secondPlaceHolder: "End Date",
firstLabel: "Select Date Range",
button: true,
},
{
type: "CheckboxInput",
field: "Optional",
label: "Optional",
color: "success",
},
{
type: "TextField",
field: "Name",
placeholder: "Name",
width: "30",
},
];
2. url
- Required to pass in
- Format: String
- Used to retrieve data to be displayed
- E.g http://localhost:5000/applyFilter
- Required params in api url:
- filterValues, page, limit
- filterValues format after user clicks on apply filter button will be in an object for example:
- filterValues: { Name: '', Country: [ 'N/A' ] }
- page is the page number, will be passed in after applying filter
- limit is the number of items displayed in a page, will be passed in after applying filter
- Expected output of api is (response.data):
- data: array of objects (table data)
- totalPages: Number (number of pages in pagination)
- Example:
{ "data": [ { "_id": "6614b7c2199743da24dc1a5b", "Country": "N/A", "Number": 2, "Dateline": "2024-01-06T12:30:00.000+00:00", "Name": "Peter" }, { "_id": "6614b7c2199743da24dc1a5d", "Country": "N/A", "Number": 86, "Dateline": "2024-02-06T12:30:00.000+00:00", "Optional": false, "Name": "Aimee" }, { "_id": "6614b7c2199743da24dc1a5e", "Country": "N/A", "Number": 98, "Dateline": "2022-04-06T12:30:00.000+00:00", "Optional": false, "Name": "Chloe" }, { "_id": "661746bb6d176f3a79b9d64c", "Country": "N/A", "Number": 86, "Dateline": "2024-02-06T12:30:00.000+00:00", "Optional": false, "Name": "Marcus" }, { "_id": "6626050a64812c92fa97c5b5", "Country": "N/A", "Number": 86, "Dateline": "2024-02-06T12:30:00.000+00:00", "Optional": false, "Name": "Sarah" } ], "totalPages": 1 }
- Example of how api may look like (collectionName is not required to be in req.query):
router.get("/applyFilter", async (req, res) => {
try {
let { filterValues, collectionName } = req.query;
let { page, limit, sortField, sortDirection } = req.query;
console.log(req.query);
if (page === undefined) {
page = 1;
}
if (limit === undefined) {
limit = 5;
}
let skip = (page - 1) * limit;
// Check if the model already exists
const Model = require(`./models/${collectionName}`);
// Construct the filter query based on the filterValues
const filterQuery = {};
// Check if filterNumber is a valid number
if (filterValues) {
if (!isNaN(parseInt(filterValues.Number))) {
// Use filterNumber in your filter logic
filterValues.Number = parseInt(filterValues.Number);
} else {
// Handle the case where filterNumber is not a valid number
}
} else {
filterValues = {};
}
// Iterate over the filterValues object
for (const [key, value] of Object.entries(filterValues)) {
// Check if the value is empty or null
if (value !== "" && value !== null) {
// For each filter category
switch (typeof value) {
case "string":
if (value.includes(",")) {
// Construct regex pattern to match both scenarios as a string
const regexPattern = `^(${value
.split(",")
.map((v) => v.trim())
.join("|")})$`;
// Use the regex pattern in the MongoDB query
filterQuery[key] = { $regex: regexPattern, $options: "i" };
} else {
if (value === "false" || value === "true") {
filterQuery[key] = value;
} else {
// Otherwise, construct the regex pattern
const regex = new RegExp(value, "i");
filterQuery[key] = { $regex: regex };
}
}
break;
case "number":
// For single value filters, directly add to filterQuery
filterQuery[key] = value;
break;
case "object":
// For range filters, construct $gte and $lte conditions
if ("start" in value && "end" in value) {
// Handle range filters
if (
value !== null &&
value !== "" &&
value.start !== "" &&
value.end !== ""
) {
if (isNaN(value.start) || isNaN(value.end)) {
filterQuery[key] = {
$gte: value.start + "T00:00:00",
$lte: value.end + "T23:59:59",
};
} else {
filterQuery[key] = { $gte: value.start, $lte: value.end };
}
}
} else {
// Handle other object types
filterQuery[key] = value;
}
break;
default:
// Handle other filter types if necessary
break;
}
}
}
const totalCount = await Model.countDocuments(filterQuery);
console.log(skip);
console.log(totalCount);
if (skip >= totalCount) {
skip = 0;
}
// Calculate the total number of pages
const totalPages = Math.ceil(totalCount / limit);
// Perform the query with filterQuery and pagination options
const data = await Model.find(filterQuery)
.sort(sortField ? { [sortField]: sortDirection === "asc" ? 1 : -1 } : {})
.skip(skip) // Skip documents
.limit(limit); // Limit the number of documents
// Send the filtered data and total pages as response
res.json({ data, totalPages });
} catch (error) {
res.status(500).json({ message: error.message });
}
});
3 collectionName
- Optional
- Used if api url requires in req.query
4 theme
- Optional
- Default theme is light
- Available themes: light, blue, dark, pink, sky, green, purple, red, yellow
Example Use of Library
import React from 'react'
import UseCustomFilters from 'custom-filter-react'
import config from "../config";
const { backendUrl } = config;
const testLibrary = () => {
const filterConfigurations = [
{
type: "Dropdown",
placeholder: "Select Category",
multiSelect: true,
field: "Country",
dropdownStyles: { border: "1px solid #ccc" },
className: "custom-dropdown",
url: `http://${backendUrl}/getFieldOptions`,
},
{
type: "NumberInput",
range: true,
field: "Number",
placeholder: "Number",
},
{
type: "DateInput",
range: true,
field: "Dateline",
formatStyle: "large",
firstPlaceHolder: "Start Date",
secondPlaceHolder: "End Date",
firstLabel: "Select Date Range",
button: true,
},
{
type: "CheckboxInput",
field: "Optional",
label: "Optional",
color: "success",
},
{
type: "TextField",
field: "Name",
placeholder: "Name",
width: "30",
},
];
return (
<div>
<UseCustomFilters filterConfigurations={filterConfigurations} url={`http://${backendUrl}/applyFilter`} theme={"red"} />
</div>
)
}
export default testLibrary
Required fields for each type of filter
Number input | Props | Value | Required | | -------- | ------- | ------- | | field | field in the database to be filtered | yes |
| range | true/false | no | | width | number | no | | size | sm/md/lg | no | | placeholder | String | no | | firstPlaceHolder | String | no | | secondPlaceHolder | String | no |Date input | Props | Value | Required | | -------- | ------- | ------- | | field | field in the database to be filtered | yes |
| range | true/false | no | | width | number | no | | formatStyle | small/medium/large | no | | placeholder | String | no | | firstPlaceHolder | String | no | | secondPlaceHolder | String | no | | label | String | no | | firstLabel | String | no | | secondLabel | String | no |Dropdown | Props | Value | Required | | -------- | ------- | ------- | | field | field in the database to be filtered | yes |
| url | String | yes | | collectionName | String | no if url route already has collection name determined | | fontSize | Number | no | | placeholder | String | no | | width | Number | no | | multiSelect | true/false | no | | className | String | no | | color | String | no |Checkbox input | Props | Value | Required | | -------- | ------- | ------- | | field | field in the database to be filtered | yes |
| defaultChecked | true/false | no | | size | small/medium/large | no | | label | String | no | | color | String | no |Textfield input | Props | Value | Required | | -------- | ------- | ------- | | field | field in the database to be filtered | yes |
| width | number | no | | size | sm/md/lg | no | | placeholder | String | no |