A Container Approach For KPI Integer Components

How can we display KPI Components in a line, side by side?



KPIs showed in a line

In my previous post Use a Lightning Pill as a simple KPI. And the power of Flows! I made a simple component to show integer KPIs.

In this article, I share a component that shows several KPIs in a row. 


Objective

We will create a component that will allow us to insert several KPI Integer Components in a line, using only SLDS formatting.

List Component, a container for KPI Integer


Specification


Name Label Type Required Default Description
alignment Alignment String false center The alignment of the KPIs will be: center, left, or right
data Items Metadata String true A list of values separated by #;#: DATA#;#DATA...

Where DATA is a list a CSV pair of values:

label:=value,description:=value,iconName:=category:icon,flowName:=Flow_API_Name,errorFormula:=value

Check my post about the KPI Component where the definition of each property is.

 

KPI Integer Bar Component

<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:attribute name="arrayItems" type="Array" access="global"></aura:attribute>
    <aura:attribute name="alignment" type="String" access="global" default="center"></aura:attribute>
    <aura:attribute name="data" type="String" access="global"></aura:attribute>

    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

    <div class="slds-size_3-of-3 slds-box slds-box_xx-small" style="background:#ecebea;">
        <div class="slds-clearfix">
            <ul class="{! v.alignment == 'center' ? 'slds-list_horizontal slds-has-dividers_left slds-has-block-links slds-align_absolute-center' : 
                       v.alignment == 'left' ? 'slds-list_horizontal slds-has-dividers_left slds-has-block-links slds-float_left' : 
                       'slds-list_horizontal slds-has-dividers_left slds-has-block-links slds-float_right'}">
                <aura:iteration items="{!v.arrayItems}" var="item">
                    <li class="slds-item"> 
                        <c:KPI_Int label="{!item.label}" recordId="{!v.recordId}" description="{!item.description}" 
                                   iconName="{!item.iconName}" flowName="{!item.flowName}" errorFormula="{!item.errorFormula}"></c:KPI_Int>
                    </li>
                </aura:iteration>
            </ul>
        </div>
    </div>
</aura:component>

 

KPI Integer Bar Design

<design:component label="KPI Integer Bar">
    <design:attribute name="alignment" label="Alignment" default="center" datasource="center,left,right"/>
    <design:attribute name="data" label="Items Metadata" description="DATA#;#DATA#;#DATA,... where DATA is: label:=value,description:=value,iconName:=category:icon,flowName:=Flow_API_Name" required="true"/>
</design:component>

 

KPI Integer Bar Controller

({
    doInit : function(component, event, helper) 
    {
        // lets get the data that defines the properties of each integer KPI and make an array of them 
        let dataItems = component.get("v.data").split('#;#'); // this separator is REQUIERED
        let arrItems = new Array(dataItems.length);

        for (var i=0; i<dataItems.length; i++)
        {
            // Validate the commas in the item ...
            if ((dataItems[i].match(/,/g) || []).length != 3)
            {
                throw new Error("KPI Integer Bar ERROR: wrong number of properties in an element. HINT: check the commas.");
            }

            // ... and the property assignment symbol :=
            if ((dataItems[i].match(/:=/g) || []).length != 4)
            {
                throw new Error("KPI Integer Bar ERROR: wrong number of properties in an element. HINT: check the ':=' chars.");
            }
            
            // now we have something like label:=<value>,description:=<value>,iconName:=<standard:quotes>,flowName:=<API name>,errorFormula:=<value>
            // and we will create a map with all the preperties, because the order they were entered is not important
            let properties = dataItems[i].split(',');
            var KPI = new Map(); 
            for (var j=0; j<properties.length; j++)
            {
                KPI.set(properties[j].split(':=')[0], properties[j].split(':=')[1]);
            }
            
            // the KPI will go to the array as an object, in order to be able to reference the properties in the aura:iteration
            var kpiObject = { label:KPI.get('label'), description:KPI.get('description'), iconName:KPI.get('iconName'), 
                              flowName:KPI.get('flowName'), errorFormula:KPI.get('errorFormula')};
            arrItems[i] = kpiObject;
        }

        component.set("v.arrayItems", arrItems);
    },
})

 

And that's all!

We have a component that allows us to align the KPI Integer components to the LEFT, the RIGHT, or the CENTER of the bar that contains them.

 

Is there any known problem with this Component?

I didn't test it thoroughly, but, for sure, the number of KPIs in the bar will depend on the length of the String parameter Items Metadata and the length of the Labels and Tooltips you use.

 

Wrap-up

This component was the obvious conclusion for a component like KPI Integer. A container for the KPIs was needed.

It wasn't that difficult to develop an HTML LIST formatted with SLDS as horizontal and containing only KPI Integer components.

The actual power is in the KPI Integer component, and the trick is in the value of the Items Metadata property, be careful with its format 😉.

 

Resources and Acknowledgement

Salesforce Developers and Lightning Design Systems were very useful to do this component.

What Next?

Can we create a component with a Drop Zone that can be the container for our KPI Integer component? I know it is not simple, and as far as I know, Drag & Drop is not supported in design mode (from the Visual Editor Palette Items), but I will give it a try.




"... the ability to simplify means to eliminate the unnecessary so that the necessary may speak ..."
Hans Hofmann, American painter 

Comments