Skip to main content
Skip table of contents

Working with filters

Learning objectives

  • Become familiar with how to use filters to select specific items from lists.

Key concepts

There are two main requirements for using a filter pattern on a list.

The implementation of these two components results in functionality similar to the following image.

Implementation of a filter file and filter control

At the top, you see filters for contacts, companies, and users. When clicked, these filters display the appropriate class, and are driven by the subjects and filters in the filter files.

Below the filters, is the text filtering area, which provides text searching capabilities and is driven by the text property of the filter.

To the right, are filter chips, which let you filter on specific conditions as defined in filter fields. In the upper right of the control, are the Save Filter 

, Select favorites 
, and Manage filters and lists
 
buttons.

Lists are named saved lists of user-selected items. This lesson focuses on filters, which can be thought of as dynamic lists. 


In preparation for the learning activities in this lesson, make sure that your files include the following code. If not, copy this code into your files before continuing.

training:Contact.portal

XML
<Portal caption="idsa.training.portal.Contact.caption">
   <Tool name="toolNotifications" caption="ids.notifications" icon="icon:notifications" event="setSidebar" parameter="NOTIFICATIONS"/>   
   <WorkspaceRef name="refSandbox" workspace="training:Sandbox"/>
   <WorkspaceRef name="refHome" workspace="mda:Home"/>
   <WorkspaceRef name="refContacts" workspace="mda:Contacts"/>
   <Drawer event="setSidebar" name="refNotifications" portlet="mda:NotificationDrawer"/>
</Portal>


training:Sandbox.workspace

XML
<Workspace caption="idsa.training.workspace.Sandbox.caption" icon="icon:attach_money">
   <Page name="page">
      <Tab caption="IDS_DETAIL" layout="cols:3 fluid:true" name="spltDetail" type="grid">
         <PortletRef name="training_EntityList_portlet" portlet="training:EntityList"/>
         <PortletRef name="training_EntityDetail_portlet" portlet="training:EntityDetail"/>
         <PortletRef name="aflBus" portlet="app/bus"/>
      </Tab>
   </Page>
</Workspace>


training:EntityList.portlet

