loading table of contents...

7.11.5. Adding Search Filters

The search mode of the library offers a filter panel at the left side of the window in which you can, by default, select the editing state of documents to be included in the search result. Depending on your editorial needs, you can add custom search filters that further restrict the search result. For example, you might want to search only for recently edited documents or for documents in a particular language.

For defining a custom filter, you can inherit from the class FilterFieldset. This class implements the interface SearchFilter and provides the framework for implementing a custom filter easily. Your implementation uses an ActionScript base class and an EXML user interface definition inheriting from that class. Both classes communicate by means of a model bean provided by the framework's base class through the method getStateBean().

See section Section 7.7, “Storing Preferences” for details of how the value stored in the state bean is persisted and for the limits on the allowed property values.

In your base class, you need to override two methods. The method buildQuery() can use the current state stored in the model bean to assemble a Solr query string. Query strings from individual filters will be combined using the AND operator. By returning an empty string or null, you can indicate that the filter should not currently impose any restrictions on the search result. The following example shows how a property foo is retrieved and how a query is built from it.

public class FooFilterFieldsetBase extends FilterFieldset {
  override public function buildQuery():String {
    var foo:Number = getStateBean().get('foo');
    if (foo === 0) {
      return null;
    } else {
      return "foo:" + foo + " OR foo:-1";
    }
  }
  ...

The method getDefaultState() returns an object mapping all properties of the state bean to their defaults. It is used for initialization, for determining whether the current state of your UI represents the filter's default state, and for manually resetting the filter. In the above example, the respective filter's default state is represented by the special value "0", and consequently, you must use "0" as the filter's default value:

  ...
  override public function getDefaultState():Object {
    return { foo:0 };
  }
}

Now you can create the EXML definition of the actual UI for the new filter. Because the item ID of the filter component is used when identifying the filter later on, it often makes sense to specify the item ID directly in the EXML file. The basic structure is shown here:

<?xml version="1.0" encoding="UTF-8"?>
<exml:component xmlns:exml="http://www.jangaroo.net/exml/0.8"
                xmlns="exml:ext.config"
                xmlns:editor=
                  "exml:com.coremedia.cms.editor.sdk.config"
                baseClass="FooFilterFieldsetBase">
  <editor:filterFieldset
          itemId="fooFilter"
          title="Foo">
    <items>
      ...
    </items>
  </editor:filterFieldset>
</exml:component>

To synchronize your UI component(s) with the model state stored in the bean returned by getStateBean(), you might want to use the various existing bind plugins. The example below shows a typical configuration of the bindPropertyPlugin that would work in a filter fieldset for a text field or a combo box.

  ...
  <plugins>
    <ui:immediateChangeEventsPlugin/>
    <ui:bindPropertyPlugin bidirectional="true">
      <ui:bindTo>
        <ui:valueExpression expression="foo"
                            context="{getStateBean()}"/>
      </ui:bindTo>
    </ui:bindPropertyPlugin>
  </plugins>
  ...

The use of the immediateChangeEventsPlugin will ensure that changes of the UI component are propagated to the model quickly and not just after the field looses focus. If you have more complex requirements, a bind plugin might be insufficient, so that you have to synchronize the model and the view using custom ActionScript code.

If you attach the style class collection-status-filters to the outermost container in your field set, you might find it easier to achieve a visual style that matches that of the predefined filters.

Use the addItemsPlugin to add your custom filter to the Studio Library filter section. The component to configure is the SearchFilters class.

<editor:studioPlugin>
  <ui:rules>
    <editor:searchFilters>
      <plugins>
        <ui:addItemsPlugin>
          <ui:items>
            <foo:FooFilterFieldset/>
          </ui:items>
        </ui:addItemsPlugin>
      </plugins>
    </editor:searchFilters>
  </ui:rules>
</editor:studioPlugin>

You can also open the library in a certain filter state, for example from a button in the favorites toolbar. To that end, the showCollectionViewAction provides a property filters that can take SearchFilterState objects, which are configured using the <searchFilterState> element in EXML. So that the action can configure the correct filter, the filterId attribute must be given, matching the item id of the configured filter fieldset. Additionally, any number of additional attributes may be configured for the <searchFilterState> element using the exml:untyped XML namespace. The names and values of the attributes are exactly the property names and values of the state bean used by the filter set.

<editor:studioPlugin>
  <ui:rules>
    <editor:favoritesToolbar>
      <plugins>
        <ui:addItemsPlugin>
          <ui:items>
            <button ...>
              <baseAction>
                <editor:showCollectionViewAction
                        contentType="CMArticle">
                  <editor:filters>
                    <editor:searchFilterState
                            xmlns:untyped="exml:untyped"
                            filterId="fooFilter"
                            untyped:foo="{1}"/>
                  </editor:filters>
                </editor:showCollectionViewAction>
              </baseAction>
            </button>
          </ui:items>
        </ui:addItemsPlugin>
      </plugins>
    </editor:favoritesToolbar>
  </ui:rules>
</editor:studioPlugin>

If you prefer a type-safe configuration, you can also define an EXML subclass of SearchFilterState that declares the parameters explicitly.