Growth Mindset
Growth Mindset

Reputation: 1233

Ag-grid set column text filter to range of letters

The goal is to set a column's text filter to be a range of letters that values start with. For example in a customer name column setting the filter to be "starts with" and a range of a-m. The user will enter the two letters that define the start and end of the range (eg. "a" and "m").

Ag-grid's filter docs state that "in range" filtering is only supported for date and number data types. Looking at ag-grid's multi-filter example, multiple filters are combined with an OR condition in the filter model:

{
    athlete: {
        filterType: "multi",
        filterModels: [
            {
                filterType: "text",
                operator: "OR",
                condition1: {
                    filterType: "text",
                    type: "startsWith",
                    filter: "a"
                },
                condition2: {
                    filterType: "text",
                    type: "startsWith",
                    filter: "b"
                }
            },
            null
        ]
    }
}

It looks like the solution is to programmatically find all letters in the range specified by the user, then include a condition for each letter in the "filterModels" array. Is there a more efficient way to do this?

Upvotes: 0

Views: 1583

Answers (1)

Growth Mindset
Growth Mindset

Reputation: 1233

A custom filter was the best solution for this scenario.

I was looking to support an optional range of letters, along with optional additional text in the filter field. Using a regular expression that matched this pattern inside the doesFilterPass method is working as expected.

Example using Vue and lodash:

doesFilterPass(params) {
    // Regex matches "[A-M]", "[n-z]", "[E-p] additionaltext", etc
    const nameFilterRegex = /^(?<nameStartRange>\[[a-z]{1}-[a-z]{1}\])?(?:\s+)?(?<additionalText>[a-z]+)?(?:\s+)?$/i;
    const regexResult = nameFilterRegex.exec(params.data.name);
    
    if (!isNil(regexResult)) {
        const nameRange = regexResult.groups.nameStartRange;
        const additionalText = regexResult.groups.additionalText;
    
        if (!isEmpty(nameRange)) {
            try {
                const lastNameRegex = new RegExp(nameRange, "gi");
                const matchedChar = params.data.name[0].match(lastNameRegex);
                if (isEmpty(matchedChar)) {
                    return false;
                }
            } catch {
                return false;
            }
        }
    
        if (!isEmpty(additionalText)) {
            if (!params.data.filterValue.includes(additionalText)) {
                return false;
            }
        }
    }
    
    return true;
};

Upvotes: 0

Related Questions