
Você precisa escrever manipuladores de filtro para seus dados? Pode ser matrizes para desenhar tabelas, cartões, listas - qualquer coisa.
Quando a filtragem Ă© estática, tudo Ă© simples. As caracterĂsticas padrĂŁo map, filtere reducebastante. Mas e se os dados tiverem uma estrutura complexa ou aninhamento, e houver muitas regras para o filtro. As regras podem ser repetidas, os dados podem ser alterados e, quanto mais controles de filtro aparecerem, mais complexo e instável será o cĂłdigo do manipulador.
Como resolver o problema de aumentar a complexidade?
Eu mesmo enfrentei esse problema ao desenvolver um aplicativo que funciona com uma enorme quantidade de dados. Gradualmente adicionou mais e mais novos filtros.
, . . , . , . - .
, .
, :
- ng-table— . .
- List.js— ng-table, .
- filter.js— , , .
- Isotope— DOM . .
, :
- .
- .
- .
- , andor.
- . .
- ( , , , , , )
awesome-data-filter.
, , .
.
npm install awesome-data-filter
.
, :
const users = [
  {
    age: 31,
    name: "Marina Gilmore",
  },
  {
    age: 34,
    name: "Joyner Mccray",
  },
  {
    age: 23,
    name: "Inez Copeland",
  },
  {
    age: 23,
    name: "Marina Mitchell",
  },
  {
    age: 25,
    name: "Prince Spears",
  },
];
:
const filterValue = {
  age: 23,
  searchText: "mari",
};
, .
:
- matchText— ;
- equalProp— ;
 - betweenDates— ;
- equalOneOf— ;
- someInArray— ;
- isEmptyArray— ;
- lessThen— , ;
- moreThen— , ;
- not— .
 
matchText equalProp.
:
- filterField— ;
- elementField— .
import { 
  buildFilter, 
  elementField, 
  filterField, 
} from "awsome-data-filter";
import { matchText, equalProp } from "awsome-data-filter/rules";
import { and } from "awsome-data-filter/conditions";
const filter = buildFilter({
    rules: {
      elementFilter: and([
        matchText(filterField("searchText"), elementField("name")),
        equalProp(filterField("age"), elementField("age")),
      ]),
    },
  });
const { elements } = filter(
    filterValue,
    {
      groups: [],
      elements: users,
    },
);
console.log(elements);
filter groups elements.
, . .

, , elements.
and or, 2 .
import { 
  buildFilter, 
  elementField, 
  filterField, 
} from "awsome-data-filter";
import { matchText, equalProp } from "awsome-data-filter/rules";
import { or } from "awsome-data-filter/conditions";
const filter = buildFilter({
    rules: {
      elementFilter: or([
        matchText(filterField("searchText"), elementField("name")),
        equalProp(filterField("age"), elementField("age")),
      ]),
    },
  });
const { elements } = filter(
    filterValue,
    {
      groups: [],
      elements: users,
    },
);
console.log(elements);
filterField, elementField .
constValue .
or(..., matchText, [and([..., matchText, ...]), or([..., ...])])
. :
const dataList = [
  {
    groupName: "first group",
    list: [
      { age: 31, name: "Marina" },
      { age: 23, name: "Fabio" },
    ],
  },
  {
    groupName: "second group",
    groups: [
      {
        groupName: "third group",
        list: [],
        groups: [
          {
            groupName: "fourth group",
            list: [{ age: 42, name: "Li" }],
          },
        ],
      },
    ],
    list: [
      { age: 41, name: "Marina" },
      { age: 29, name: "Inez" },
      { age: 33, name: "Marina" },
    ],
  },
  {
    groupName: "fifth group",
    list: [
      { age: 21, name: "Dmitriy" },
      { age: 22, name: "Li" },
      { age: 45, name: "Mitchell" },
    ],
  },
];
traversal:
import { 
  buildFilter, 
  elementField, 
  filterField, 
} from "awsome-data-filter";
import { matchText } from "awsome-data-filter/rules";
const filter = buildFilter({
    traversal: {
      getChildrenFunc: group => group.list, 
      setChildrenFunc: (group, list) => ({ ...group, list }), 
      getGroupsFunc: group => group.groups, 
      setGroupsFunc: (group, groups) => ({ ...group, groups }), 
    },
    rules: {
      elementFilter: matchText(filterField("searchText"), elementField("name")),
    },
  });
const filterValue = {
  searchText: "li",
};
const { groups } = filter(filterValue, {
  groups: dataList, 
  elements: [], 
});
console.log(groups);
elementFilter , . groupFilter .
import { 
  buildFilter, 
  elementField, 
  filterField, 
} from "awsome-data-filter";
import { matchText } from "awsome-data-filter/rules";
const filter = buildFilter({
    traversal: {
      getChildrenFunc: group => group.list, 
      setChildrenFunc: (group, list) => ({ ...group, list }), 
      getGroupsFunc: group => group.groups, 
      setGroupsFunc: (group, groups) => ({ ...group, groups }), 
    },
    rules: {
      elementFilter: matchText(filterField("searchText"), elementField("name")),
      groupFilter: matchText(filterField("groupName"), elementField("groupName")),
    },
  });
const filterValue = {
  searchText: "li",
  groupName: "fi",
};
const { groups } = filter(filterValue, {
  groups: dataList,
  elements: [],
});
console.log(groups);
first group , , , .
fifth group , , .
const standardStrategy: StrategiesFilterInterface = {
  elementHandler: ({ 
    element,
    tools: { 
        isGroupFilterIsActive, 
        applyElementFilter 
    },
  }) => {
    if (isGroupFilterIsActive) return null;
    if (!applyElementFilter) return element;
    return applyElementFilter(element, true) ? element : null;
  },
  groupHandler: ({
    element: group,
    originalElement: originalGroup,
    tools: {
      isGroupFilterIsActive,
      applyElementFilter,
      getIsGroupFilterHaveMatch,
      getGroupsFunc,
      getChildrenFunc,
      setChildrenFunc,
    },
  }) => {
    let newChildren = [];
    let originalChildren = [];
    const children = getChildrenFunc(group);
    const childrenExists = !!children;
    
    if (children) {
      originalChildren = [...children];
      newChildren = originalChildren.filter(element =>
        applyElementFilter
          ? applyElementFilter(element, !isGroupFilterIsActive)
          : !isGroupFilterIsActive,
      );
    }
    
    if (!newChildren.length && getIsGroupFilterHaveMatch(group)) {
      return originalGroup;
    }
    
    if (childrenExists) {
      group = setChildrenFunc(group, newChildren);
    }
    
    const newGroups = getGroupsFunc(group);
    const isGroupsExists = !!(newGroups && newGroups.length);
    const isElementExists = !!(newChildren && newChildren.length);
    
    return isElementExists || isGroupsExists ? group : null;
  },
};
, filterStrategy.
awesome-data-filter . .

, . .
, .