XML
<Portlet context="EntityId">
   <Script><![CDATA[(context-form-source (this'view) "EntityId" "training_EntityList_layout")]]></Script>
   <Composite name="composite">
      <LayoutRef layout="training:EntityList" name="training_EntityList_layout"/>
   </Composite>
</Portlet>


training:EntityList.layout

XML
<Layout class="Entity">
   <UIActions>
      <UIAction event="sysProperties">
         <Popup association="tblEntityList" edit="true" screen="training:mda:EntityProperties"/>
      </UIAction>
   </UIActions>
   <Composite name="composite">
      <Table caption="idsa.training.layout.EntityList.caption" name="tblEntityList" rows="(@)">
         <Menu name="mnuRightClick">
            <Item caption="ids.edit2" event="sysProperties" icon="edit" name="mitProperties"/>
            <Item event="sysRemove" name="deleteItem"/>
         </Menu>
         <Column name="colType" caption="idsa.training.layout.EntityList.type" icons="type iconDefault"/>
         <Column name="colIcon" caption="idsa.training.layout.EntityList.icon" icons="(image . image)(data . mimeData)(type . mimeType)" texts="initial"/>
         <Column name="colName" caption="idsa.training.layout.EntityList.name" length="100" values="fullName"/>
      </Table>
   </Composite>
</Layout>


training:EntityDetail.portlet

XML
<Portlet context="EntityId">
   <Script><![CDATA[(context-form-target (this'view) "EntityId" "training_EntityDetail_layout" ())]]></Script>
   <Composite name="composite">
      <LayoutRef layout="training:EntityDetail" name="training_EntityDetail_layout"/>
   </Composite>
</Portlet>


EntityDetail.layout

XML
<Layout class="Entity" caption="idsa.training.layout.EntityDetail.caption">
   <Composite name="composite">
      <Label caption="firstName" head="true" name="lblFirstName"/>
      <Label caption="lastName" name="lblLastName"/>
   </Composite>
</Layout>


training:mda:EntityProperties.dialog

XML
<Dialog caption="ids.caption.editPopup">
   <Composite cols="2" name="composite">
      <LayoutRef layout="mda:EntityPropertyDashboard" head="true" name="mda_EntityPropertyDashboard_layout"/>
      <Switch caption="ids.detail" head="true" name="grpDetailLayout" span="2" value="mda_EntityPropertyDashboard_layout">
         <Composite case="UserPerson" name="compUser">
            <LayoutRef association="mda_EntityPropertyDashboard_layout" layout="mda:UserPersonEditDetail" head="true" name="mda_UserPersonEditDetail_layout"/>
         </Composite>
         <Composite case="Person" name="compPerson">
            <LayoutRef association="mda_EntityPropertyDashboard_layout" layout="mda:PersonEditDetail" head="true" name="mda_PersonEditDetail_layout"/>
         </Composite>
         <Composite case="Company" name="compOrg">
            <LayoutRef association="mda_EntityPropertyDashboard_layout" layout="mda:CompanyEditDetail" head="true" name="mda_CompanyEditDetail_layout"/>
         </Composite>
      </Switch>
      <LayoutRef association="mda_EntityPropertyDashboard_layout" head="true" layout="mda:EntityAuditFields" name="mda_EntityAuditFields_layout" span="2"/>
   </Composite>
   <Actions layout="mda:PopupButtons" name="mda_PopupButtons_layout"/>
</Dialog>


idsa.training.en.strings

CODE
idsa.training.layout.EntityDetail.caption=Entity Detail
idsa.training.layout.EntityList.caption=Entity List
idsa.training.layout.EntityList.icon=Icon
idsa.training.layout.EntityList.name=Name
idsa.training.layout.EntityList.type=Type
idsa.training.portal.Contact.caption=My Training Application
idsa.training.workspace.Sandbox.caption=Sandbox

Each class has a filter file, with a .filter extenstion, that specifies the attributes you can filter on. This file is applied to the list controls to provide filtering on the classes to which the control is bound.

Version 9.X

Filter and picker configurations have been greatly simplified in version 9.X. Now, you only need to maintain one filter configuration per class and reuse it where needed. This, along with greatly simplified metadata, makes it easier to understand and maintain filters.

Adding a search layout

Let's add a search layout to the training:EntityList.portlet.

Learning activity

  1. Create a new layout with the name training:EntitySearch.

    training:EntitySearch.layout

    XML
    <Layout class="Entity">
       <Composite name="composite">
          <Filter name="filter"/>
       </Composite>
    </Layout>
  2. Add a reference to this layout in your EntityList.portlet.

    training:EntityList.portlet

    XML
    <Portlet context="EntityId">
       <Script><![CDATA[(context-form-source (this'view) "EntityId" "training_EntityList_layout")]]></Script>
       <Composite name="composite">
          <LayoutRef association="training_EntityList_layout" layout="training:EntitySearch" name="training_EntitySearch_layout" query="true"/>
          <LayoutRef layout="training:EntityList" name="training_EntityList_layout"/>
       </Composite>
    </Portlet>

    In the EntityList.portlet source,  we added a search layout (query="true") and associated it with our training_EntityList_layout. Any criteria set in the search layout is applied to the list layout.

  3. Save your changes, restart the server, re-seed the portal, and refresh your browser. The application should look similar to the following:

  4. Explore by clicking on the filters and filter chips.
    Because the training:EntitySearch.layout is associated with the Entity class, its filter control looks for any filter elements in metadata with a class or base class of Entity, and shows the appropriate saved filters and filter chips. For more information about the end-user capabilities of filters, filter chips, saved filters, and favorites, see "Searching and filtering in NexJ CRM" in end-user documentation. Also, take a minute to learn how filter configuration works.

Usually, the configuration of fields is straightforward and the system displays the appropriate picker for the attribute you want to filter on, regardless of the attribute type (string, date, enumeration, or other). There are some more advanced ways of configuring a field as well, for example, dynamic custom fields.

Example filter field configurations

The following are example filter field configurations for different types of attributes that will display as filter chips.

Primitive attributes

Primitive attributes have types such as string, integer, date, and binary.

Primitive attribute types

To configure a filter field for a primitive attribute, point the association to the attribute. The system then provides an appropriate picker.

XML
<Field association="lastName" caption="IDS_LAST_NAME"/>


Last name filter chip

Enter Last name filter dialog

Date attributes display as an appropriate date picker.

XML
<Field association="lastUpdated" caption="My LastUpdated"/>

My LastUpdated filter chip

Enter My LastUpdated dialog

This also applies to boolean, integer, currency, and other primitive types. The appropriate picker and validation are automatically applied.

Association attributes

Association attributes are also simple to configure. They present a paging-enabled picker of instances of the attribute's type. In this case, the field's association property is set to the name of the association attribute household.

Field's association property set to name of association attribute household

XML
<Field association="household" caption="ids.household" persistent="true"/>

Household filter chip

Select a household dialog

This field displays by default because persistent="true".

Enumeration attributes

Enumeration attributes display the list of enumerated values, in the appropriate language.

XML
<Field association="addrs countryValue" caption="ids.country"/>

Country (English) filter chip
 in English or 
Pays (French) filter chip
 in French.

Select a country dialog in English
 in English or 
Select a pays dialog (French)
 in French.

Notice that we are traversing an association in the model to get to the primitive countryValue.

Adding fields dynamically (poly="true" or flattening)

When you have an intersection table that refers to a value and a type, and you want to dynamically add the types for selection to the filter list, the type is based on either of the following:

  • A class, so the values are records in a database table.
  • An enumeration, so it is a pre-defined list.

The latter use case involves defining a set of fields that are dynamically added to the list. You can configure this dynamic set of fields using the "poly", "type", and "picker" properties.

We illustrate this with two examples:

  • Custom fields, which is based on a type that is another class.
  • EntityDate, which has a type based on an enumeration.

To better understand how custom fields work, take a look at the application user and admin documentation. In a nutshell, custom fields allow you to configure a new attribute for entities at runtime. These fields have a name and a type (text, number, currency, convertible currency, date, and relationship). They are created in the Admin console and must be enabled for an entity type before they display in the UI.

Example 1

This is the custom field model. The following configuration flattens the custom field types and adds them to the list of available filter chips.


XML
<Field association="customFields" case="*" mode="queryField?" picker="mda:CustomFieldType" poly="true" type="type"/>

We need:

Custom field model

  • The association property is set to the Entity'customFields attribute.
  • Type is set to the CustomField'type attribute.
  • Poly="true" - dynamically add to the list and flatten the collection.
  • Picker - the collection for the picker is merged into the flat "Select filter fields" list.

With this type of configuration (with a picker and the poly property set to true), we dynamically and automatically add all of the custom field types to the list. In the following diagram, the highlighted entries are read from the CustomFieldType class and added to the list.  

The highlighted entries are read from the CustomFieldType class and added to the list

Based on the custom field type (date, relationship, or text), the appropriate picker displays automatically. For example:

  • When picking a custom field of the type text, the appropriate dialog displays, including pre-defined quick picks.

    Personal Interest filter chip

    Personal Interest filter dialog


  • When picking a custom field of the type date, a calendar displays.

    Start Date filter chip

    Start date filter dialog


  • When picking a custom field of the type relationship, an entity picker opens.

    Guarantor filter chip

    Entity picker for Guarantor

Example 2

This is the entity date model.

Entity date model

The following configuration adds the filter fields associated with the BIRTHTIME and EDITTIME enumerations to the list.

XML
<Field association="dates" case="*" picker="mda:DateTypeEnum" poly="true" type="dateType"/>

The following figure shows the two filter fields: Birthdate (the caption of the BIRTHTIME enumeration) and Last Update (the caption for the EDITTIME enumeration).

Birthdate and Last Update filter fields

When clicked, the Date field appropriately displays a calendar.

Birthdate filter chip

Calendar for selection of birthdate

Adding a filter

Let's learn how to add a filter.

Learning activity

  1. Create a new filter named training.Entity.filter and add the following contents:

    XML
    <Filter class="Entity">
       <Subject caption="Training Subject" class="Person" name="trainingSubject"/>
       <Field association="ageValue" caption="My AgeValue" case="*" persistent="true"/>
       <Field association="lastUpdated" caption="My LastUpdated" persistent="true"/>
       <Field association="primaryAccounts" caption="My accounts" persistent="true"/>
    </Filter>
    Only one field is used for each association. If you define two associations for lastName with different captions, only one will display in the application. To prevent confusion, ensure that the field associations are unique. 
  2. Restart the server.
    You should see new filter chips because your .filter file merged with all existing fields for Entity.

    New filter chips

  3. In the training portal, click the Manage filters and lists button
    , and click the Add Filter or List button
    .
  4. Select Filter, and add a filter with the name My Persons, using the Training Subject subject area.
    Newly created filter

An additional filter named My Persons is added, as shown in the following figure.

My Persons filter has been added


Filters


JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.