Thursday, February 11, 2021

Counter LWC - Lightning Design System


There are many awesome component blueprints defined in SLDS which are not available in LWC library, one such is Counter, full article here.


I have created a generic custom LWC component, code below, to use it across orgs - 

customCounter.html

<template>
    <div class="slds-form-element">

        <div class="slds-form-element__control">
            <button class="slds-button slds-button_icon 
slds-button_icon-small slds-input__button_decrement" 
                    title="Decrement counter">
                <lightning-icon icon-name="utility:ban" 
                                alternative-text="" 
                                size="xx-small" 
                                title="" 
                                variant="error"
                                onclick={setDecrementCounter}>
                </lightning-icon>
              <span class="slds-assistive-text">Decrement counter</span>
            </button>
            <input type="number" id="default1" placeholder={qtyVal} 
class="slds-input slds-input_counter" />
            <button class="slds-button slds-button_icon 
slds-button_icon-small 
slds-input__button_increment" 
                    title="Increment counter">
                <lightning-icon icon-name="utility:new" 
                                alternative-text="" 
                                size="xx-small" 
                                title="" 
                                variant="success"
                                onclick={setIncrementCounter}>
                </lightning-icon>
              <span class="slds-assistive-text">Increment counter</span>
            </button>
          </div>

      </div>
</template>

customCounter.js

import { LightningElementapi } from 'lwc';

export default class CustomCounter extends LightningElement {
    
    qty = 0;
    qtyVal = '';

    setDecrementCounter(event) {
        if(this.qty == 0)   this.qty = 0;
        else    this.qty = this.qty - 1;
        let quantity = this.qty.toString();
        this.qtyVal = quantity + ' ' + this.qtyMeasure;
        const decrementEvent = new CustomEvent(
'decrement'
detail: this.qty }
);
        this.dispatchEvent(decrementEvent);
    }

    setIncrementCounter(event) {
        this.qty = this.qty + 1;
        let quantity = this.qty.toString();
        this.qtyVal = quantity + ' ' + this.qtyMeasure;
        const incrementEvent = new CustomEvent(
'increment'
detail: this.qty }
);
        this.dispatchEvent(incrementEvent);
    }

    @api 
    get qtyMeasure() {
        return this._qtyMeasure;
    }

    set qtyMeasure(value) {
        if (value) {
            this._qtyMeasure = value;
            let qty = this.qty.toString();
            this.qtyVal = qty + ' ' + this.qtyMeasure;
        }else{
            this.qtyVal = '';
        }
    }
}

Call "customCounter" from other LWCs - 

parent.html

<template>
    <lightning-card >
        <lightning-layout>
            <lightning-layout-item class="slds-p-left_small">
                <lightning-icon icon-name="utility:trailhead" 
size="large"></lightning-icon>
            </lightning-layout-item>
            <lightning-layout-item>
                <p class="slds-p-horizontal_small">
                    <b>SLDS COUNTER</b>
                </p>
            </lightning-layout-item>
        </lightning-layout>
        
        <lightning-layout multiple-rows class="slds-m-around_xx-large">
                <lightning-layout-item class="slds-size_1-of-4">
</lightning-layout-item>    
                <lightning-layout-item class="slds-size_1-of-4 slds-box">
                    <lightning-icon icon-name="utility:product_workspace" 
size="small"></lightning-icon>
                    &nbsp;&nbsp;&nbsp;&nbsp;Paracetamol
                </lightning-layout-item>
                <lightning-layout-item class="slds-size_1-of-4 slds-box">
                    <c-custom-counter 
                                qty-measure='Strips'
                                ondecrement={quantityCtrl}
                                onincrement={quantityCtrl}>
                    </c-custom-counter>
                </lightning-layout-item>
                <lightning-layout-item class="slds-size_1-of-4">
</lightning-layout-item>
                <lightning-layout-item class="slds-size_1-of-4">
</lightning-layout-item>  
  
                <lightning-layout-item class="slds-size_1-of-4 slds-box">
                    <lightning-icon icon-name="utility:product_workspace" 
size="small"></lightning-icon>
                    &nbsp;&nbsp;&nbsp;&nbsp;Hand Sanitizer
                </lightning-layout-item>
                <lightning-layout-item class="slds-size_1-of-4 slds-box">
                    <c-custom-counter
                                qty-measure='Pieces'
                                ondecrement={quantityCtrl}
                                onincrement={quantityCtrl}>
                    </c-custom-counter>
                </lightning-layout-item>
                <lightning-layout-item class="slds-size_1-of-4">
</lightning-layout-item>

                <lightning-layout-item class="slds-size_1-of-4">
</lightning-layout-item>    
                <lightning-layout-item class="slds-size_1-of-4 slds-box">
                    <lightning-icon icon-name="utility:product_workspace" 
size="small"></lightning-icon>
                    &nbsp;&nbsp;&nbsp;&nbsp;Water Bottle
                </lightning-layout-item>
                <lightning-layout-item class="slds-size_1-of-4 slds-box">
                    <c-custom-counter 
                                qty-measure='Litres'
                                ondecrement={quantityCtrl}
                                onincrement={quantityCtrl}>
                    </c-custom-counter>
                </lightning-layout-item>
                <lightning-layout-item class="slds-size_1-of-4">
</lightning-layout-item>    

                <lightning-layout-item class="slds-size_1-of-4">
</lightning-layout-item>    
                <lightning-layout-item class="slds-size_1-of-4 slds-box">
                    <lightning-icon icon-name="utility:product_workspace" 
size="small"></lightning-icon>
                    &nbsp;&nbsp;&nbsp;&nbsp;Sugar
                </lightning-layout-item>
                <lightning-layout-item class="slds-size_1-of-4 slds-box">
                    <c-custom-counter 
                                qty-measure='Kilograms'
                                ondecrement={quantityCtrl}
                                onincrement={quantityCtrl}>
                    </c-custom-counter>
                </lightning-layout-item>
                <lightning-layout-item class="slds-size_1-of-4">
</lightning-layout-item>    
        </lightning-layout>

   </lightning-card>
        
</template>

parent.js

import { LightningElement } from 'lwc';

export default class Parent extends LightningElement {
    qty = 0;
    
    quantityCtrl(event) {
        this.qty = event.detail;
    }

}