File

projects/storefrontlib/cms-components/product/product-list/product-facet-navigation/product-facet-navigation.component.ts

Metadata

changeDetection ChangeDetectionStrategy.OnPush
selector cx-product-facet-navigation
templateUrl ./product-facet-navigation.component.html

Index

Properties
Methods
Accessors

Constructor

constructor(breakpointService: BreakpointService)
Parameters :
Name Type Optional
breakpointService BreakpointService No

Methods

close
close()
Returns : void
launch
launch()
Returns : void

Properties

Protected CLOSE_DELAY
Type : number
Default value : 300

We delay the removal of DOM so that animations can finish playing before the DOM is removed. Removing the DOM, as hidding is not enough to stop elements to be focused.

iconTypes
Default value : ICON_TYPE
isActive$
Default value : this.open$.pipe( // deffer emitting a new value to the next micro-task to ensure the active class is // applied after the DOM is created observeOn(asapScheduler) )

Emits the active state that indicates whether the facet list is activated. Activation is related to the css, so that a animation or transition can visualize opening/closing the list (i.e. dialog).

isOpen$
Type : Observable<boolean>
Default value : this.breakpointService.breakpoint$.pipe( // deffer emitting a new value to the next micro-task to ensure that the `hasTrigger` // method represents the actual UI state. observeOn(asapScheduler), switchMap(() => (this.hasTrigger ? this.open$ : of(true))), delayWhen((launched) => interval(launched ? 0 : this.CLOSE_DELAY)) )

Emits the open state that indicates whether the facet list should be rendered. This is either done instantly, or after the user triggers this by using the trigger button. This driven by the visiibility of the trigger, so that the CSS drives the behaviour. This can differ per breakpoint.

There's a configurable delay for the closed state, so that the DOM is not removed before some CSS animations are done.

Protected open$
Default value : new BehaviorSubject(false)
trigger
Type : ElementRef<HTMLElement>
Decorators :
@ViewChild('trigger')

Used to open the facet navigation in a dialog. The usage of the dialog depends on the availability of the trigger element, which is driven by CSS.

The reference is also used to refocus the trigger after the dialog is closed.

Accessors

hasTrigger
gethasTrigger()

Indicates that the facet navigation should be open explicitely by a trigger. This is fully controlled by CSS, where the trigger button can be hidden (display:none) for certain screen sizes.

import {
  ChangeDetectionStrategy,
  Component,
  ElementRef,
  ViewChild,
} from '@angular/core';
import { asapScheduler, BehaviorSubject, interval, Observable, of } from 'rxjs';
import { delayWhen, observeOn, switchMap } from 'rxjs/operators';
import { ICON_TYPE } from '../../../../cms-components/misc/icon/icon.model';
import { BreakpointService } from '../../../../layout/breakpoint/breakpoint.service';

@Component({
  selector: 'cx-product-facet-navigation',
  templateUrl: './product-facet-navigation.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProductFacetNavigationComponent {
  iconTypes = ICON_TYPE;

  /**
   * We delay the removal of DOM so that animations can finish playing before the
   * DOM is removed. Removing the DOM, as hidding is not enough to stop elements
   * to be focused.
   */
  protected CLOSE_DELAY = 300;

  /**
   * Used to open the facet navigation in a dialog. The usage of the dialog depends
   * on the availability of the trigger element, which is driven by CSS.
   *
   * The reference is also used to refocus the trigger after the dialog is closed.
   */
  @ViewChild('trigger') trigger: ElementRef<HTMLElement>;

  protected open$ = new BehaviorSubject(false);

  /**
   * Emits the open state that indicates whether the facet list should be rendered.
   * This is either done instantly, or after the user triggers this by using the trigger
   * button. This driven by the visiibility of the trigger, so that the CSS drives
   * the behaviour. This can differ per breakpoint.
   *
   * There's a configurable delay for the closed state, so that the DOM is not removed
   * before some CSS animations are done.
   */
  isOpen$: Observable<boolean> = this.breakpointService.breakpoint$.pipe(
    // deffer emitting a new value to the next micro-task to ensure that the `hasTrigger`
    // method represents the actual UI state.
    observeOn(asapScheduler),
    switchMap(() => (this.hasTrigger ? this.open$ : of(true))),
    delayWhen((launched) => interval(launched ? 0 : this.CLOSE_DELAY))
  );

  /**
   * Emits the active state that indicates whether the facet list is activated. Activation
   * is related to the css, so that a animation or transition can visualize opening/closing
   * the list (i.e. dialog).
   */
  isActive$ = this.open$.pipe(
    // deffer emitting a new value to the next micro-task to ensure the active class is
    //  applied after the DOM is created
    observeOn(asapScheduler)
  );

  constructor(protected breakpointService: BreakpointService) {}

  launch() {
    this.open$.next(true);
  }

  close() {
    this.open$.next(false);
    this.trigger.nativeElement.focus();
  }

  /**
   * Indicates that the facet navigation should be open explicitely by a trigger.
   * This is fully controlled by CSS, where the trigger button can be hidden
   * (display:none) for certain screen sizes.
   */
  get hasTrigger() {
    return this.trigger.nativeElement.offsetParent !== null;
  }
}
<button
  #trigger
  class="btn btn-action btn-block dialog-trigger"
  (click)="launch()"
>
  <cx-icon [type]="iconTypes.FILTER"></cx-icon>
  {{ 'productList.filterBy.label' | cxTranslate }}
</button>

<cx-active-facets></cx-active-facets>

<cx-facet-list
  *ngIf="isOpen$ | async"
  [isDialog]="hasTrigger"
  (closeList)="close()"
  [class.active]="isActive$ | async"
  [class.dialog]="hasTrigger"
></cx-facet-list>
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""