API Reference / Angular InstantSearch Widgets / ais-refinement-list
Apr. 24, 2019

ais-refinement-list

You are reading the documentation for Angular InstantSearch v3, which is in beta. You can find the v2 documentation here.

Widget signature
<ais-refinement-list
  attribute="string"

  // Optional parameters
  operator="or|and"
  [limit]="number"
  [showMoreLimit]="number"
  showMoreLabel="string"
  showLessLabel="string"
  [searchable]="boolean"
  searchPlaceholder="string"
  [sortBy]="string[]|function"
  [autoHideContainer]="boolean"
  [transformItems]="function"
></ais-refinement-list>

About this widget #

The ais-refinement-list component displays a list that let the end user choose multiple values for a specific facet.

Requirements#

The attribute passed to the attribute prop must be present in “attributes for faceting” on the Algolia dashboard or configured as attributesForFaceting via a set settings call to the Algolia API.

If you are using the searchable prop, you’ll also need to make the attribute searchable using the dashboard or using the API.

Examples #

Edit
1
<ais-refinement-list attribute="categories"></ais-refinement-list>

Props #

attribute #
type: string
Required

The name of the attribute in the record.

Edit
1
2
3
<ais-refinement-list
  attribute="categories"
></ais-refinement-list>
operator #
type: string
default: or|and
Optional

How to apply refinements.

Edit
1
2
3
4
<ais-refinement-list
  // ...
  operator="and"
></ais-refinement-list>
limit #
type: number
default: 10
Optional

The minimum number of items to diplayed.

Edit
1
2
3
4
<ais-refinement-list
  // ...
  [limit]="5"
></ais-refinement-list>
showMoreLimit #
type: number
Optional

The maximum number of items to displayed when the list is showing more items.

Edit
1
2
3
4
<ais-refinement-list
  // ...
  [showMoreLimit]="20"
></ais-refinement-list>
showMoreLabel #
type: string
default: Show more
Optional

Label of the “Show more” button.

Edit
1
2
3
4
<ais-refinement-list
  // ...
  showMoreLabel="See more"
></ais-refinement-list>
showLessLabel #
type: string
default: Show less
Optional

Label of the show less button.

Edit
1
2
3
4
<ais-refinement-list
  // ...
  showLessLabel="See less"
></ais-refinement-list>
searchable #
type: boolean
default: false
Optional

You should set it to true if the component should display an input to search for facet values. To make this feature work, you need to make the attribute searchable using the API or the dashboard.

Edit
1
2
3
4
<ais-refinement-list
  // ...
  [searchable]="true"
></ais-refinement-list>
searchPlaceholder #
type: string
default: Search here...
Optional

Label for the placeholder of the search box.

Edit
1
2
3
4
<ais-refinement-list
  // ...
  searchPlaceholder="Search for brand..."
></ais-refinement-list>
sortBy #
type: string[]|function
default: ["isRefined", "count:desc", "name:asc"]
Optional

How to sort refinements. Must be one or more of the following strings:

  • "count:asc"
  • "count:desc"
  • "name:asc"
  • "name:desc"
  • "isRefined"

It’s also possible to give a function, which must have the same signature than the JavaScript Array.sort function.

Edit
1
2
3
4
<ais-refinement-list
  // ...
  [sortBy]="['isRefined', 'name:asc']"
></ais-refinement-list>
autoHideContainer #
type: boolean
Optional

Hides the refinement list if there’s no item to display.

Edit
1
2
3
4
<ais-refinement-list
  // ...
  [autoHideContainer]="true"
></ais-refinement-list>
transformItems #
type: function
default: x => x
Optional

A function which receives the items, which are called before displaying them. Should return a new array with the same shape as the original array. Useful for mapping over the items to transform, remove or reorder them.

Edit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Component({
  template: `
    <ais-refinement-list
      // ...
      [transformItems]="transformItems"
    ></ais-refinement-list>
  `,
})
export class AppComponent {
  transformItems(items) {
    return items.map(item => ({
      ...item,
      highlighted: item.highlighted.toUpperCase(),
    }));
  }
}

Customize the UI - connectRefinementList#

If you want to create your own UI of the ais-refinement-list widget, you can combine the connectRefinementList connector with the BaseWidget class.

1. Extend the BaseWidget class#

First of all, you will need to write some boilerplate code in order to initialize correctly the BaseWidget class. This happens in the constructor() of your class extending the BaseWidget class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { Component, Inject, forwardRef } from '@angular/core';
import { BaseWidget, NgAisInstantSearch } from 'angular-instantsearch';

@Component({
  selector: 'app-refinement-list',
  template: '<p>It works!</p>'
})
export class RefinementList extends BaseWidget {
  constructor(
    @Inject(forwardRef(() => NgAisInstantSearch))
    public instantSearchParent
  ) {
    super('RefinementList');
  }
}

There are a couple of things happening in this boilerplate:

  • we create a RefinementList class extending BaseWidget
  • we reference the <ais-instantsearch> parent component instance on the RefinementList widget class
  • we set app-refinement-list as a selector, so we can use our component as <app-refinement-list></app-refinement-list>

2. Connect your custom widget#

The BaseWidget class has a method called createWidget() which takes two arguments: the connector to use and an object of options (instance options) for this connector. We call this method at ngOnInit. This component now implements OnInit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { Component, Inject, forwardRef } from '@angular/core';
import { BaseWidget, NgAisInstantSearch } from 'angular-instantsearch';
import { connectRefinementList } from 'instantsearch.js/es/connectors';

