API Reference / InstantSearch.js / toggleRefinement
Signature
instantsearch.widgets.toggleRefinement({
  container: string|HTMLElement,
  attribute: string,
  // Optional parameters
  on: boolean|number|string,
  off: boolean|number|string,
  templates: object,
  cssClasses: object,
});

About this widget # A

The toggleRefinement widget provides an on/off filtering feature based on an attribute value.

Requirements#

Ensure that the attribute provided is already declared as an attribute for faceting.

Examples # A

1
2
3
4
5
6
7
instantsearch.widgets.toggleRefinement({
  container: '#toggle-refinement',
  attribute: 'free_shipping',
  templates: {
    labelText: 'Free shipping',
  },
});

Options # A

container #
type: string|HTMLElement
Required

The CSS Selector or HTMLElement to insert the widget into.

1
2
3
4
instantsearch.widgets.toggleRefinement({
  // ...
  container: '#toggle-refinement',
});
attribute #
type: string
Required

The name of the attribute on which apply the refinement.

1
2
3
4
instantsearch.widgets.toggleRefinement({
  // ...
  attribute: 'free_shipping',
});
on #
type: boolean|number|string
default: true
Optional

The value of the refinement to apply on the attribute when checked.

1
2
3
4
instantsearch.widgets.toggleRefinement({
  // ...
  on: false,
});
off #
type: boolean|number|string
Optional

The value of the refinement to apply on the attribute when unchecked.

1
2
3
4
instantsearch.widgets.toggleRefinement({
  // ...
  off: false,
});
templates #
type: object
Optional

The templates to use for the widget.

1
2
3
4
5
6
instantsearch.widgets.toggleRefinement({
  // ...
  templates: {
    // ...
  },
});
cssClasses #
type: object
default: {}
Optional

The CSS classes to override.

  • root: the root element of the widget.
  • label: the label of the toggle.
  • checkbox: the checkbox element of the toggle.
  • labelText: the label text of the toggle.
1
2
3
4
5
6
7
8
9
10
instantsearch.widgets.toggleRefinement({
  // ...
  cssClasses: {
    root: 'MyCustomToggleRefinement',
    label: [
      'MyCustomToggleRefinementLabel',
      'MyCustomToggleRefinementLabel--subclass',
    ],
  },
});

Templates # A

labelText #
type: string|function
Optional

The template to use to customize the label. It exposes:

  • isRefined: boolean: indicates whether the checkbox is checked.
  • count: number: shows the number of results after the refinement was applied.
  • onFacetValue: object: describes the value for the attribute. It contains count (useful to get the raw value of the count).
  • offFacetValue: object: describes the value for the attribute. It contains count (useful to get the raw value of the count).
1
2
3
4
5
6
instantsearch.widgets.toggleRefinement({
  // ...
  templates: {
    labelText: 'Free shipping ({{ count }})',
  },
});

HTML output# A

1
2
3
4
5
6
7
<div class="ais-ToggleRefinement">
  <label class="ais-ToggleRefinement-label">
    <input class="ais-ToggleRefinement-checkbox" type="checkbox" />
    <span class="ais-ToggleRefinement-labelText">Free Shipping</span>
    <span class="ais-ToggleRefinement-count">18,013</span>
  </label>
</div>

Customize the UI with connectToggleRefinement# A

If you want to create your own UI of the toggleRefinement widget, you can use connectors.

It’s a 3-step process:

// 1. Create a render function
const renderToggleRefinement = (renderOptions, isFirstRender) => {
  // Rendering logic
};

// 2. Create the custom widget
const customToggleRefinement = instantsearch.connectors.connectToggleRefinement(
  renderToggleRefinement
);

// 3. Instantiate
search.addWidgets([
  customToggleRefinement({
    // instance params
  })
]);

Create a render function#

This rendering function is called before the first search (init lifecycle step) and each time results come back from Algolia (render lifecycle step).

const renderToggleRefinement = (renderOptions, isFirstRender) => {
  const {
    object value,
    boolean canRefine,
    function refine,
    function sendEvent,
    function createURL,
    object widgetParams,
  } = renderOptions;

  if (isFirstRender) {
    // Do some initial rendering and bind events
  }

  // Render the widget
}

Rendering options #

value #
type: object

The current refinement, with:

  • isRefined: boolean: indicates whether the checkbox is checked.
  • count: number: shows the number of results after the refinement was applied.
  • onFacetValue: object: describes the value for the attribute. It contains count (useful to get the raw value of the count).
  • offFacetValue: object: describes the value for the attribute. It contains count (useful to get the raw value of the count).
