Skip to main content

Configure a List Filter on the Custom List Component

Zuora

Configure a List Filter on the Custom List Component

This article explains how to configure a List Filter on custom List Component instances.

Configure List Filter on Custom List Component Instances

When you implement a custom List Component instance, you need to take the following steps to add and configure a List Filter on that custom list:

  1. Implement a new List Filter Admin Plugin class.
  2. Modify the Query Plugin for the List Component instance.
  3. Register your new List Component instance with the new List Filter Admin Plugin and the updated Query Plugin classes.
  4. Configure the List Filter for the new List Component instance.

Implement the List Filter Admin Plugin

To be able to edit the List Filter on your new List Component instance, you need to implement a new List Filter Admin Plugin class by extending the zqu.AbstractListFilterController class. The List Filter Admin Plugin provides the following information to the List Filter Settings page:

  • The registered name of the List Component instance
  • The object to which the List Component instance is applied
  • The context object of the List Filter. For example, in the product selection step, the Quote is the context object since the quote currency affects the products that you can select.
  • The fields not available for selection when defining a filter criteria.

AbstractListFilterController Methods

The table below lists all the abstract methods that need to be implemented in your List Filter Admin Plugin class.

Method Signature
Description
abstract String getListName() Return the list name this filter is applied against, e.g. ProductList.
abstract String getLeftObjectName() Return the left object name used by this filter.
abstract Map <String, ContextObjec> getContextObjects() Return the map of the right objects that form the filter context at runtime.
abstract List <ListFilterItem> getProtectedFilters() Return the list of protected filters already applied to the list.
abstract Set <String> getRestrictedFields() Return the list of fields that should not be available for selection. Return their unique name, relationship and namespace prefix.

The following method is implemented in the AbstractListFilterController class and is called at runtime to generated the proper SOQL fragment for the List Filter. It requires a map that associates a Salesforce ID (value) to a context object, whose name (key) matches what you declared in the getContextObjects() method implementation in your class.

Method Signature
Description
String getSoqlFragment
(Map <String, String> contextIds)

Build the SOQL fragment to be added to the List Component options by passing all the context object IDs.

If an ID is missing, all dynamic values associated with this context are dismissed.

The following code is an example implementation of the ProductList List Filter Controller class:

/**
 *  Implementation of the list filter for the product selector
 */
 global class ProductListFilterController extends zqu.AbstractListFilterController {
  private Set < String > restrictedFields;
  private Map < String, zqu.ContextObject > ctx;
  public override String getListName() {
    return 'ProductList';
  }
  public override String getLeftObjectName() {
    return 'zqu__ZProduct__c';
  }
  public override Map < String, zqu.ContextObject > getContextObjects() {
    if (ctx == null) {
      // Get the global describe
      Map < String, Schema.SObjectType > globalDescribe = Schema.getGlobalDescribe();
      zqu.ContextObject accountContext = new zqu.ContextObject();
      accountContext.objectKey = 'Account';
      accountContext.objectName = 'Account';
      accountContext.objectType = globalDescribe.get('Account');
      zqu.ContextObject opportunityContext = new zqu.ContextObject();
      opportunityContext.objectKey = 'Opportunity';
      opportunityContext.objectName = 'Opportunity';
      opportunityContext.objectType = globalDescribe.get('Opportunity');
        
      zqu.ContextObject quoteContext = new zqu.ContextObject();
      quoteContext.objectKey = 'Quote';
      quoteContext.objectName = 'zqu__Quote__c';
      quoteContext.objectType = globalDescribe.get('zqu__Quote__c');
        
      ctx = new Map < String, zqu.ContextObject > {
        accountContext.objectKey      => accountContext,
        opportunityContext.objectKey  => opportunityContext,
        quoteContext.objectKey        => quoteContext
      };
    }
    return ctx;
  }
  public override List<zqu.AbstractListFilterController.ListFilterItem> getProtectedFilters() {
    // Currency (protected) filter
    zqu.AbstractListFilterController.ListFilterItem currencyFilter = new zqu.AbstractListFilterController.ListFilterItem();
    currencyFilter.leftObjectValue = 'Product';
    currencyFilter.leftFieldValue = 'Currency';
    currencyFilter.operatorValue = 'equals';
    currencyFilter.rightType = 'field';
    currencyFilter.rightObjectValue = 'Quote';
    currencyFilter.rightFieldValue = 'Currency';
    currencyFilter.isProtected = true;
    return new List<zqu.AbstractListFilterController.ListFilterItem> { currencyFilter };
  }
  public override Set<String> getRestrictedFields() {
    if (restrictedFields == null) {
      restrictedFields = new Set<String> {
        'IsDeleted',
        'CreatedDate',
        'LastModifiedDate',
        'SystemModstamp',
        'LastReferencedDate',
        'zqu__Active__c',
        'zqu__Deleted__c',
        'zqu__EffectiveEndDateTEXT__c',
        'zqu__EffectiveStartDateTEXT__c',
        'zqu__AmendmentName__c',
        'zqu__DeltaMRR__c',
        'zqu__DeltaTCV__c',
        'zqu__MRR__c',
        'zqu__SubscriptionName__c',
        'zqu__Tax__c',
        'zqu__TCV__c',
        'zqu__Total__c'
      };
    }
    return restrictedFields;
  }
}

Modify the Query Plugin

In order to have a List Filter, the List Component instance must have a Query Plugin that calls the getSoqlFragment method, appends the filter SOQL fragment to the base SOQL, and returns the Database.QueryLocator object.

Here is an example of a Query Plugin implementation:

 global class MyQueryPlugin implements zqu.ListComponentController.IQueryPlugin {
    public Database.QueryLocator getQueryLocator(String baseSoql, ParentController parentController) {
        // Prepare an empty map of context IDs, to simplify the example
        Map < String, String > contextIds = new Map < String, String > ();
        // Retrieve the SOQL fragment from the list filter admin
        zqu.AbstractListFilterController filter = new YourImplementationFilter();
        String soqlFragment = filter.getSoqlFragment(contextIds);
        // Append it to the base SOQL
        if (baseSoql.containsIgnoreCase('where')) {
            baseSoql += ' AND ' + soqlFragment;
        } else {
            baseSoql += ' WHERE ' + soqlFragment;
        }
        return Database.getQueryLocator(baseSoql);
    }
}

Register the List Component 

After you implement the List Filter Admin Plugin and the Query Plugin for the new List Component instance, perform the following to complete the configuration:

  1. Register your List Component instance.
  2. Set the List Filter Admin Plugin value to the name of your List Filter Admin Plugin class that extends the AbstractListFilterController class.
  3. Set the Query Plugin to your implementation of the Query Plugin this instance of the List Component.

Now your List Component instance is displayed on the List Filter Configuration Settings page, and you can edit the List Filter for the new List Component instance on that settings page.

See Component Registration for detail steps of registering a component.