@Component({
  selector: 'app-refinement-list',
  template: '<p>It works!</p>'
})
export class RefinementList extends BaseWidget {
  public state: {
    // render options
  };
  constructor(
    @Inject(forwardRef(() => NgAisInstantSearch))
    public instantSearchParent
  ) {
    super('RefinementList');
  }
  ngOnInit() {
    this.createWidget(connectRefinementList, {
      // instance options
      attribute: 'brands',
    });
    super.ngOnInit();
  }
}

3. Render from the state#

Your component instance has access to a this.state property which holds the rendering options of the widget.

public state: {
  items: object[];
  refine: Function;
  createURL: Function;
  isFromSearch: boolean;
  searchForItems: Function;
  isShowingMore: boolean;
  canToggleShowMore: boolean;
  toggleShowMore: Function;
  widgetParams: object;
}
1
2
3
4
5
<label *ngFor="let item of state.items">
  <input type="checkbox"
         (click)="state.refine(item.value)"
         [checked]="item.isRefined" > {{ item.label }} ({{ item.count }})
</label>

Rendering options #

items #
type: object[]

The list of refinement values returned from the Algolia API.

Each object has the following properties:

  • value: string: the value of the item
  • label: string: the label of the item
  • count: number: the number of results that match the item
  • isRefined: boolean: whether the refinement is applied
refine #
type: function

Toggles a refinement.

createURL #
type: function

Generates a URL for the corresponding search state.

isFromSearch #
type: boolean

Whether the items prop contains facet values from the global search or from the search inside the items.

searchForItems #
type: function

Triggers a search inside items values.

To make this feature work, you need to make the attribute searchable using the dashboard or using the searchable modifier of attributesForFaceting with the API.

isShowingMore #
type: boolean

Whether the menu is displaying all the menu items.

canToggleShowMore #
type: boolean

Whether the “Show more” button can be activated (if there are enough items to display and not already displaying more than the limit).

toggleShowMore #
type: function

Toggles the number of displayed values between limit and showMoreLimit.

widgetParams #
type: object

All original widget options forwarded to the render function.

Instance options #

attribute #
type: string
Required

The name of the attribute in the records.

operator #
type: string ("or"|"and")
default: "or"
Optional

How to apply refinements.

  • "or": apply an OR between all selected values
  • "and": apply an AND between all selected values
limit #
type: number
default: 10
Optional

How many facet values to retrieve.

showMoreLimit #
type: number
Optional

The maximum number of items to display if the widget is showing more items. Needs to be bigger than the limit parameter.

escapeFacetValues #
type: boolean
default: true
Optional

When true, escapes the facet values that are returned from Algolia. In this case, the surrounding tags are always mark.

sortBy #
type: string[]|function
default: ["isRefined","count:desc","name:asc"]
Optional

How to sort refinements. Must be one or more of the following strings:

  • "count:asc"
  • "count:desc"
  • "name:asc"
  • "name:desc"
  • "isRefined"

It’s also possible to give a function, which receives items two by two, like JavaScript’s Array.sort.

transformItems #
type: function
Optional

A function to transform the items passed to the templates.

Full example#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import { Component, Inject, forwardRef } from '@angular/core';
import { BaseWidget, NgAisInstantSearch } from 'angular-instantsearch';
import { connectRefinementList } from 'instantsearch.js/es/connectors';

@Component({
  selector: 'app-refinement-list',
  template: `
<label *ngFor="let item of state.items">
  <input type="checkbox"
         (click)="state.refine(item.value)"
         [checked]="item.isRefined" > {{ item.label }} ({{ item.count }})
</label>
`
})
export class RefinementList extends BaseWidget {
  public state: {
     items: object[];
     refine: Function;
     createURL: Function;
     isFromSearch: boolean;
     searchForItems: Function;
     isShowingMore: boolean;
     canToggleShowMore: boolean;
     toggleShowMore: Function;
     widgetParams: object;
  };
  constructor(
    @Inject(forwardRef(() => NgAisInstantSearch))
    public instantSearchParent
  ) {
    super('RefinementList');
  }
  ngOnInit() {
    this.createWidget(connectRefinementList, {
      // instance options
      attribute: 'brands',
    });
    super.ngOnInit();
  }
}

HTML output#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<div class="ais-RefinementList">
  <div class="ais-RefinementList-searchBox">
    <!-- SearchBox widget here -->
  </div>
  <ul class="ais-RefinementList-list">
    <li class="ais-RefinementList-item ais-RefinementList-item--selected">
      <label class="ais-RefinementList-label">
        <input class="ais-RefinementList-checkbox" type="checkbox" value="Insignia™" checked />
        <span class="ais-RefinementList-labelText">Insignia™</span>
        <span class="ais-RefinementList-count">746</span>
      </label>
    </li>
    <li class="ais-RefinementList-item">
      <label class="ais-RefinementList-label">
        <input class="ais-RefinementList-checkbox" type="checkbox" value="Samsung">
        <span class="ais-RefinementList-labelText">Samsung</span>
        <span class="ais-RefinementList-count">633</span>
      </label>
    </li>
  </ul>
  <button class="ais-RefinementList-showMore">Show more</button>
</div>

Did you find this page helpful?