0

I want to create flexible table filtering on user-company-roles objects in JS array. User shall be able to provide filtering on multiple object properties, with multiple values, with use of AND (&&) operand when matching.

I would appreciate tip on how to proceed implementing the logic here. Of course I could loop through the array and have multiple nested if-statements, but maybe there are more clean and nice approach on this?

User-Company-Roles Array

const userArray = [
{
    "id": "peterpan",
    "name": "Peter pan",
    "company": [
        {
            "id": "12345678",
            "name": "Company A",
            "roles": [
                "Role A",
                "Role B",
                "Role C"
            ]
        }
    ],
    "systemRoles": [
        {
            "systemName": "System A",
            "role": "Admin"
        },
        {
            "systemName": "System B",
            "role": "User"
        }
    ]
},
{
    "id": "robinhood",
    "name": "Robin Hood",
    "company": [
        {
            "id": "9876543",
            "name": "Company B",
            "roles": [
                "Role A"
            ]
        },
        {
            "id": "546372",
            "name": "Company C",
            "roles": [
                "Role A"
            ]
        }
    ],
    "systemRoles": [
        {
            "systemName": "System B",
            "role": "User"
        }
    ]
},
{
    "id": "biggiant",
    "name": "Big Giant",
    "company": [
        {
            "id": "546372",
            "name": "Company C",
            "roles": [
                "Role A"
            ]
        }
    ],
    "systemRoles": [
        {
            "systemName": "System B",
            "role": "User"
        }
    ]
}
];

Filter object

const filter = {
        includeUserIds: [], // filters 'user.id' that matches values in this array
        includeCompanyNames: [], // filters 'user.company.name' that matches values in this array
        includeSystemRoleNames: [], // filters 'user.systemRoles.role' that matches values in this array
        includeCompanyRoles: [], // filters 'user.company.roles' that matches values in this array
        excludeSystemRoleNames: [], // filters 'user.systemRoles.role' that **DOES NOT** match values in this array
        excludeCompanyRoles: [] // filters 'user.company.roles' that **DOES NOT** match values in this array
    }

Matching When filtering the array I want the filter to match user-objects as this (pseudo code):

filter.includeUserIds && filter.includeCompanyNames 
    && filter.includeSystemRoleNames && filter.includeCompanyRoles 
    && !filter.excludeSystemRoleNames && !filter.excludeCompanyRoles

Example 1: Filter users by user id:

const filter = {
        includeUserIds: ['peterpan', 'robinhood'],
        includeCompanyNames: [],
        includeSystemRoleNames: [], 
        includeCompanyRoles: [], 
        excludeSystemRoleNames: [],
        excludeCompanyRoles: []
    }

Would return array with Peter Pan and Robin Hood users

Example 2: Filter by company name

const filter = {
        includeUserIds: [],
        includeCompanyNames: ['Company C'],
        includeSystemRoleNames: [], 
        includeCompanyRoles: [], 
        excludeSystemRoleNames: [],
        excludeCompanyRoles: []
    }

Would return array with Robin Hood and Big Giant users

Example 3: Filter by company roles and system roles

const filter = {
        includeUserIds: [],
        includeCompanyNames: [],
        includeSystemRoleNames: ['User'], 
        includeCompanyRoles: ['Role A'], 
        excludeSystemRoleNames: ['Admin'],
        excludeCompanyRoles: []
    }

Would return array with Robin Hood and Big Giant users

0

1 Answer 1

1

I would create a decision function for each type of the filter and put it into object with same properties as filter is. Each function should accept 2 arguments: item of type any and filter of type string[]. So it will look like:

const deciders = {
    includeUserIds: (item, filter) => { ... },
    includeCompanyNames: (item, filter) => { ... },
    includeSystemRoleNames: (item, filter) => { ... },
    includeCompanyRoles: (item, filter) => { ... },
    excludeSystemRoleNames: (item, filter) => { ... },
    excludeCompanyRoles: (item, filter) => { ... },
};

Then filtering is a simple filter of original array like:

const filtered = userArray.filter(user => {
  let include = true;
  Object.keys(deciders).forEach(type => include &= deciders[type](user, filter[type]));
  return include;
});
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. Can you give an example of logic within one deciders function?
Basically it is simple (item, filter) => filter.indexOf(item) !== -1 but may differ e.g. in a case of a company where you have actual value deeper in object

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.