Allow select handlers to apply a hidden advanced filter for dynamic scoping

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • rabii
    Active Community Member
    • Jun 2016
    • 1416

    #1

    Allow select handlers to apply a hidden advanced filter for dynamic scoping

    selectHandler (handlers/select-related) and getSelectFilters let a link field scope the select modal's results dynamically based on the host record's current values. This works correctly for the query. However, any filter returned via the advanced key is rendered in the select modal as a visible, user-editable/removable filter pill.

    When the filter targets a relationship rather than a real field on the foreign entity (e.g. filtering Account by its contactsrelation), the pill renders as an empty/broken control, and — more importantly — the user can remove it, defeating the intended scoping.

    There is currently no supported return key to apply an advanced filter as a hidden constraint (applied to the query, not surfaced in the filter UI).

    Concrete example

    A common requirement: on Opportunity, when a primary contact is selected, the account field's select modal should only offer accounts linked to that contact.

    clientDefs/Opportunity.json:
    PHP Code:
    {
        "fields": {
            "account": {
                "selectHandler": "custom:handlers/opportunity/contact-account"
            }
        }
    } 
    

    Handler:
    PHP Code:
    define('custom:handlers/opportunity/contact-account', ['handlers/select-related'], (SelectRelatedHandler) => {
    
        class ContactAccountSelectRelatedHandler extends SelectRelatedHandler {
    
            getFilters(model) {
    
                const advanced = {};
                const contactId = model.get('contactId');
    
                if (contactId) {
                    advanced.contacts = {
                        type: 'linkedWith',
                        attribute: 'contacts',
                        value: [contactId],
                    };
                }
    
                return Promise.resolve({advanced});
            }
        }
    
        return ContactAccountSelectRelatedHandler;
    }); 
    

    This filters the Account list correctly (only accounts linked to the selected contact appear), but because contacts is a relationship and not a field on Account, the resulting advanced-filter pill renders empty and is user-removable.

    So today a developer must choose between a filter that carries the dynamic value but renders a removable/broken pill, or a hidden filter that can't see the dynamic value.

    Benefit

    Cascading link-field scoping based on a related record's relationships is a frequent customization need. A hidden-filter channel would make it a first-class, non-hacky pattern rather than requiring a custom field view + custom select-records modal override.
    Last edited by rabii; 06-28-2026, 01:48 PM. Reason: cust
    Rabii
    EspoCRM Custom Development

    🔗 Portfolio & Builds
  • rabii
    Active Community Member
    • Jun 2016
    • 1416

    #2
    Current workaround

    For anyone hitting this before native support exists, here's the approach that avoids the broken/removable pill — without overriding setupSearch or any search-manager internals.

    Instead of trying to hide an individual filter, hide the entire search panel in the select modal, but only when the dynamic filter is actually applied. The filter itself still scopes the results correctly via the normal selectHandler/getSelectFilters advancedpath; hiding the panel just removes the UI that would otherwise render the broken pill.

    Custom select modal:
    PHP Code:
    define('custom:views/opportunity/modals/select-account', ['views/modals/select-records'], (SelectRecordsModalView) => {
    
        class SelectAccountModalView extends SelectRecordsModalView {
    
            setup() {
    
                console.log('search modal triggered');
    
                if (this.options.filters && Object.keys(this.options.filters).length) {
                    this.options.searchPanelDisabled = true;
                }
    
                super.setup();
            }
        }
    
        return SelectAccountModalView;
    }); 
    

    Registered alongside the existing handler.

    Behavior:
    • Contact selected → results are scoped to that contact's accounts, and the search panel (and therefore the broken filter pill) is hidden.
    • No contact → filters is empty, the panel renders normally, full default search is available.

    A native hidden-filter channel (as proposed above) would let the dynamic scope be enforced and keep text search and other filters usable — which this workaround can't do.
    Rabii
    EspoCRM Custom Development

    🔗 Portfolio & Builds

    Comment

    • yuri
      EspoCRM product developer
      • Mar 2014
      • 9893

      #3
      Hi,

      To solve the problem with a non-existing field, one can create a link-multiple field with the noLoad parameter. It won't load records in the detail view but can be used for search purposes.

      To solve the problem of filter removing, one can add backend validation. This is how I would always do in such cases, this is how it should be done to prevent the possibility to post invalid data (even through the API calls).

      Hiding filters is not what I would want to have. I believe that we should avoid such a behavior, and filters should be always explicit. The clean solution would be to have read-only filters, but unfortunately our fields does not support read-only search view and adding such a feature would be kind of a breaking change as custom fields created by developers would not be able to support it properly. And it would be quite a complex endevour.

      Comment


      • rabii
        rabii commented
        Editing a comment
        i agree and already implemented the backend validation first thing but from front end was just more about user experience to make it easy for the end user to move to next step.

        Making filters readonly would be a true beautiful addition - it was much better than hiding the filters. so may if there is a way in future to add this it will be a really nice feature.

        Thanks
    Working...