File

feature-libs/product-configurator/rulebased/components/attribute/header/configurator-attribute-header.component.ts

Extends

ConfiguratorAttributeBaseComponent

Implements

OnInit

Metadata

changeDetection ChangeDetectionStrategy.OnPush
selector cx-configurator-attribute-header
templateUrl ./configurator-attribute-header.component.html

Index

Properties
Methods
Inputs
Accessors

Constructor

constructor(configUtils: ConfiguratorStorefrontUtilsService)
Parameters :
Name Type Optional
configUtils ConfiguratorStorefrontUtilsService No

Inputs

attribute
Type : Configurator.Attribute
groupId
Type : string
groupType
Type : Configurator.GroupType
owner
Type : CommonConfigurator.Owner

Methods

getConflictMessageKey
getConflictMessageKey(groupType: Configurator.GroupType)

Retrieves a certain conflict link key depending on the current group type for translation.

Parameters :
Name Type Optional Description
groupType Configurator.GroupType No
  • group type
Returns : string
  • the conflict link key
getRequiredMessageKey
getRequiredMessageKey()

Get message key for the required message. Is different for multi- and single selection values @return {string} - required message key

Returns : string
  • required message key
isAttributeGroup
isAttributeGroup(groupType: Configurator.GroupType)

Verifies whether the group type is attribute group

Parameters :
Name Type Optional Description
groupType Configurator.GroupType No
  • group type
Returns : boolean
  • 'true' if the group type is 'attribute group' otherwise 'false'
Protected isMultiSelection
isMultiSelection()
Returns : boolean
Protected isRequiredAttributeWithDomain
isRequiredAttributeWithDomain()
Returns : boolean
Protected isSingleSelection
isSingleSelection()
Returns : boolean
ngOnInit
ngOnInit()
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

attribute
Type : Configurator.Attribute
Decorators :
@Input()
groupId
Type : string
Decorators :
@Input()
groupType
Type : Configurator.GroupType
Decorators :
@Input()
iconTypes
Default value : ICON_TYPE
owner
Type : CommonConfigurator.Owner
Decorators :
@Input()
showRequiredMessageForDomainAttribute$
Type : Observable<boolean>
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 : '--'

Accessors

hasImage
gethasImage()

Checks if an image is attached

Returns : boolean
image
getimage()

Returns image attached to the attribute (if available)

import {
  ChangeDetectionStrategy,
  Component,
  Input,
  OnInit,
} from '@angular/core';
import { CommonConfigurator } from '@spartacus/product-configurator/common';
import { ICON_TYPE } from '@spartacus/storefront';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Configurator } from '../../../core/model/configurator.model';
import { ConfiguratorStorefrontUtilsService } from '../../service/configurator-storefront-utils.service';
import { ConfiguratorAttributeBaseComponent } from '../types/base/configurator-attribute-base.component';

