algolia / angular-instantsearch

⚑️Lightning-fast search for Angular apps, by Algolia
https://algolia.com/doc/deprecated/instantsearch/angular/v4/api-reference/instantsearch/
MIT License
261 stars 73 forks source link

ais-range-slider does not works under *ngIf #804

Open Celtian opened 3 years ago

Celtian commented 3 years ago

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:

Haroenv commented 3 years ago

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

Celtian commented 3 years ago

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.

francoischalifour commented 3 years ago

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?

Celtian commented 3 years ago

@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.

francoischalifour commented 3 years ago

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.