File

projects/storefrontlib/shared/components/item-counter/item-counter.component.ts

Description

Provides a UI to manage the count of the quantity, typically by using increase and decrease functionality. The item counter expects an input FormControl so that the state of the control can be managed outside of this component.

Implements

OnInit OnDestroy

Metadata

selector cx-item-counter
templateUrl ./item-counter.component.html

Index

Properties
Methods
Inputs
HostListeners

Inputs

allowZero
Type : boolean
Default value : false

Indicates that the input can be manually set to zero, despite the fact that the input controls will be limited to the minimum. The zero value can be used to remove an item.

control
Type : FormControl

Holds the value of the counter, the state of the FormControl can be managed outside of the item counter.

max
Type : number

This can be used in case an item has a maximum order quantity.

min
Type : number
Default value : 1

This can be used in case an item has a minmum order quantity.

readonly
Type : boolean
Default value : false

In readonly mode the item counter will only be shown as a label, the form controls are not rendered. Please not that readonly is different from the disabled form state.

step
Type : number
Default value : 1

The step is used to increment the count. It is supposed to be a positive integer or float.

HostListeners

click
click()

Methods

decrement
decrement()
Returns : void
Private getValidCount
getValidCount(value: number)

Validate that the given value is in between the min and max value. If the value is out of the min/max range, it will be altered. If allowZero is set to true, the 0 value is ignored.

Parameters :
Name Type Optional
value number No
Returns : number
handleClick
handleClick()
Decorators :
@HostListener('click')
Returns : void
increment
increment()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void

Properties

allowZero
Default value : false
Decorators :
@Input()

Indicates that the input can be manually set to zero, despite the fact that the input controls will be limited to the minimum. The zero value can be used to remove an item.

control
Type : FormControl
Decorators :
@Input()

Holds the value of the counter, the state of the FormControl can be managed outside of the item counter.

Private input
Type : ElementRef<HTMLInputElement>
Decorators :
@ViewChild('qty')
max
Type : number
Decorators :
@Input()

This can be used in case an item has a maximum order quantity.

min
Type : number
Default value : 1
Decorators :
@Input()

This can be used in case an item has a minmum order quantity.

readonly
Default value : false
Decorators :
@HostBinding('class.readonly')
@Input()

In readonly mode the item counter will only be shown as a label, the form controls are not rendered. Please not that readonly is different from the disabled form state.

step
Type : number
Default value : 1
Decorators :
@Input()

The step is used to increment the count. It is supposed to be a positive integer or float.

Private sub
Type : Subscription

Subscription responsible for auto-correcting control's value when it's invalid.

import {
  Component,
  ElementRef,
  HostBinding,
  HostListener,
  Input,
  OnDestroy,
  OnInit,
  ViewChild,
} from '@angular/core';
import { FormControl } from '@angular/forms';
import { Subscription } from 'rxjs';
import { startWith } from 'rxjs/operators';

/**
 * Provides a UI to manage the count of the quantity, typically by using
 * increase and decrease functionality. The item counter expects an input `FormControl`
 * so that the state of the control can be managed outside of this component.
 */
@Component({
  selector: 'cx-item-counter',
  templateUrl: './item-counter.component.html',
  // do not use OnPush change detection strategy as we would not
  // get updates of other form control state (disabled). We want to have a
  // disabled state in order to ensure that the control cannot be used while
  // the cart is updated.
})
export class ItemCounterComponent implements OnInit, OnDestroy {
  /**
   * Holds the value of the counter, the state of the `FormControl`
   * can be managed outside of the item counter.
   */
  @Input() control: FormControl;

  /**
   * This can be used in case an item has a minmum order quantity.
   * @default 1
   */
  @Input() min = 1;

  /**
   * This can be used in case an item has a maximum order quantity.
   */
  @Input() max: number;

  /**
   * The step is used to increment the count. It is supposed to be a
   * positive integer or float.
   * @default 1
   */
  @Input() step = 1;

  /**
   * Indicates that the input can be manually set to zero,
   * despite the fact that the input controls will be limited to
   * the minimum. The zero value can be used to remove an item.
   */
  @Input() allowZero = false;

  /**
   * In readonly mode the item counter will only be shown as a label,
   * the form controls are not rendered.
   * Please not that readonly is different from the `disabled` form state.
   * @default false
   */
  @HostBinding('class.readonly') @Input() readonly = false;

  @ViewChild('qty') private input: ElementRef<HTMLInputElement>;

  /**
   * Subscription responsible for auto-correcting control's value when it's invalid.
   */
  private sub: Subscription;

  @HostListener('click') handleClick() {
    this.input.nativeElement.focus();
  }

  ngOnInit() {
    this.sub = this.control.valueChanges
      .pipe(startWith(this.control.value))
      .subscribe((value) =>
        this.control.setValue(this.getValidCount(value), { emitEvent: false })
      );
  }

  ngOnDestroy() {
    if (this.sub) {
      this.sub.unsubscribe();
    }
  }

  increment() {
    // it's too early to use the `stepUp` and `stepDown` API...
    // let's wait for FF: https://caniuse.com/#search=stepUp
    this.control.setValue(this.control.value + this.step);
    this.control.markAsDirty();
  }

  decrement() {
    this.control.setValue(this.control.value - this.step);
    this.control.markAsDirty();
  }

  /**
   * Validate that the given value is in between
   * the `min` and `max` value. If the value is out
   * of  the min/max range, it will be altered.
   * If `allowZero` is set to true, the 0 value is ignored.
   *
   */
  private getValidCount(value: number) {
    if (value < this.min && !(value === 0 && this.allowZero)) {
      value = this.min;
    }
    if (this.max && value > this.max) {
      value = this.max;
    }
    return value;
  }
}
<button
  type="button"
  (click)="decrement()"
  [disabled]="control.disabled || control.value <= min"
  [tabindex]="control.disabled || control.value <= min ? -1 : 0"
  attr.aria-label="{{ 'itemCounter.removeOne' | cxTranslate }}"
>
  -
</button>
<input
  #qty
  type="number"
  [min]="min"
  [max]="max"
  [step]="step"
  [readonly]="readonly"
  [tabindex]="readonly ? -1 : 0"
  [formControl]="control"
  attr.aria-label="{{ 'itemCounter.quantity' | cxTranslate }}"
/>
<button
  type="button"
  (click)="increment()"
  [disabled]="control.disabled || control.value >= max"
  tabindex="0"
  attr.aria-label="{{ 'itemCounter.addOneMore' | cxTranslate }}"
>
  +
</button>
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""