Task List - Filter Parent task on current project filter (what is the best custom way to do that?)


I have a customer request, on task list when standard filter list on project is apply, the additional filter (with the filter button) on Parent Task field have to suggest only tasks from the project previously filtered.

I wonder what is the bast way to do that in my customer app
1 - add a hook doctype_list_js = {“Task”: [“public/js/task_list.js”]} but still execute standard task_list.js to keep standard feature and try to intercept query (get_query) on parent_task filter. I try that but seems big hack to manage this (and I didn’t success to make it correctly for now)
2 - add a hook doctype_list_js = {“Task”: [“public/js/task_list.js”]} but still execute standard task_list.js to keep standard feature and add a special button with onload: function(listview) {listview.page.add_menu_item(__(“Special filter”), function() { “frappe.dialog with add_field({…}) that ask project and parent task filtered on project and send the filter resulting to the listview filter)”}, I didn’t try it yet but seems a better option

What would be your best way to do that ? Is there another way ?

Hello dear Frappe customizer,

Here my solution

doctype_list_js = {
"Task": [


special_filter_feature = {
  onload: function (listview) {
    //Copy/paste from erpnext/projects/doctype/task/task_list.js because listview_settings
    // do not execute standard call and after custom app call
    // The only way is to rewrite the standard method
    let method = "erpnext.projects.doctype.task.task.set_multiple_status";

    listview.page.add_menu_item(__("Set as Open"), function () {
      listview.call_for_selected_items(method, {"status": "Open"});

    listview.page.add_menu_item(__("Set as Completed"), function () {
      listview.call_for_selected_items(method, {"status": "Completed"});
    //End of copy/paste

    //Purpose of this custom JS : add a spécial filter button on the list
    listview.page.add_inner_button(__('Special Filter Parent Task'), () => {
    }, '');


$.extend(frappe.listview_settings['Task'], special_filter_feature);

function dialog_filter_parent_task(listview) {

  let d = new frappe.ui.Dialog({
    title: 'Filter On Parent Task By Project',
    fields: [
        label: __('Project'),
        fieldname: 'project_filter',
        fieldtype: 'Link',
        options: "Project",
        default: listview.page.fields_dict.project.get_value(),
        change: function () {
        label: __('Parent Task'),
        fieldname: 'task_filter',
        fieldtype: 'Link',
        options: "Task",
    size: 'small', // small, large, extra-large
    primary_action_label: __('Apply Filter'),
    primary_action(values) {
      listview.filter_area.remove("project").then(() => {
        listview.filter_area.add("Task", "project", "=", d.fields_dict.project_filter.get_value());
      listview.filter_area.remove("parent_task").then(() => {
        listview.filter_area.add("Task", "parent_task", "=", d.fields_dict.task_filter.get_value());

  function set_query_filter(prj) {
    d.fields_dict.task_filter.get_query = {
      "filters": {"is_group": 1, "project": prj}