@Component({
  selector: 'cx-configurator-attribute-header',
  templateUrl: './configurator-attribute-header.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ConfiguratorAttributeHeaderComponent
  extends ConfiguratorAttributeBaseComponent
  implements OnInit
{
  @Input() attribute: Configurator.Attribute;
  @Input() owner: CommonConfigurator.Owner;
  @Input() groupId: string;
  @Input() groupType: Configurator.GroupType;

  iconTypes = ICON_TYPE;
  showRequiredMessageForDomainAttribute$: Observable<boolean>;

  constructor(protected configUtils: ConfiguratorStorefrontUtilsService) {
    super();
  }

  ngOnInit(): void {
    /**
     * Show message that indicates that attribute is required in case attribute has a domain of values
     */
    this.showRequiredMessageForDomainAttribute$ = this.configUtils
      .isCartEntryOrGroupVisited(this.owner, this.groupId)
      .pipe(
        map((result) => (result ? this.isRequiredAttributeWithDomain() : false))
      );
  }

  /**
   * Get message key for the required message. Is different for multi- and single selection values
   *  @return {string} - required message key
   */
  getRequiredMessageKey(): string {
    if (this.isSingleSelection()) {
      return 'configurator.attribute.singleSelectRequiredMessage';
    } else if (this.isMultiSelection()) {
      return 'configurator.attribute.multiSelectRequiredMessage';
    } else {
      //input attribute types
      return 'configurator.attribute.singleSelectRequiredMessage';
    }
  }

  protected isMultiSelection(): boolean {
    switch (this.attribute.uiType) {
      case Configurator.UiType.CHECKBOXLIST:
      case Configurator.UiType.CHECKBOXLIST_PRODUCT:
      case Configurator.UiType.MULTI_SELECTION_IMAGE: {
        return true;
      }
    }
    return false;
  }

  protected isSingleSelection(): boolean {
    switch (this.attribute.uiType) {
      case Configurator.UiType.RADIOBUTTON:
      case Configurator.UiType.RADIOBUTTON_PRODUCT:
      case Configurator.UiType.CHECKBOX:
      case Configurator.UiType.DROPDOWN:
      case Configurator.UiType.DROPDOWN_PRODUCT:
      case Configurator.UiType.SINGLE_SELECTION_IMAGE: {
        return true;
      }
    }
    return false;
  }

  protected isRequiredAttributeWithDomain(): boolean {
    const uiType = this.attribute.uiType;
    return (
      (this.attribute.required &&
        this.attribute.incomplete &&
        uiType !== Configurator.UiType.NOT_IMPLEMENTED &&
        uiType !== Configurator.UiType.STRING &&
        uiType !== Configurator.UiType.NUMERIC) ??
      false
    );
  }

  /**
   * Verifies whether the group type is attribute group
   *
   * @param groupType {Configurator.GroupType} - group type
   * @return {boolean} - 'true' if the group type is 'attribute group' otherwise 'false'
   */
  isAttributeGroup(groupType: Configurator.GroupType): boolean {
    if (Configurator.GroupType.ATTRIBUTE_GROUP === groupType) {
      return true;
    }
    return false;
  }

  /**
   * Retrieves a certain conflict link key depending on the current group type for translation.
   *
   * @param groupType {Configurator.GroupType}- group type
   * @return {string} - the conflict link key
   */
  getConflictMessageKey(groupType: Configurator.GroupType): string {
    return groupType === Configurator.GroupType.CONFLICT_GROUP
      ? 'configurator.conflict.viewConfigurationDetails'
      : 'configurator.conflict.viewConflictDetails';
  }

  /**
   * Checks if an image is attached
   * @returns True if an only if at least one image exists
   */
  get hasImage(): boolean {
    const images = this.attribute.images;
    return images ? images.length > 0 : false;
  }
  /**
   * Returns image attached to the attribute (if available)
   * @returns Image
   */
  get image(): Configurator.Image | undefined {
    const images = this.attribute.images;
    return images && this.hasImage ? images[0] : undefined;
  }
}
<label
  id="{{ createAttributeUiKey('label', attribute.name) }}"
  [class.cx-required-icon]="attribute.required"
  [class.cx-required-error]="showRequiredMessageForDomainAttribute$ | async"
  [attr.aria-label]="
    !attribute.required
      ? attribute.label
      : ('configurator.attribute.requiredAttribute'
        | cxTranslate: { param: attribute.label })
  "
  >{{ attribute.label }}</label
>
<div *ngIf="attribute.hasConflicts" class="cx-conflict-msg">
  <cx-icon
    *ngIf="isAttributeGroup(groupType)"
    [type]="iconTypes.WARNING"
  ></cx-icon>
  <div class="cx-conflict-msg">
    {{ getConflictMessageKey(groupType) | cxTranslate }}
  </div>
</div>
<div
  *ngIf="showRequiredMessageForDomainAttribute$ | async"
  class="cx-required-error-msg"
>
  <cx-icon [type]="iconTypes.ERROR"></cx-icon>
  {{ getRequiredMessageKey() | cxTranslate }}
</div>
<img
  *ngIf="hasImage"
  class="cx-attribute-img"
  src="{{ image?.url }}"
  alt="{{ image?.altText }}"
/>
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""