angular-instantsearch icon indicating copy to clipboard operation
angular-instantsearch copied to clipboard

ais-range-slider does not works under *ngIf

Open Celtian opened this issue 4 years ago • 5 comments

Describe the bug 🐛

Range slider cannot be hidden by *ngIf. I can use display none in some cases. However If i use third-party lib like ngBootstrap with ngAccordion, it does not works because it is using *ngIf internally because it prevents to render large scaled DOM.

To Reproduce 🔍

Steps to reproduce the behavior:

 <ais-range-slider
   *ngIf="someDynamicCondition"
   attribute="listings.price"
   [precision]="0">
</ais-range-slider>

Expected behavior 💭

NgIf can be use like for the other types of filters in your library.

Screenshots 🖥

Console log that shows you the problem: image

Environment:

  • OS: windows
  • Browser chrome
  • algoliasearch: 3
  • angular-instantsearch: 3.0.0-beta.5
  • instantsearch.js: 3
  • @angular/core: 11.1.0
  • @ng-bootstrap/ng-bootstrap: 9.0.1
  • bootstrap: 4.6.0

Celtian avatar Feb 11 '21 12:02 Celtian

could you conditionally show & hide a wrapping container of the slider? Note that when you not render the component, the refinement will likely disappear

Haroenv avatar Feb 11 '21 14:02 Haroenv

Hello @Haroenv ,

it is not working.

see https://ng-bootstrap.github.io/#/components/accordion

<ais-instantsearch [config]="config">
  <ngb-accordion [destroyOnHide]="true">
    <ngb-panel>
      <ng-template ngbPanelHeader let-opened="opened">
        <button ngbPanelToggle class="btn btn-link p-0 w-100 text-decoration-none card-header-custom">
          Button
        </button>
      </ng-template>
      <ng-template ngbPanelContent>
        <ais-range-slider
          attribute="listings.price"
          [precision]="0">
        </ais-range-slider>
      </ng-template>
    </ngb-panel>
  </ngb-accordion>
<ais-instantsearch [config]="config">

It is not working because that component destroys alll components which are not visible.

Another example with switch case is not also working - and it has parent div inside switch case.

<ng-container [ngSwitch]="filter">
  <ng-container *ngSwitchCase="'price'">
      <!-- price must be present in dom otherwise it causes crashes -->
      <div class="px-3 py-2">
        <ais-range-slider
          attribute="listings.price"
          [precision]="0">
        </ais-range-slider>
      </div>
    </ng-container>
 </ng-container>

Thx.

Celtian avatar Feb 11 '21 16:02 Celtian

It is not working because that component destroys alll components which are not visible.

This will likely be a problem with Angular InstantSearch because as @Haroenv mentioned, unmounted components' search state (i.e., search parameters) are ignored by InstantSearch. This means that when users visually toggle the accordion, the search results might change.

Is there a way to tell ngb-accordion to not destroy the component but just to visually hide it?

francoischalifour avatar Feb 15 '21 12:02 francoischalifour

@francoischalifour Yes, luckylly there is. But it is making my DOM deeper and it is decresing my Lighthouse score.

I should be possible either pass arguments directely through "SearchRequestParameters" or from another place in DOM.

Still was not explained why "ais-range-slider" causes crashes and for example "ais-refinement-list" not.

Celtian avatar Feb 15 '21 12:02 Celtian

The error seems to happen because we expect the slider container to exist at first render to create the slider instance.

Since ngb-accordion doesn't mount the InstantSearch slider component, this.sliderContainer is undefined, and therefore this.sliderContainer.nativeElement throws.

francoischalifour avatar Feb 15 '21 13:02 francoischalifour