Register a Custom Display Filter

It is possible to register a custom filter and use it as a displayFilter for dashboards or search modals.

At the moment there are 3 types of custom filters:

Hint: If you want to create a filter with metadata, make sure they are setup correctly in the ElasticSearch index (search.metadata_mapping config in the server)

Register Custom List v2 Filter

Added in: release-2020-02


searchFilters.registerListV2 registers an object where you can configure a filter object which is used to render the search UI.



  • datasource.fetch fetch data async from a remote service or create a list of filter items

  • mount - configure the filter object

liEditor.searchFilters.registerListV2('contentTypeV2Filter', {
datasource: {
// fetch data and inject response into mount function
async fetch ({project, user, server, config}) {
const host =
const channelId =
const uri = `${host}/channel-configs/properties?channelId=${channelId}&properties=contentTypes`
const response = await window.fetch(uri, {
method: 'GET',
headers: new window.Headers({
'Content-Type': 'application/json',
'Authorization': `Bearer ${server.accessToken}`
// only succeed on status codes 200 - 299
if (!response.ok) throw new Error('contentTypeV2Filter was not able to fetch data')
return response.json()
// Mount a search filter (search behaviour, display options)
// @param data injected result from datasource.fetch
// @example options = [{
// id: 'regular',
// label: 'Regular Article',
// type: 'contentType',
// value: 'regular'
// }, {
// id: 'page',
// label: 'Page',
// type: 'contentType',
// value: 'page',
// isDefault: true
// }]
async mount ({data, filter}) {
const options = => {
return {
id: ct.handle,
// these props are used for creating a search request (see above section 'Filter Query Types')
type: 'contentType',
value: ct.handle
filter.options = options

isDefault option

Added in: release-2020-07

When isDefault: true (see example above), the default option will be added to the search query by default. As soon as one selects a filter manually, the default filter option will be ignored.

Register Custom List Filter

Deprecated since: release-2020-02


searchFilters.registerList registers a filter based on a config object to create an Angular directive for the search UI. Display is controlled with the filters key in the configuration.

There are two flavors to this function

liEditor.searchFilters.registerList('creation-date', ['session', 'config', (session, config) => {
const channels = _map(session.project.channels, (channel) => ({
label: channel.label,
// type and value are used in the query builder
type: 'channelId',
return {
title: 'Filter by channels',
options: channels
liEditor.searchFilters.registerList('creationDate', {
title: 'Filter by creation date',
options: [{
id: '2015',
label: 'Created in 2015',
type: 'dateRange',
key: 'created_at',
from: new Date('2015-01-01'),
to: new Date('2016-01-01')
}, {
id: '2016',
label: 'Created in 2016',
type: 'dateRange',
key: 'created_at',
from: new Date('2016-01-01'),
to: new Date('2017-01-01'),
isDefault: true

Register Custom Angular Component Filter


searchFilters.registerAngularComponent registers an Angular component as filter for the search UI. Display is controlled with the filters key in the configuration.

coreApi.searchFilters.registerAngularComponent('test', {
bindings: {
value: '=',
config: '='
template: `
ng-class="{'is-set': $ctrl.isActive}"
<div class="ld-dropdown__text">
Show print documents
controller: class PrintController {
static get $inject () { return ['session'] }
constructor (session) {
this.session = session = _find(session.project.channels, {handle: 'print'}) || {}
this.hasPrint = !!
$doCheck () {
this.isActive = this.value.get()
toggleProjectFilter () {
if ( this.isActive = !this.isActive
if (this.isActive && {
this.value.set({type: 'channelId', value:})
} else {