search envelope-o feed check
Home Unanswered Active Tags New Question
user comment-o

Adding custom filters

Asked by Anonymous
3 months ago.

Hello,

I’ve added two custom filters using a select2 multi-select element like this:

$(document).ready(function () {
    let assignedToSelect = $('#assignedToList').select2();
    let campaignSelect = $('#campaignList').select2();
    
    assignedToSelect.on('click change select2:select', function () {
        setUpMultiChoice("assignedToList", assignedToSelect);
    });

    campaignSelect.on('click change select2:select', function () {
        setUpMultiChoice("campaignList", campaignSelect);
    });
});



function setUpMultiChoice(listID, selectList) {
    let selectedValues = selectList.val();

    if (selectedValues?.includes("All Tasks")) {
        // Unselect all other values
        selectedValues = ["All Tasks"];
        selectList.val(null).trigger("change");
    }

    let uppercaseValues = selectedValues.map(function (value) {
        return value.toUpperCase();
    });

    let fieldToFilter = "";
    switch (listID) {
        case "assignedToList":
            fieldToFilter = "AssignedTo";
            break;
        case "campaignList":
            fieldToFilter = "Campaign";
            break;
    }
    filterWrapper(fieldToFilter, listID, uppercaseValues);
}

function filterWrapper(filterType, filterFieldID, selectedValues) {
                console.log("Entered filterWrapper for: ", filterFieldID, "on: ", new Date(),"\n\n");
                const query = document.getElementById(filterFieldID).value;
                if (query === "All Tasks" || selectedValues.length == 0 || selectedValues.includes("ALL TASKS")) {
                    dp.onRowFilter = null;
                    dp.update();
                    return;
                }
                let visibleTasks = [];
                const isTaskVisible = (task) => {
                    console.log("Entered isTaskVisible for: ", task, "on: ", new Date(), "\n\n");
                    if (!task.data) {
                        return false;
                    }
                    switch (filterType) {
                        case 'text':
                            return task.data.text?.toUpperCase().includes(query.toUpperCase());
                        case 'AssignedTo':
                            if (task.data.AssignedTo?.toUpperCase().includes(query.toUpperCase())) {
                                visibleTasks.push(task.data.id);
                                if (task.data.children && task.data.children.length > 0) {
                                    task.data.children.forEach(child => {
                                        visibleTasks.push(child.id);
                                    });
                                }
                            }
                            //console.log("visibleTasks: ",visibleTasks);
                            return (
                                task.data.AssignedTo && task.data.AssignedTo.toUpperCase().includes(query.toUpperCase()) ||
                                visibleTasks.includes(task.data.Parent_id)
                            );
                        case 'Campaign':
                            if (task.data.Campaign?.toUpperCase().includes(query.toUpperCase())) {
                                visibleTasks.push(task.data.id);
                            }
                            return (
                                task.data.Campaign && task.data.Campaign.toUpperCase().includes(query.toUpperCase()) ||
                                visibleTasks.includes(task.data.Parent_id)
                            );
                        default:
                            return true;
                    }
                };

                const isTaskOrAncestorVisible = (task, forceVisible = false) => {
                    if (forceVisible) {
                        return true;
                    }
                    if (isTaskVisible(task)) {
                        checkTaskChildrenVisibility(task.data.id, dp.tasks.list);
                        return true;
                    }
                    return false;
                };

                const checkTaskChildrenVisibility = (taskID, tasks) => {
                    tasks.forEach(task => {
                        if (task.data && task.Parent_id && task.Parent_id === taskID) {
                            visibleTasks.push(task.id);
                            task.visible = true;
                        }
                        if (task.children) {
                            checkTaskChildrenVisibility(taskID, task.children);
                        }
                    });
                };
                const isTaskInSelectedValues = (assignedToField, selectedValue) => {
                    return selectedValue.includes(assignedToField.toUpperCase())
                };

                dp.onRowFilter = function (args) {
                    console.log("Entered onRowFilter for: ", args, "on: ", new Date(), "\n\n");
                    args.visible = isTaskOrAncestorVisible(args.task) || (args.task.data.AssignedTo && isTaskInSelectedValues(args.task.data.AssignedTo, selectedValues));
                };
                console.log("Entered update on: ", new Date(), "\n\n");
                dp.update();
                console.log("After update on: ", new Date(), "\n\n");
            }

My problem is these filters only start to actually work (i.e enter the onRowFilter event) once I use the regular built in type filter at least once or press its filter button.
The event listener does attach and this is what my console looks like after the first time I choose a value in the multi select filter:

Entered filterWrapper for:  assignedToList on:  Tue Jan 16 2024 14:00:17 GMT+0200 (Israel Standard Time) 


Entered update on:  Tue Jan 16 2024 14:00:17 GMT+0200 (Israel Standard Time) 


After update on:  Tue Jan 16 2024 14:00:17 GMT+0200 (Israel Standard Time) 


Entered filterWrapper for:  assignedToList on:  Tue Jan 16 2024 14:00:17 GMT+0200 (Israel Standard Time) 


Entered update on:  Tue Jan 16 2024 14:00:17 GMT+0200 (Israel Standard Time) 


After update on:  Tue Jan 16 2024 14:00:17 GMT+0200 (Israel Standard Time) 

The dp.update() line is executed but no changes are made to it.

Answer posted by Dan Letecky [DayPilot]
3 months ago.

To apply the filter, it is necessary to call the rows.filter() method with a non-null parameter. It also updates the UI (no additional update() call is necessary).

This filter parameter is then stored and used during all updates until you call rows.filter(null) or rows.filter() which clears the filter.

Comment posted by Anonymous
3 months ago.

Thank you!

This question is more than 1 months old and has been closed. Please create a new question if you have anything to add.