File

feature-libs/product-configurator/rulebased/components/attribute/types/numeric-input-field/configurator-attribute-numeric-input-field.component.ts

Extends

ConfiguratorAttributeInputFieldComponent

Implements

OnInit OnDestroy

Metadata

changeDetection ChangeDetectionStrategy.OnPush
selector cx-configurator-attribute-numeric-input-field
templateUrl ./configurator-attribute-numeric-input-field.component.html

Index

Properties
Methods
Inputs
Outputs

Constructor

constructor(configAttributeNumericInputFieldService: ConfiguratorAttributeNumericInputFieldService, config: ConfiguratorUISettingsConfig)
Parameters :
Name Type Optional
configAttributeNumericInputFieldService ConfiguratorAttributeNumericInputFieldService No
config ConfiguratorUISettingsConfig No

Inputs

language
Type : string
attribute
Type : Configurator.Attribute
group
Type : string
ownerKey
Type : string
ownerType
Type : CommonConfigurator.OwnerType

Outputs

inputChange
Type : EventEmitter

Methods

Protected getDefaultSettings
getDefaultSettings()
Returns : DefaultSettings
Protected getInstalledLocale
getInstalledLocale(locale: string)
Parameters :
Name Type Optional
locale string No
Returns : string
mustDisplayValidationMessage
mustDisplayValidationMessage()

Do we need to display a validation message

Returns : boolean
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
Protected reportMissingLocaleData
reportMissingLocaleData(lang: string)
Parameters :
Name Type Optional
lang string No
Returns : void
onChange
onChange()
Returns : void
createAriaLabelledBy
createAriaLabelledBy(prefix: string, attributeId: string, valueId?: string, hasQuantity?: boolean)

Creates unique key for attribute 'aria-labelledby'

Parameters :
Name Type Optional
prefix string No
attributeId string No
valueId string Yes
hasQuantity boolean Yes
Returns : string
createAttributeIdForConfigurator
createAttributeIdForConfigurator(currentAttribute: Configurator.Attribute)

Creates unique key for config attribute to be sent to configurator

Parameters :
Name Type Optional
currentAttribute Configurator.Attribute No
Returns : string
createAttributeUiKey
createAttributeUiKey(prefix: string, attributeId: string)

Creates unique key for config attribute on the UI

Parameters :
Name Type Optional Description
prefix string No

for key depending on usage (e.g. uiType, label)

attributeId string No
Returns : string
createAttributeValueIdForConfigurator
createAttributeValueIdForConfigurator(currentAttribute: Configurator.Attribute, value: string)

Creates unique key for config value to be sent to configurator

Parameters :
Name Type Optional
currentAttribute Configurator.Attribute No
value string No
Returns : string
createFocusId
createFocusId(attributeId: string, valueCode: string)

Creates a unique key for focus handling for the given attribute and value

Parameters :
Name Type Optional
attributeId string No
valueCode string No
Returns : string

focus key

createValueUiKey
createValueUiKey(prefix: string, attributeId: string, valueId: string)

Creates unique key for config value on the UI

Parameters :
Name Type Optional Description
prefix string No

for key depending on usage (e.g. uiType, label)

attributeId string No
valueId string No
Returns : string
Protected getAttributeCode
getAttributeCode(attribute: Configurator.Attribute)

Get code from attribute. The code is not a mandatory attribute (since not available for VC flavour), still it is mandatory in the context of CPQ. Calling this method therefore only makes sense when CPQ is active. In case the method is called in the wrong context, an exception will be thrown

Parameters :
Name Type Optional
attribute Configurator.Attribute No
Returns : number

Attribute code

Protected getUiType
getUiType(attribute: Configurator.Attribute)
Parameters :
Name Type Optional
attribute Configurator.Attribute No
Returns : string

Properties

language
Type : string
Decorators :
@Input()
locale
Type : string
numericFormatPattern
Type : string
attribute
Type : Configurator.Attribute
Decorators :
@Input()
attributeInputForm
Default value : new FormControl('')
Protected Readonly FALLBACK_DEBOUNCE_TIME
Type : number
Default value : 500

In case no config is injected, or when the debounce time is not configured at all, this value will be used as fallback.

group
Type : string
Decorators :
@Input()
inputChange
Default value : new EventEmitter<ConfigFormUpdateEvent>()
Decorators :
@Output()
ownerKey
Type : string
Decorators :
@Input()
ownerType
Type : CommonConfigurator.OwnerType
Decorators :
@Input()
Protected sub
Type : Subscription
Private Static PREFIX
Type : string
Default value : 'cx-configurator'
Private Static PREFIX_DDLB_OPTION_PRICE_VALUE
Type : string
Default value : 'option--price'
Private Static PREFIX_LABEL
Type : string
Default value : 'label'
Private Static PREFIX_OPTION_PRICE_VALUE
Type : string
Default value : 'price--optionsPriceValue'
Private Static SEPERATOR
Type : string
Default value : '--'
import { getLocaleId } from '@angular/common';
import {
  ChangeDetectionStrategy,
  Component,
  Input,
  isDevMode,
  OnDestroy,
  OnInit,
} from '@angular/core';
import { FormControl } from '@angular/forms';
import { timer } from 'rxjs';
import { debounce } from 'rxjs/operators';
import { ConfiguratorUISettingsConfig } from '../../../config/configurator-ui-settings.config';
import { ConfiguratorAttributeInputFieldComponent } from '../input-field/configurator-attribute-input-field.component';
import { ConfiguratorAttributeNumericInputFieldService } from './configurator-attribute-numeric-input-field.component.service';