1
2
3
4
5
6
7
8
9
10
const renderToggleRefinement = (renderOptions, isFirstRender) => {
  const { value } = renderOptions;

  document.querySelector('#toggle-refinement').innerHTML = `
    <label>
      <input type="checkbox" ${value.isRefined ? 'checked' : ''} />
      Free shipping (${value.count})
    </label>
  `;
};
canRefine #
type: boolean
Required

Indicates if search state can be refined.

1
2
3
4
5
6
const { canRefine } = renderOptions;

if (!canRefine) {
  document.querySelector('#toggle-refinement').innerHTML = '';
  return;
}
refine #
type: function

Updates to the next state by applying the toggle refinement.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const renderToggleRefinement = (renderOptions, isFirstRender) => {
  const { value, refine } = renderOptions;
  const container = document.querySelector('#toggle-refinement');

  if (isFirstRender) {
    const label = document.createElement('label');
    const input = document.createElement('input');
    input.type = 'checkbox';

    input.addEventListener('change', event => {
      refine({ isRefined: !event.target.checked });
    });

    label.appendChild(input);
    label.appendChild(document.createTextNode('Free shipping'));
    container.appendChild(label);
  }

  container.querySelector('input').checked = value.isRefined;
};
sendEvent #
type: (eventType, facetValue) => void

The function to send click events. The click event is automatically sent when refine is called. You can learn more about the insights middleware.

  • eventType: 'click'
  • facetValue: string
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// For example,
sendEvent('click', true);

/*
  A payload like the following will be sent to the `insights` middleware.
  {
    eventType: 'click',
    insightsMethod: 'clickedFilters',
    payload: {
      eventName: 'Filter Applied',
      filters: ['isShippingFree:true'],
      index: '',
    },
    widgetType: 'ais.toggleRefinement',
  }
*/
createURL #
type: function

Generates a URL for the next state.

1
2
3
4
5
6
7
const renderToggleRefinement = (renderOptions, isFirstRender) => {
  const { createURL } = renderOptions;

  document.querySelector('#toggle-refinement').innerHTML = `
    <a href="${createURL()}">Link to the next state</a>
  `;
};
widgetParams #
type: object

All original widget options forwarded to the render function.

1
2
3
4
5
6
7
8
9
10
11
12
13
const renderToggleRefinement = (renderOptions, isFirstRender) => {
  const { widgetParams } = renderOptions;

  widgetParams.container.innerHTML = '...';
};

// ...

search.addWidgets([
  customToggleRefinement({
    container: document.querySelector('#toggle-refinement'),
  })
]);

Create and instantiate the custom widget#

We first create custom widgets from our rendering function, then we instantiate them. When doing that, there are two types of parameters you can give:

  • Instance parameters: they are predefined parameters that you can use to configure the behavior of Algolia.
  • Your own parameters: to make the custom widget generic.

Both instance and custom parameters are available in connector.widgetParams, inside the renderFunction.

const customToggleRefinement = instantsearch.connectors.connectToggleRefinement(
  renderToggleRefinement
);

search.addWidgets([
  customToggleRefinement({
    attribute: string,
    // Optional parameters
    on: boolean|number|string,
    off: boolean|number|string,
  })
]);

Instance options #

attribute #
type: string
Required

The name of the attribute on which to apply the refinement.

1
2
3
customToggleRefinement({
  attribute: 'free_shipping',
});
on #
type: boolean|number|string
default: true
Optional

The value of the refinement to apply on the attribute when checked.

1
2
3
4
customToggleRefinement({
  // ...
  on: false,
});
off #
type: boolean|number|string
Optional

The value of the refinement to apply on the attribute when unchecked.

1
2
3
4
customToggleRefinement({
  // ...
  off: false,
});

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
// Create the render function
const renderToggleRefinement = (renderOptions, isFirstRender) => {
  const { value, refine, widgetParams } = renderOptions;

  if (isFirstRender) {
    const label = document.createElement('label');
    const input = document.createElement('input');
    input.type = 'checkbox';

    const span = document.createElement('span');

    input.addEventListener('change', event => {
      refine({ isRefined: !event.target.checked });
    });

    label.appendChild(input);
    label.appendChild(document.createTextNode('Free shipping'));
    label.appendChild(span);

    widgetParams.container.appendChild(label);
  }

  widgetParams.container.querySelector('input').checked = value.isRefined;
  widgetParams.container.querySelector('span').innerHTML =
    value.count !== null ? ` (${value.count})` : '';
};

// Create the custom widget
const customToggleRefinement = instantsearch.connectors.connectToggleRefinement(
  renderToggleRefinement
);

// Instantiate the custom widget
search.addWidgets([
  customToggleRefinement({
    container: document.querySelector('#toggle-refinement'),
    attribute: 'free_shipping',
  })
]);
Did you find this page helpful?