File

projects/congarevenuecloud/elements/src/lib/product-configuration/product-configuration.component.ts

Description

Product configuration component is used to show the hierarchical view of the configurations for a given product or cart line item.

Preview

This component is responsible for loading configuration of product

Usage

import { ProductConfigurationModule } from '@congarevenuecloud/elements';
@NgModule({
imports: [ProductConfigurationModule, ...]
})
export class AppModule {}
```typescript
<apt-product-configuration
              [product]="product.Id"
              [relatedTo]="parent"
[accordion]="true"
></apt-product-configuration>

Implements

OnChanges OnDestroy

Metadata

Index

Properties
Methods
Inputs

Constructor

constructor(cdr: ChangeDetectorRef, productOptionService: ProductOptionService, cartItemService: CartItemService, secondaryCartService: SecondaryCartService, primaryCartService: CartService, productConfigurationService: ProductConfigurationService, araiService: AppliedRuleActionInfoService, productService: ProductService, alertService: AlertService, assetService: AssetService)
Parameters :
Name Type Optional
cdr ChangeDetectorRef No
productOptionService ProductOptionService No
cartItemService CartItemService No
secondaryCartService SecondaryCartService No
primaryCartService CartService No
productConfigurationService ProductConfigurationService No
araiService AppliedRuleActionInfoService No
productService ProductService No
alertService AlertService No
assetService AssetService No

Inputs

accordion
Type : boolean
Default value : true

Flag to determine whether the accordion is expanded or collapsed.

discovery
Type : string
Default value : null

This flag is of type string and can have values like 'productDetailsPage' or 'cartItemDetailsPage'. EX: discovery = 'productDetailsPage;cartItemDetailsPage' If 'productDetailsPage' is set, it allows configuring the product before adding it to the cart. If 'productDetailsPage' is not set, the component will only show a READ-ONLY version with the default configuration and this is the default behaviour. Similarly, If 'cartItemDetailsPage' is set, it allows configuring the item before updating the bundle. If 'cartItemDetailsPage' is not set, configuring before updating the bundle is not allowed. 'CartItemDetailsPage' It's a work in progress. Therefore, configure before update the bundle is not supported.

product
Type : string | Product

The primitive id of the product to render the configuration or the product record.

relatedTo
Type : CartItem

The primitive id of the parent product line item that should be used to render the configuration.

Methods

assignCartItems
assignCartItems(component: ProductOptionComponent, parentBundleNumber: number, cartItems: Array)

This method traverses the component and its children, assigning the cart items to their corresponding components.

Parameters :
Name Type Optional Description
component ProductOptionComponent No

The input component

parentBundleNumber number No

The parent bundle number of the starting component.

cartItems Array<CartItem> No

Array of cart items to assign

Returns : void
getAllComponents
getAllComponents(view: ConfigurationView)

This method returns a list of option product

See ConfigurationView for more details on the structure and fields required.

Parameters :
Name Type Optional Description
view ConfigurationView No

instance of ConfigurationView.

Returns : Array<ProductOptionComponent>

an array of option products associated with the provided view.

getComponentArray
getComponentArray(component: ProductOptionComponent)

Method returns a flat array of components and their children of the product option.

Parameters :
Name Type Optional Description
component ProductOptionComponent No

it is an object of type ProductOptionComponent.

Returns : Array<ProductOptionComponent>
getProductOptionComponent
getProductOptionComponent(productId: string, view: ConfigurationView)

Method returns an instance of the product option component for the specified product ID.

See ConfigurationView for more details on the structure and fields required.

Parameters :
Name Type Optional Description
productId string No

string value representing the product Id.

view ConfigurationView No
isTriggeringProduct
isTriggeringProduct(rules: Array<AppliedRuleActionInfo>, componentId: string, bundleProduct: CartItem)

This function checks if a given component ID triggers any of the given rules. Only considers rules with an ActionType other than 'Replacement' and an ActionIntent of 'Prompt'

Parameters :
Name Type Optional Description
rules Array<AppliedRuleActionInfo> No
  • An array of constraint rules.
componentId string No
  • The ID of the component being checked.
bundleProduct CartItem No
Returns : boolean
  • Boolean Whether the component ID triggers any of the given rules.
toggleOption
toggleOption(component: ProductOptionComponent, group: ProductOptionGroup, reference: string, view: ConfigurationView, evt?: any, showLoader: boolean)

This method allows you to add or remove options for a product.

See ConfigurationView for more details on the structure and fields required.

Parameters :
Name Type Optional Default value Description
component ProductOptionComponent No

The product option component required for adding/removing on toggle.

group ProductOptionGroup No

The product option group of the option being toggled.

reference string No
view ConfigurationView No

The configuration view containing the product, cart, and rule list.

evt any Yes

Optional event parameters of type any.

showLoader boolean No false

Optional Parameters to show loader on button.

Returns : void

Properties

attributeChanged
Type : boolean
Default value : false

Flag determines changes in attribute.

cart$
Type : Observable<Cart>

Cart$ holds Observable of cart

collapseAll
Type : boolean
Default value : true

Controls the collapse of all configuration accordions.

onConfigChange
Type : boolean
Default value : false

Flag determines config change.

productQuantity
Type : number
Default value : 1

Holds quantity of the product.

readOnly
Type : boolean
Default value : false
searchText
Type : string
Default value : null

Search query to filter configuration.

view$
Type : BehaviorSubject<ConfigurationView>
Default value : new BehaviorSubject<ConfigurationView>(null)

The view object used to hold information for rendering the view, of type ConfigurationView.

<div class="card">
    <div class="card-body">
        <ng-container *ngIf="(view$ | async) as view; else loading">
            <ng-container *ngIf="view?.product?.OptionGroups?.length > 0 || view?.product?.HasAttributes && view?.product?.AttributeGroups?.length > 0
                            ; else empty">
                <div>
                    <div class="d-flex justify-content-between mb-2">

                        <form
                            class="input-group input-group-sm col-lg-2 col-md-4 col-sm-9 col-9 d-flex align-items-center pl-0">
                            <div class="input-group-append position-absolute">
                                <button class="btn btn-link">
                                    <i class="fas fa-search"></i>
                                </button>
                            </div>
                            <input type="search" class="form-control"
                                placeholder="{{'COMMON.SEARCH_CONFIGURATION' | translate}}" [(ngModel)]="searchText"
                                name="searchText" (ngModelChange)="searchChange()">
                        </form>
                        <div>
                            <button class="btn btn-link px-2" [disabled]="accordion"
                                (click)="accordion = true; collapseAll = false;">
                                <i class="fa fa-angle-double-up fa-lg" title="Collapse All"></i>
                            </button>
                            <button class="btn btn-link pl-2 pr-0" [disabled]="!accordion"
                                (click)="accordion = false; collapseAll = true;">
                                <i class="fa fa-angle-double-down fa-lg" title="Expand All"></i>
                            </button>
                        </div>
                    </div>

                    <div class="accordion" id="optionAccordion">
                        <ng-container *ngIf="view?.product?._metadata?.item?.AttributeValue">
                            <apt-product-attribute [product]="view.product" [relatedTo]="relatedTo"
                                [(productAttributeValue)]="view.product._metadata.item.AttributeValue"
                                (productAttributeValueChange)="onAttributeChange($event, view)" [readOnly]="readOnly"
                                container="optionAccordion" (attributeValueChange)="handleAttributeValueChange($event)"
                                [accordion]="accordion" [collapseAll]="collapseAll">
                            </apt-product-attribute>
                        </ng-container>

                        <ng-container *ngIf="view?.product?.HasOptions && view?.product?.OptionGroups?.length > 0">
                            <div class="card border"
                                *ngFor="let productOptionGroup of view?.product?.OptionGroups; let optionIndex = index; trackBy: trackById"
                                [hidden]="productOptionGroup.get('hide')">
                                <ng-container *ngIf="!productOptionGroup?.IsHidden">
                                    <div [id]="'ac' + productOptionGroup.Id" class="accordion">
                                        <div class="card-header px-2 py-1">
                                            <h2 class="mb-0 d-flex justify-content-between align-items-center">
                                                <button class="btn btn-link chevron" type="button"
                                                    data-toggle="collapse"
                                                    [attr.data-target]="'#a' + productOptionGroup.Id"
                                                    [attr.aria-expanded]="((optionIndex + view?.product?.AttributeGroups?.length === 0 || productOptionGroup._metadata.expand) && collapseAll) || !accordion ? 'true' : 'false'">
                                                    {{productOptionGroup?.OptionGroup?.Label}}
                                                </button>
                                                <apt-alert [record]="productOptionGroup"
                                                    message="ERROR.OPTION_GROUP.ERROR" layout="inline"
                                                    [showAlertWithAction]="false"
                                                    *ngIf="!readOnly && productOptionGroup?.ModifiableType !== 'Fixed'">
                                                </apt-alert>
                                            </h2>
                                        </div>

                                        <div [id]="'a' + productOptionGroup.Id" class="collapse"
                                            [class.show]="((optionIndex + view?.product?.AttributeGroups?.length === 0 || productOptionGroup._metadata.expand) && collapseAll) || !accordion"
                                            [attr.data-parent]="'#ac' + productOptionGroup.Id">
                                            <div class="card-body">
                                                <div
                                                    *ngIf="productOptionGroup?.IsPicklist &&  productOptionGroup.MaxOptions === 1 && productOptionGroup.MinOptions === 1">
                                                    <ng-template [ngTemplateOutlet]="picklistTemplate"
                                                        [ngTemplateOutletContext]="{componentList: productOptionGroup?.Options, parent: productOptionGroup.Id, group: productOptionGroup, picklistIndex: optionIndex}">
                                                    </ng-template>
                                                </div>
                                                <div *ngIf="!productOptionGroup?.IsPicklist">
                                                    <ng-template [ngTemplateOutlet]="productOptionGroupTemplate"
                                                        [ngTemplateOutletContext]="{optionGroupList: productOptionGroup?.ChildOptionGroups, parent: productOptionGroup.Id}">
                                                    </ng-template>
                                                    <div class="pl-3">
                                                        <ng-template [ngTemplateOutlet]="componentListTemplate"
                                                            [ngTemplateOutletContext]="{componentList: productOptionGroup?.Options, parent: productOptionGroup.Id, group: productOptionGroup, optionIndex: optionIndex}">
                                                        </ng-template>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </ng-container>
                            </div>
                        </ng-container>
                    </div>

                    <ng-template #productOptionGroupTemplate let-optionGroupList="optionGroupList" let-parent="parent"
                        let-parentProduct="parentProduct">
                        <div class="accordion" [id]="parent">
                            <div *ngFor="let subProductOptionGroup of optionGroupList; let categoryIndex = index; let l = last; let f = first; trackBy: trackById"
                                class="mb-3">
                                <ng-container *ngIf="!subProductOptionGroup?.IsHidden">
                                    <h5 class="d-flex justify-content-between align-items-center border-bottom">
                                        <button class="btn btn-link chevron" type="button" data-toggle="collapse"
                                            [attr.data-target]="'#' + parent + '-' + subProductOptionGroup.Id"
                                            [attr.aria-expanded]="((subProductOptionGroup._metadata.expand) && collapseAll) || !accordion ? 'true' : 'false'">
                                            {{subProductOptionGroup?.OptionGroup?.Label}}
                                        </button>
                                        <apt-alert message="ERROR.OPTION_GROUP.ERROR" layout="inline"
                                            [record]="subProductOptionGroup" [showAlertWithAction]="false"
                                            *ngIf="!readOnly && subProductOptionGroup?.ModifiableType !== 'Fixed'"></apt-alert>
                                    </h5>

                                    <div [id]="parent + '-' + subProductOptionGroup.Id"
                                        class="collapse pl-lg-4 pl-md-4 pl-sm-2 pl-2" [attr.data-parent]="'#' + parent"
                                        [class.show]="((subProductOptionGroup._metadata.expand) && collapseAll) || !accordion">
                                        <div class="mt-4"
                                            *ngIf="subProductOptionGroup?.IsPicklist &&  subProductOptionGroup.MaxOptions === 1 && subProductOptionGroup.MinOptions === 1">
                                            <ng-template [ngTemplateOutlet]="picklistTemplate"
                                                [ngTemplateOutletContext]="{componentList: subProductOptionGroup?.Options, parent: subProductOptionGroup.Id, group: subProductOptionGroup, picklistIndex: categoryIndex}">
                                            </ng-template>
                                        </div>
                                        <div *ngIf="!subProductOptionGroup?.IsPicklist">
                                            <ng-template [ngTemplateOutlet]="componentListTemplate"
                                                [ngTemplateOutletContext]="{componentList: subProductOptionGroup?.Options, parent: parent + '-' + subProductOptionGroup.Id, group: subProductOptionGroup, optionIndex: categoryIndex}">
                                            </ng-template>
                                        </div>
                                    </div>
                                </ng-container>
                            </div>
                        </div>
                    </ng-template>

                    <ng-template #componentListTemplate let-componentList="componentList" let-parent="parent"
                        let-group="group" let-optionIndex = "optionIndex">
                        <ng-container
                            *ngIf="componentList?.length > 0 || group?.ChildOptionGroups?.length > 0; else cLoading">
                            <ng-container class="custom-border-bottom"
                                *ngFor="let component of componentList; let f = first; let l = last; trackBy: trackById; let componentListIndex = index;">
                                <div class="option" *ngIf="!component.get('hidden')" [class.border-bottom]="!l"
                                    [hidden]="component.get('hide')">

                                    <ng-template
                                        *ngIf="component?.ComponentProduct?._metadata?.item?.AssetLineItem?.PriceType === 'One Time'"
                                        [ngTemplateOutlet]="readOnlyComponent" [ngTemplateOutletContext]="{
                                                                component: component,
                                                                parent: parent,
                                                                selected: isOptionSelected(component),
                                                                cartItem: component?.ComponentProduct?._metadata?.item,
                                                                group: group, readOnlyIndex: optionIndex,
                                                            }"></ng-template>

                                    <ng-template
                                        *ngIf="component?.ComponentProduct?._metadata?.item?.AssetLineItem?.PriceType !== 'One Time'"
                                        [ngTemplateOutlet]="componentTemplate" [ngTemplateOutletContext]="{
                                                            component: component, 
                                                            parent: parent, 
                                                            selected: isOptionSelected(component), 
                                                            cartItem: component?.ComponentProduct?._metadata?.item,
                                                            group: group,
                                                            componentIndex: optionIndex,
                                                            componentListIndex: componentListIndex}">
                                    </ng-template>
                                </div>
                            </ng-container>
                        </ng-container>
                        <ng-template #cLoading>
                            <div class="d-flex justify-content-center pt-5">
                                <apt-dots></apt-dots>
                            </div>
                        </ng-template>
                    </ng-template>

                    <ng-template #picklistTemplate let-componentList="componentList" let-parent="parent"
                        let-group="group" let-picklistIndex = "picklistIndex">
                        <ng-container
                            *ngIf="componentList?.length > 0 || group?.ChildOptionGroups?.length > 0; else cLoading">
                            <ng-select [items]="componentList" class="optionPicklist"
                                placeholder="{{'PRODUCT_DETAILS.SELECT_ONE_OPTION' | translate}}"
                                labelForId="group.Id+'-'+ parent.Id" [(ngModel)]="group._metadata.componentName"
                                (ngModelChange)="isPicklistChangeValue($event, group, view)" [disabled]="readOnly"
                                bindLabel="ComponentProduct.Name" [virtualScroll]="true">
                                <ng-template ng-option-tmp let-item="item" let-index="index">
                                    <div class="d-flex py-2"
                                        [ngClass]="{'border-bottom': index !== componentList?.length-1}">
                                        <div class="d-flex flex-grow-1">
                                            <div class="d-flex cr-popover-container">
                                                <div class="image-container d-flex justify-content-center">
                                                    <img [src]="item?.ComponentProduct?.IconId | image" height="50">
                                                </div>
                                            </div>
                                            <div class="mx-3">
                                                <p class="m-0 font-weight-bold d-flex">{{item?.ComponentProduct?.Name}}
                                                </p>
                                                <small
                                                    class="d-block desc">{{item?.ComponentProduct?.Description}}</small>
                                            </div>
                                        </div>
                                        <div class="width-picklist-fixed border-left d-flex">
                                            <div class="form-group col">
                                                <label>{{'COMMON.PRICE' | translate}}</label>
                                                <h5 class="pt-1">
                                                    <apt-price [record]="item?.ComponentProduct"
                                                        [type]="'list'"></apt-price>
                                                </h5>
                                            </div>
                                        </div>
                                    </div>
                                </ng-template>
                            </ng-select>
                            <ng-template *ngIf="group._metadata.componentName" [ngTemplateOutlet]="componentTemplate"
                                [ngTemplateOutletContext]="{
                                                component: group._metadata?.optionSelected, 
                                                parent: group.Id, 
                                                selected: !!group._metadata.componentName, 
                                                cartItem: group._metadata?.optionSelected?.ComponentProduct?._metadata?.item,
                                                group: group,
                                                isPicklist: true,
                                                componentIndex: picklistIndex,
                                                componentListIndex: picklistIndex
                                                }"></ng-template>
                        </ng-container>
                        <ng-template #cLoading>
                            <div class="d-flex justify-content-center pt-5">
                                <apt-dots></apt-dots>
                            </div>
                        </ng-template>
                    </ng-template>

                    <ng-template #readOnlyComponent let-component="component" let-parent="parent"
                        let-cartItem="cartItem" let-group="group" let-selected="selected"
                        let-readOnlyIndex = "readOnlyIndex">
                        <div class="d-flex py-2">
                            <div class="d-flex flex-grow-1">
                                <div class="d-flex">
                                    <div class="mr-2">
                                        <i class="fa fa-check-square-o fa-lg"></i>
                                    </div>
                                    <div class="image-container d-flex justify-content-center">
                                        <img [src]="component?.ComponentProduct?.IconId | image" height="50">
                                    </div>
                                </div>
                                <div class="mx-3">
                                    <p class="m-0 font-weight-bold">{{component?.ComponentProduct?.Name}}</p>
                                    <small class="d-block desc">{{component?.ComponentProduct?.Description}}</small>
                                </div>
                            </div>
                            <div class="width-fixed border-left d-flex">
                                <div class="form-group col">
                                    <label>{{'COMMON.PRICE' | translate}}</label>
                                    <h5 class="pt-1">
                                        <apt-price [record]="component?.ComponentProduct" [quantity]="1"
                                            [type]="'list'"></apt-price>
                                    </h5>
                                </div>

                                <div class="form-group col">
                                    <label for="qty">{{'COMMON.QTY' | translate}}</label>
                                    <input type="number" min="0" class="form-control form-control-sm text-center"
                                        [disabled]="true" id="qty" [value]="cartItem?.Quantity" name="quantity">
                                </div>
                            </div>
                        </div>

                        <div class="pl-lg-3" [hidden]="!selected">
                            <ng-container
                                *ngIf="component?.ComponentProduct?._metadata?.item && component?.ComponentProduct?.HasAttributes">
                                <apt-product-attribute [product]="component.ComponentProduct"
                                    [relatedTo]="component.ComponentProduct._metadata.item"
                                    [container]="parent + '-' + component.Id" lineType="Option"
                                    [(productAttributeValue)]="component.ComponentProduct._metadata.item.AttributeValue"
                                    (productAttributeValueChange)="onAttributeChange($event, view)"
                                    [readOnly]="readOnly" (attributeValueChange)="handleAttributeValueChange($event)"
                                    [accordion]="accordion" [collapseAll]="collapseAll"></apt-product-attribute>
                            </ng-container>


                            <ng-template *ngIf="component?.ComponentProduct?._metadata?.item?.Id"
                                [ngTemplateOutlet]="productOptionGroupTemplate"
                                [ngTemplateOutletContext]="{optionGroupList: component?.ComponentProduct?.OptionGroups, parent: parent + '-' + component.Id, parentProduct: component?.ComponentProduct}">
                            </ng-template>
                        </div>
                    </ng-template>

                    <ng-template #componentTemplate let-component="component" let-parent="parent"
                        let-selected="selected" let-cartItem="cartItem" let-group="group" let-isPicklist="isPicklist"
                        let-componentListIndex = "componentListIndex" let-componentIndex = "componentIndex">
                        <div class="d-lg-flex d-md-flex py-lg-2 py-md-2 py-sm-3 py-3">
                            <div class="d-flex flex-grow-1">
                                <div class="d-flex cr-popover-container">
                                    <div class="custom-control custom-checkbox"
                                        *ngIf="!component?._metadata?.processing; else spinner">
                                        <input type="checkbox" class="custom-control-input"
                                            [(ngModel)]="component._metadata.isDirty" [id]="parent + '-' + component.Id"
                                            [checked]="selected"
                                            (ngModelChange)="toggleOption(component, group, parent, view, component?._metadata?.disabled)"
                                            [disabled]="group?._metadata?.summary?.disabled || component?._metadata?.disabled || group.ModifiableType === 'Fixed' || readOnly">
                                        <label class="custom-control-label"
                                            [for]="parent + '-' + component.Id">&nbsp;</label>
                                    </div>
                                    <ng-template #spinner><apt-spinner class="pr-1 mr-2"
                                            [large]="false"></apt-spinner></ng-template>

                                    <div
                                        class="image-container col-auto row-auto p-0 justify-content-center d-lg-block d-md-block d-sm-none d-none">
                                        <img [src]="component?.ComponentProduct?.IconId | image" height="50">
                                    </div>
                                </div>
                                <div class="mx-lg-3 mx-md-3 mx-sm-0 mx-0" [ngClass]="{'pl-2': selected}">
                                    <p class="m-0 font-weight-bold d-flex">{{component?.ComponentProduct?.Name}}
                                        <i *ngIf='!readOnly && component?.IsRequired'
                                            class="fa fa-asterisk text-danger fa-xs" aria-hidden="true"></i>
                                        <apt-popover *ngIf="!readOnly" [placement]="'right'" [constraintRules]="isTriggeringProduct(component?.ComponentProduct?._metadata?.rules, component?.ComponentProduct?.Id, view?.product?._metadata?.item)
                                            ? component?.ComponentProduct?._metadata?.rules : null"
                                            [outsideClick]="false"
                                            [isClose]="component?.ComponentProduct?._metadata?.hidePopover">
                                            <i role="button" class="fas fa-info-circle ml-2 text-primary"
                                                *ngIf="isTriggeringProduct(component?.ComponentProduct?._metadata?.rules, component?.ComponentProduct?.Id, view?.product?._metadata?.item)"></i>
                                        </apt-popover>
                                    </p>
                                    <small class="d-block desc">{{component?.ComponentProduct?.Description}}</small>
                                    <apt-alert [record]="component" message="ERROR.OPTION_GROUP.ERROR" layout="inline"
                                        [showAlertWithAction]="false"
                                        *ngIf="!readOnly && productOptionGroup?.ModifiableType !== 'Fixed'">
                                    </apt-alert>
                                </div>
                            </div>
                            <div class="border-left d-lg-flex d-md-flex d-sm-none d-none px-3 py-4"
                                *ngIf="selected && cartItem">
                                <div class="custom-control custom-checkbox">
                                    <input type="checkbox" class="custom-control-input"
                                        [(ngModel)]="cartItem.IsOptional" [id]="cartItem.Id"
                                        [checked]="cartItem.IsOptional"
                                        (ngModelChange)="changeItemToOptional($event, cartItem, component)">
                                    <label class="custom-control-label pl-1 pt-1"
                                        [for]="cartItem.Id">{{'PRODUCT_DETAILS.IS_OPTIONAL' | translate}}</label>
                                </div>
                            </div>
                            <div class="d-lg-none d-md-none d-sm-flex d-flex pl-4 ml-1 py-2"
                                *ngIf="selected && cartItem">
                                <div class="custom-control custom-checkbox">
                                    <input type="checkbox" class="custom-control-input"
                                        [(ngModel)]="cartItem.IsOptional" [id]="cartItem.Id"
                                        [checked]="cartItem.IsOptional"
                                        (ngModelChange)="changeItemToOptional($event, cartItem, component)">
                                    <label class="custom-control-label pl-1 pt-1"
                                        [for]="cartItem.Id">{{'PRODUCT_DETAILS.IS_OPTIONAL' | translate}}</label>
                                </div>
                            </div>
                            <div class="width-fixed border-left d-lg-flex d-md-flex d-sm-none d-none">
                                <div class="form-group col">
                                    <label>{{'COMMON.PRICE' | translate}}</label>
                                    <h5 class="pt-1" [id]="'item-price-' + componentIndex + '-' + componentListIndex">
                                        <ng-container
                                            *ngIf="!component?.ComponentProduct?._metadata?.item?.NetPrice; else itemPrice">
                                            <apt-price [record]="component?.ComponentProduct"
                                                [type]="'list'"></apt-price>
                                        </ng-container>
                                        <ng-template #itemPrice>
                                            <span>{{component?.ComponentProduct?._metadata?.item?.NetPrice |
                                                localCurrency | async}}</span>
                                        </ng-template>
                                    </h5>
                                </div>

                                <div class="form-group col">
                                    <label for="qty">{{'COMMON.QTY' | translate}}</label>
                                    <i role="button" class="fas fa-info-circle ml-2 text-primary"
                                        [tooltip]="'COMMON.QUANTITY_NOT_MODIFIABLE' | translate"
                                        *ngIf="!readOnly && ((selected && !component?.IsModifiable) || group?.ModifiableType === 'Fixed')"></i>
                                    <input type="number" [min]="component?.IsRequired ? 1 : 0"
                                        class="form-control form-control-sm text-center"
                                        *ngIf="cartItem; else disabledInput"
                                        [disabled]="!selected || group?.ModifiableType === 'Fixed' || !component?.IsModifiable"
                                        id="qty" placeholder="1" name="quantity"
                                        (change)="emitChange(view); changeItemQuantity(cartItem, component)"
                                        [(ngModel)]="!selected ? 0 : cartItem.Quantity">
                                    <ng-template #disabledInput>
                                        <input type="number" min="0" class="form-control form-control-sm text-center"
                                            [disabled]="true" id="qty" placeholder="1" name="quantity">
                                    </ng-template>
                                </div>
                            </div>
                            <div class="width-fixed d-lg-none d-md-none d-sm-block d-block pl-3">
                                <div class="form-group col">
                                    <label>{{'COMMON.PRICE' | translate}}</label>
                                    <h5 class="pt-1" [id]="'item-price-sm-' + componentIndex + '-' + componentListIndex">
                                        <ng-container
                                            *ngIf="!component?.ComponentProduct?._metadata?.item?.NetPrice; else itemPrice">
                                            <apt-price [record]="component?.ComponentProduct"
                                                [type]="'list'"></apt-price>
                                        </ng-container>
                                        <ng-template #itemPrice>
                                            <span>{{component?.ComponentProduct?._metadata?.item?.NetPrice |
                                                localCurrency | async}}</span>
                                        </ng-template>
                                    </h5>
                                </div>

                                <div class="form-group col">
                                    <label for="qty">{{'COMMON.QTY' | translate}}</label>
                                    <i role="button" class="fas fa-info-circle ml-2 text-primary"
                                        [tooltip]="'COMMON.QUANTITY_NOT_MODIFIABLE' | translate"
                                        *ngIf="!readOnly && ((selected && !component?.IsModifiable) || group?.ModifiableType === 'Fixed')"></i>
                                    <input type="number" [min]="component?.IsRequired ? 1 : 0"
                                        class="form-control form-control-sm text-center"
                                        *ngIf="cartItem; else disabledInput"
                                        [disabled]="!selected || group?.ModifiableType === 'Fixed' || !component?.IsModifiable"
                                        id="qty" placeholder="1" name="quantity"
                                        (change)="emitChange(view); changeItemQuantity(cartItem, component)"
                                        [(ngModel)]="!selected ? 0 : cartItem.Quantity">
                                    <ng-template #disabledInput>
                                        <input type="number" min="0" class="form-control form-control-sm text-center"
                                            [disabled]="true" id="qty" placeholder="1" name="quantity">
                                    </ng-template>
                                </div>
                            </div>
                        </div>

                        <div class="pl-lg-3 pl-md-0 pl-sm-0 pl-0" [hidden]="!selected">
                            <ng-container
                                *ngIf="component?.ComponentProduct?._metadata?.item && component?.ComponentProduct?.HasAttributes">
                                <apt-product-attribute [product]="component.ComponentProduct"
                                    [relatedTo]="component.ComponentProduct._metadata.item"
                                    [container]="parent + '-' + component.Id" lineType="Option"
                                    [(productAttributeValue)]="component.ComponentProduct._metadata.item.AttributeValue"
                                    (productAttributeValueChange)="onAttributeChange($event, view)"
                                    [readOnly]="readOnly" (attributeValueChange)="handleAttributeValueChange($event)"
                                    [accordion]="accordion" [collapseAll]="collapseAll"></apt-product-attribute>
                            </ng-container>


                            <ng-template *ngIf="component?.ComponentProduct?._metadata?.item?.Id"
                                [ngTemplateOutlet]="productOptionGroupTemplate"
                                [ngTemplateOutletContext]="{optionGroupList: component?.ComponentProduct?.OptionGroups, parent: 'ad' + parent + '-' + component.Id, parentProduct: component?.ComponentProduct}">
                            </ng-template>
                        </div>
                    </ng-template>
                </div>
            </ng-container>
            <ng-template #empty>
                <div class="d-flex justify-content-center flex-column align-items-center py-5 my-5">
                    <i class="fa fa-cog fa-5x text-primary xl text-faded"></i>
                    <div class="mt-4">{{'CONFIGURATION.NO_CONFIGURATION' | translate}}</div>
                </div>
            </ng-template>
        </ng-container>
        <ng-template #loading>
            <div class="d-flex justify-content-center py-5">
                <apt-dots></apt-dots>
            </div>
        </ng-template>
    </div>
</div>

./product-configuration.component.scss

.accordion {
  .cr-popover-container {
    min-width: 10%;
  }

  .image-container {
    width: 64px;

    img {
      max-height: 50px;
      max-width: 64px;
    }
  }

  .form-group {
    margin-bottom: 0;
  }

  input {
    max-width: 70px;
  }

  .custom-control {
    margin-top: -3px;
  }

  .width-fixed {
    min-width: 14rem;
  }

  .desc {
    max-height: 40px;
    overflow-y: hidden;
  }

  .card {
    overflow: visible;
  }
}

.search {
  min-width: 300px;
}

apt-cr-popover {
  .custom-checkbox {
    input[type="checkbox"][disabled] {
      + label {
        pointer-events: none;
      }
    }
  }
}

@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
  /* IE10+ CSS styles go here */
  apt-product-configuration
    div.accordion
    div.card
    div.option
    div.py-2
    div.mx-3 {
    margin-left: 3rem;
  }
}

.input-group-append {
  z-index: 1;
}

.input-group {
  input {
    border-radius: 0.3rem;
    padding-left: 2rem !important;
    z-index: 0;
  }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""