class DefaultSettings {
  numDecimalPlaces: number;
  numTotalLength: number;
  negativeAllowed: boolean;
}

@Component({
  selector: 'cx-configurator-attribute-numeric-input-field',
  templateUrl: './configurator-attribute-numeric-input-field.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ConfiguratorAttributeNumericInputFieldComponent
  extends ConfiguratorAttributeInputFieldComponent
  implements OnInit, OnDestroy
{
  numericFormatPattern: string;
  locale: string;

  @Input() language: string;

  constructor(
    protected configAttributeNumericInputFieldService: ConfiguratorAttributeNumericInputFieldService,
    protected config: ConfiguratorUISettingsConfig
  ) {
    super(config);
  }

  /**
   * Do we need to display a validation message
   */
  mustDisplayValidationMessage(): boolean {
    const wrongFormat: boolean =
      (this.attributeInputForm.dirty || this.attributeInputForm.touched) &&
      this.attributeInputForm.errors?.wrongFormat;

    return wrongFormat;
  }

  ngOnInit() {
    //locales are available as 'languages' in the commerce backend
    this.locale = this.getInstalledLocale(this.language);

    let numDecimalPlaces = this.attribute.numDecimalPlaces;
    let numTotalLength = this.attribute.numTotalLength;
    let negativeAllowed = this.attribute.negativeAllowed;

    if (
      numDecimalPlaces === undefined ||
      numTotalLength === undefined ||
      negativeAllowed === undefined
    ) {
      //This won't happen in environments with the standard configurators deployed, as numeric
      //attributes do carry these settings. We still introduce default values to ease development
      //of extension use cases, but log a warning
      const defaultSettings = this.getDefaultSettings();
      numDecimalPlaces = defaultSettings.numDecimalPlaces;
      numTotalLength = defaultSettings.numTotalLength;
      negativeAllowed = defaultSettings.negativeAllowed;
      if (isDevMode()) {
        console.warn(
          'Meta data for numeric attribute not present, falling back to defaults'
        );
      }
    }

    this.attributeInputForm = new FormControl('', [
      this.configAttributeNumericInputFieldService.getNumberFormatValidator(
        this.locale,
        numDecimalPlaces,
        numTotalLength,
        negativeAllowed
      ),
    ]);

    this.numericFormatPattern =
      this.configAttributeNumericInputFieldService.getPatternForValidationMessage(
        numDecimalPlaces,
        numTotalLength,
        negativeAllowed,
        this.locale
      );
    if (this.attribute.userInput) {
      this.attributeInputForm.setValue(this.attribute.userInput);
    }

    this.sub = this.attributeInputForm.valueChanges
      .pipe(
        debounce(() =>
          timer(
            this.config.productConfigurator?.updateDebounceTime?.input ??
              this.FALLBACK_DEBOUNCE_TIME
          )
        )
      )
      .subscribe(() => this.onChange());
  }

  ngOnDestroy() {
    super.ngOnDestroy();
  }

  protected getDefaultSettings(): DefaultSettings {
    return { numDecimalPlaces: 2, numTotalLength: 6, negativeAllowed: false };
  }

  protected getInstalledLocale(locale: string): string {
    try {
      getLocaleId(locale);
      return locale;
    } catch {
      this.reportMissingLocaleData(locale);
      return 'en';
    }
  }

  protected reportMissingLocaleData(lang: string): void {
    if (isDevMode()) {
      console.warn(
        `ConfigAttributeNumericInputFieldComponent: No locale data registered for '${lang}' (see https://angular.io/api/common/registerLocaleData).`
      );
    }
  }
}
<div id="{{ createAttributeIdForConfigurator(attribute) }}" class="form-group">
  <input
    [formControl]="attributeInputForm"
    [required]="attribute.required"
    class="form-control"
    attr.role="{{ attribute.dataType }}"
    attr.aria-required="{{ attribute.required }}"
    (change)="onChange()"
    maxlength="{{ attribute.maxlength }}"
    attr.aria-labelledby="{{ createAriaLabelledBy('label', attribute.name) }}"
    [cxFocus]="{
      key: createAttributeIdForConfigurator(attribute)
    }"
  />
  <div class="cx-validation-msg" *ngIf="mustDisplayValidationMessage()">
    {{
      'configurator.attribute.wrongNumericFormat'
        | cxTranslate: { pattern: numericFormatPattern }
    }}
  </div>
</div>
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""