19 KiB
Added, Status, Last reviewed
Added | Status | Last reviewed |
---|---|---|
v2.3.0 | Active | 2018-04-16 |
Search Filter component
Represents a main container component for custom search and faceted search settings.
Basic usage
<adf-search-filter #settings></adf-search-filter>
Details
The component is based on dynamically created widgets to modify the resulting query and options, and the Search Query Builder service` to build and execute the search queries.
Before you begin with customizations, check also the following articles:
Configuration
The configuration should be provided via the search
entry in the app.config.json
file.
Below is an example configuration:
{
"search": {
"filterQueries": [
{ "query": "TYPE:'cm:folder' OR TYPE:'cm:content'" },
{ "query": "NOT cm:creator:System" }
],
"facetFields": [
{ "field": "content.mimetype", "mincount": 1, "label": "Type" },
{ "field": "content.size", "mincount": 1, "label": "Size" },
{ "field": "creator", "mincount": 1, "label": "Creator" },
{ "field": "modifier", "mincount": 1, "label": "Modifier" }
],
"facetQueries": {
"label": "My facet queries",
"pageSize": 4,
"queries": [
{ "query": "created:2018", "label": "Created This Year" },
{ "query": "content.mimetype", "label": "Type" },
{ "query": "content.size:[0 TO 10240]", "label": "Size: xtra small"},
{ "query": "content.size:[10240 TO 102400]", "label": "Size: small"},
{ "query": "content.size:[102400 TO 1048576]", "label": "Size: medium" },
{ "query": "content.size:[1048576 TO 16777216]", "label": "Size: large" },
{ "query": "content.size:[16777216 TO 134217728]", "label": "Size: xtra large" },
{ "query": "content.size:[134217728 TO MAX]", "label": "Size: XX large" }
]
},
"categories": [
{
"id": "queryName",
"name": "Name",
"enabled": true,
"expanded": true,
"component": {
"selector": "adf-search-text",
"settings": {
"pattern": "cm:name:'(.*?)'",
"field": "cm:name",
"placeholder": "Enter the name"
}
}
}
]
}
}
Please refer to the schema.json to get more details on available settings, values and formats.
Extra fields and filter queries
You can explicitly define the include
section for the query from within the application configuration file.
{
"search": {
"include": ["path", "allowableOperations"]
}
}
In addition, it is also possible to provide a set of queries that are always executed alongside user-defined settings:
{
"search": {
"filterQueries": [
{ "query": "TYPE:'cm:folder' OR TYPE:'cm:content'" },
{ "query": "NOT cm:creator:System" }
]
}
}
Note that the entries of the filterQueries
array are joined using the AND
operator.
Categories
The Search Settings component and Query Builder require a categories
section provided within the configuration.
Categories are needed to build widgets so that users can modify the search query at runtime. Every Category can be represented by a single Angular component, which can be either a simple one or a composite one.
export interface SearchCategory {
id: string;
name: string;
enabled: boolean;
expanded: boolean;
component: {
selector: string;
settings: SearchWidgetSettings;
};
}
The interface above also describes entries in the search.query.categories
section for the app.config.json
file.
Important note: you need at least one category field to be provided in order to execute the query, so that filters and selected facets are applied.
Settings
Every use case will have a different set of settings. For example Number editors may parse minimum and maximum values, while Text editors can support value formats or length constraints.
You can use component.settings
to pass any information to your custom widget using the
SearchWidgetSettings
interface:
export interface SearchWidgetSettings {
field: string;
[indexer: string]: any;
}
Facet Fields
{
"search": {
"facetFields": [
{ "field": "content.mimetype", "mincount": 1, "label": "Type" },
{ "field": "content.size", "mincount": 1, "label": "Size" },
{ "field": "creator", "mincount": 1, "label": "Creator" },
{ "field": "modifier", "mincount": 1, "label": "Modifier" },
{ "field": "created", "mincount": 1, "label": "Created" }
]
}
}
Every field declared within the facetFields
group is presented by a separate collapsible category at runtime.
By default, users see only top 5 entries. If there are more than 5 entries, the "Show more" button is displayed to allow displaying next block of results.
FacetField Properties
Name | Type | Default | Description |
---|---|---|---|
field | string | This specifies the facet field. | |
mincount | number | 1 | This specifies the minimum count required for a facet field to be included in the response. The default value is 1. |
label | string | This specifies the label to include in place of the facet field. | |
prefix | string | This restricts the possible constraints to only indexed values with a specified prefix. | |
limit | number | Maximum number of results | |
pageSize | number | 5 | Display page size |
offset | number | Offset position |
Facet Queries
Provides a custom category based on admin-defined facet queries.
{
"search": {
"facetQueries": {
"label": "Facet queries",
"pageSize": 5,
"expanded": true,
"queries": [
{ "query": "created:2018", "label": "Created This Year" },
{ "query": "content.mimetype", "label": "Type" },
{ "query": "content.size:[0 TO 10240]", "label": "Size: xtra small"},
{ "query": "content.size:[10240 TO 102400]", "label": "Size: small"},
{ "query": "content.size:[102400 TO 1048576]", "label": "Size: medium" },
{ "query": "content.size:[1048576 TO 16777216]", "label": "Size: large" },
{ "query": "content.size:[16777216 TO 134217728]", "label": "Size: xtra large" },
{ "query": "content.size:[134217728 TO MAX]", "label": "Size: XX large" }
]
}
}
}
The queries declared in the facetQueries
are collected into a single collapsible category.
Only the queries that have 1 or more response entries are displayed at runtime.
Based on the pageSize
value, the component provides a Show more
button to display more items.
You can also provide a custom label
(or i18n resource key) for the resulting collapsible category.
The pageSize
property allows you to define the amount of results to display.
Users will see Show more
or Show less
buttons depending on the result set.
The default page size is 5
, it is going to be used in case you set the value to 0
or omit the value entirely.
Widgets
You can use external application configuration to define a set of Angular components (aka Search Filter Widgets) that provide extra features and/or behaviour for the Search Filter component.
The Search Filter supports the following widgets out of the box:
- Check List (
check-list
) - Date Range (
date-range
) - Number Range (
number-range
) - Radio List (
radio
) - Slider (
slider
) - Text (
text
)
At runtime, ADF uses selector
attribute values to map and create corresponding Angular element.
Check List Widget
Provides you with a list of check-boxes, each backed by a particular query fragment.
You can choose a label
(or i18n resources key) and a value
, alongside the conditional operator
(either AND
or OR
).
{
"search": {
"categories": [
{
"id": "checkList",
"name": "Check List",
"enabled": true,
"component": {
"selector": "check-list",
"pageSize": 5,
"settings": {
"operator": "OR",
"options": [
{ "name": "Folder", "value": "TYPE:'cm:folder'" },
{ "name": "Document", "value": "TYPE:'cm:content'" }
]
}
}
}
]
}
}
If user checks both boxes, the underlying query will get the following fragment:
... (TYPE:'cm:folder' OR TYPE:'cm:content') ...
It is possible to set the size of the page to display items. The default size is 5. If all items fit a single page, then a "Clear all" action button is displayed at the bottom of the widget.
In case there are more than one page three icon buttons will be displayed to allow:
- clear all values
- show more items (if applicable)
- show less items (if applicable)
Date Range Widget
Provides ability to select a range between two Dates based on the particular field
.
{
"search": {
"categories": [
{
"id": "createdDateRange",
"name": "Created Date (range)",
"enabled": true,
"component": {
"selector": "date-range",
"settings": {
"field": "cm:created"
}
}
}
]
}
}
Number Range Widget
Provides ability to select a range between two Numbers based on the particular field
.
{
"search": {
"categories": [
{
"id": "contentSizeRange",
"name": "Content Size (range)",
"enabled": true,
"component": {
"selector": "number-range",
"settings": {
"field": "cm:content.size",
"format": "[{FROM} TO {TO}]"
}
}
}
]
}
}
Widget Settings
Name | Type | Description |
---|---|---|
field | string | Field to to use |
format | string | Value format. Uses string substitution to allow all sorts of range queries. |
Range query format
For more details on the range search format please refer to the "Search for ranges" article.
The widget uses {FROM}
and {TO}
values together with the required target format of the query.
You can use any type of the query pattern, the widget automatically substitutes the values, for example:
"settings": {
"field": "cm:content.size",
"format": "[{FROM} TO {TO}]"
}
The format above may result in the following query at runtime:
cm:content.size:[0 TO 100]
Other format examples:
Format | Example |
---|---|
[{FROM} TO {TO}] |
[0 TO 5] |
<{FROM} TO {TO}] |
<0 TO 5] |
[{FROM} TO {TO}> |
[0 TO 5> |
<{FROM} TO {TO}> |
<0 TO 5> |
Radio List Widget
Provides you with a list of radio-boxes, each backed by a particular query fragment.
The behaviour is very similar to those of the check-list
except radio
allows selecting only one item.
{
"search": {
"categories": [
{
"id": "queryType",
"name": "Type",
"enabled": true,
"component": {
"selector": "radio",
"settings": {
"field": null,
"pageSize": 5,
"options": [
{ "name": "None", "value": "", "default": true },
{ "name": "All", "value": "TYPE:'cm:folder' OR TYPE:'cm:content'" },
{ "name": "Folder", "value": "TYPE:'cm:folder'" },
{ "name": "Document", "value": "TYPE:'cm:content'" }
]
}
}
}
]
}
}
It is possible to set the size of the page to display items. The default size is 5. In case there are more than one page three icon buttons will be displayed to allow:
- show more items (if applicable)
- show less items (if applicable)
Slider Widget
Provides ability to select a numeric range based on min
and max
values in the form of horizontal slider.
{
"search": {
"categories": [
{
"id": "contentSize",
"name": "Content Size",
"enabled": true,
"component": {
"selector": "slider",
"settings": {
"field": "cm:content.size",
"min": 0,
"max": 18,
"step": 1,
"thumbLabel": true
}
}
}
]
}
}
Resetting slider value
Slider widget comes with a Clear
button that allows users to reset selected value to the initial state.
This helps to undo changes for scenarios where minimal value (like 0 or predefined number) still should not be used in a query.
Upon clicking the Clear
button slider will be reset to the min
value or 0
, and underlying fragment is removed from the resulting query.
Text Widget
{
"search": {
"categories": [
{
"id": "queryName",
"name": "Name",
"enabled": true,
"expanded": true,
"component": {
"selector": "text",
"settings": {
"pattern": "cm:name:'(.*?)'",
"field": "cm:name",
"placeholder": "Enter the name"
}
}
}
]
}
}
Important note: you need at least one category field to be provided in order to execute the query, so that filters and selected facets are applied.
Custom Widgets
Implementing custom widget
It is possible to create custom Angular components that display and/or modify resulting search query.
You start creating a Search Filter widget by generating a blank Angular component that implements SearchWidget
interface:
export interface SearchWidget {
id: string;
settings?: SearchWidgetSettings;
context?: SearchQueryBuilderService;
}
Every widget implementation must have an id
, and may also support external settings
.
At runtime, every time a new instance of the widget is created, it also receives a reference to the SearchQueryBuilderService
so that you component can access query related information, events and methods.
@Component({...})
export class MyComponent implements SearchWidget, OnInit {
id: string;
settings: SearchWidgetSettings;
context: SearchQueryBuilderService;
key1: string;
key2: string;
}
Reading external settings
At runtime, ADF provides every Search Filter widget with the settings
instance, based on the JSON data
that administrator has provided for your widget in the external configuration file.
It is your responsibility to parse the settings
property values, convert types or setup defaults.
ADF does not provide any validation of the objects, it only reads from the configuration and passes data to your component instance.
@Component({...})
export class MyComponent implements SearchWidget, OnInit {
id: string;
settings: SearchWidgetSettings;
context: SearchQueryBuilderService;
key1: string;
key2: string;
ngOnInit() {
if (this.settings) {
this.key1 = this.settings['key1'];
this.key2 = this.settings['key2'];
}
}
}
Updating final query
The SearchQueryBuilderService
keeps track on all query fragments populated by widgets
and composes them together alongside other settings when performing a final query.
Every query fragment is stored/retrieved using widget id
.
It is your responsibility to format the query correctly.
Once your value is ready, update the context and run update
method to let other components know the query has been changed:
@Component({...})
export class MyComponent implements SearchWidget, OnInit {
...
onUIChanged() {
this.context.queryFragments[this.id] = `some query`;
this.context.update();
}
}
When executed, your fragment will be injected into the resulting query based on the category order in the application configuration file.
... AND (widget1) AND (some query) AND (widget2) AND ...
Registering custom widget
You can register your own Widgets by utilizing the SearchFilterService
service:
import { MyComponent } from './my-component.ts'
@Component({...})
export class MyAppOrComponent {
constructor(searchFilterService: SearchFilterService) {
searchFilterService.widgets['my-widget'] = MyComponent;
}
}
That allows you to declare your widget in the external configuration and pass custom attributes in case your component supports them:
{
"search": {
"categories": [
{
"id": "someUniqueId",
"name": "String or i18n key",
"enabled": true,
"component": {
"selector": "my-widget",
"settings": {
"key1": "value1",
"key2": "value2",
"keyN": "valueN"
}
}
}
]
}
}