Saturday, December 22, 2018

Overlay Library for modals and popovers

Messages can be displayed in modals and popovers. Modals display a dialog in the foreground of the app, interrupting a user’s workflow and drawing attention to the message. Popovers display relevant information when you hover over a reference element.
Include one <lightning:overlayLibrary aura:id="overlayLib"/> tag in the component that triggers the messages, where aura:id is a unique local ID. Only one tag is needed for multiple messages.

Modals

A modal blocks everything else on the page until it’s dismissed. A modal must be acknowledged before a user regains control over the app again. A modal is triggered by user interaction, which can be a click of a button or link. The modal header, body, and footer are customizable. Pressing the Escape key or clicking the close button closes the modal.
Modals inherit styling from modals in the Lightning Design System.
Here’s an example that contains a button. When clicked, the button displays a modal with a custom body.

<aura:component>
    <lightning:overlayLibrary aura:id="overlayLib"/>
    <lightning:button name="modal" label="Show Modal" onclick="{!c.handleShowModal}"/>
</aura:component>

This client-side controller displays the modal. To create and display a modal, pass in the modal attributes using component.find('overlayLib').showCustomModal(), where overlayLib matches the aura:id on the lightning:overlayLibrary instance.

({
    handleShowModal: function(component, evt, helper) {
        var modalBody;
        $A.createComponent("lightning:button",
              {
                "aura:id": "findableAuraId",
                "label": "Press Me",
                "onclick": cmp.getReference("c.handlePress")
}, function(content, status) { if (status === "SUCCESS") { modalBody = content; component.find('overlayLib').showCustomModal({ header: "Application Confirmation", body: modalBody, showCloseButton: true, cssClass: "mymodal", closeCallback: function() { alert('You closed the alert!'); } }) } }); } })
================

Popovers

Popovers display contextual information on a reference element and don’t interrupt like modals. A popover can be displayed when you hover over or click the reference element. Pressing the Escape key closes the popover. The default positioning of the popover is on the right of the reference element.
Popovers inherit styling from popovers in the Lightning Design System.
Here’s an example that contains a button and a reference div element. When clicked, the button displays a popover. The popover also displays when you hover over the div element.

<aura:component>
    <lightning:overlayLibrary aura:id="overlayLib"/>
    <lightning:button name="popover" label="Show Popover" onclick="{!c.handleShowPopover}"/>
    <div class="mypopover" onmouseover="{!c.handleShowPopover}">Popover should display if you hover over here.</div>
</aura:component>
This client-side controller displays the popover. Although this example passes in a string to the popover body, you can also pass in a custom component like in the previous modal example. Any custom CSS class you add must be accompanied by the cMyCmp class, where c is your namespace and MyCmp is the name of the component that creates the popover. Adding this class ensures that the custom styling is properly scoped.

({
    handleShowPopover : function(component, event, helper) {
        component.find('overlayLib').showCustomPopover({
            body: "Popovers are positioned relative to a reference element",
            referenceSelector: ".mypopover",
            cssClass: "popoverclass, cMyCmp"
        }).then(function (overlay) {
            setTimeout(function(){ 
                //close the popover after 3 seconds
                overlay.close(); 
            }, 3000);
        });
    }
})

Notifications Library powers to create Toast and Notices

We have been using window.alert, window.confirm, window.prompt for various reasons, all these screens runs in synchronous mode and pauses your execution logic until clicks on a button.

Below are the offerings of the Lightning frame work in the for of Notifications Library which runs in asynchronous mode

Messages can be displayed in notices and toasts. Notices alert users to system-related issues and updates. Toasts enable you to provide feedback and serve as a confirmation mechanism after the user takes an action.
Include one <lightning:notificationsLibrary aura:id="notifLib"/> tag in the component that triggers the notifications, where aura:id is a unique local ID. Only one tag is needed for multiple notifications.

Notices

Notices interrupt the user's workflow and block everything else on the page. Notices must be acknowledged before a user regains control over the app again. As such, use notices sparingly. They are not suitable for confirming a user’s action, such as before deleting a record. To dismiss the notice, only the OK button is currently supported.
Notices inherit styling from prompts in the Lightning Design System.
Here’s an example that contains a button. When clicked, the button displays a notice with the error variant.
==================================================================================
<aura:component implements="flexipage:availableForAllPageTypes" access="global" >
  <lightning:notificationsLibrary aura:id="notifLib"/>
    <lightning:button name="notice" label="Show Notice" onclick="{!c.handleShowNotice}"/>
    
    <lightning:button name="toast" label="Show Toast" onclick="{!c.handleShowToast}"/>
</aura:component>
===================================================================================

({    
    handleShowNotice : function(component, event, helper) {
        component.find('notifLib').showNotice({
            "variant": "error",
            "header": "Something has gone wrong!",
            "message": "Unfortunately, there was a problem updating the record.",
            closeCallback: function() {
                alert('You closed the show notice!');
            }
        });
    },
      handleShowToast : function(component, event, helper) {
        component.find('notifLib').showToast({
            "title": "Notif library Success!",
            "message": "The record has been updated successfully.",
            "variant": "success"
        });
    }
})
===============================================================================
Show toast Example:



Show Modal Example:






Tuesday, October 16, 2018

Another advanced way of Parent to child component communication

We have been using below two techniques to communicate from parent to child. In addition to the below techniques, introducing advance way of communication with the component body technique.




Component Body

The root-level tag of every component is <aura:component>Every component inherits the body attribute from <aura:component>. We dont need to create a separate attribute to handle the v.body.
 Any free markup that is not enclosed in one of the tags allowed in a component is assumed to be part of the body and is set in the body attribute.
The body attribute has type Aura.Component[]. It can be an array of one component, or an empty array, but it's always an array.
In a component, use “v” to access the collection of attributes. For example, {!v.body} outputs the body of the component.

Below is the perfect example for body communication technique. Follow the step by step process to see the end result. Its gonna be very advanced level of communication technique.

===========
Step 1:  Markup : Coldata   (below component just acts like a programmatic abstraction, it wont display any data). Sole purpose of the below component is to pass the data to the Childcmp.
=========
<aura:component >
     <aura:attribute name="Firstname" type="string" />
     <aura:attribute name="LastName" type="string" />
     <aura:attribute name="age" type="Integer" />
</aura:component>

==========
Step 2:  Markup :Coldata2 (Again below component also just acts like a programmatic abstraction, it wont display any data). Sole purpose of the below component is to pass the data to the Childcmp.
=========

<aura:component >
     <aura:attribute name="att1" type="string" />
     <aura:attribute name="att2" type="string" />
</aura:component>

=========
Step 3:  Markup :Childcmp 
=========

<aura:component >
    <aura:attribute name="subtagsdata" type="object[]" />
     <aura:attribute name="subtagsdata2" type="object[]" />
    <aura:handler name="init" value="{!this}"  action="{!c.doinit}" />
    
    {!v.body}  <!---without this attribute you would not be able to access the body placed in the below parent component(see step 5) -->
    <table border="1">
        <tr>
        <th>FirstName</th>
             <th>LastName</th>
             <th>Age</th>
        </tr>
     <aura:iteration items="{!v.subtagsdata}" var="item">
          <tr>
        <td> {!item.Fname} </td>
         <td>  {!item.Lname}  </td>
         <td>  {!item.age} </td>
                </tr>
    </aura:iteration>
    </table>
</aura:component>

========
Step 4:  JavaScript controller:Childcmp 
========

({
doinit : function(component, event, helper) {
        var body=component.get("v.body");
        var coldata=[];
         var coldata2=[];
        
        for(var i=0; i<body.length;i++){
            /* below code differentiates two different components instances */
            if(body[i].isInstanceOf("c:Coldata")){
            coldata.push(
                {
                 Fname:body[i].get('v.Firstname'),
                 Lname:body[i].get('v.LastName'),
                 age:body[i].get('v.age')
                
                }
            
            );} else{
                
                 coldata2.push(
                {
                 att1:body[i].get('v.att1'),
                 att2:body[i].get('v.att2')
                
                }
           
            );
            }
        }
        
        component.set('v.subtagsdata',coldata);
         component.set('v.subtagsdata2',coldata2);
        console.log('%%%%Col data 1%%%%'+JSON.stringify(component.get('v.subtagsdata')));
         console.log('%%%%Col data 2%%%%'+JSON.stringify(component.get('v.subtagsdata2')));
}
})
=============
Step 5:  Markup : Parentcmp 
=============
<aura:component >
    <aura:attribute name="fn" type="string" default="Oliva trainings"/>
    <c:Childcmp >
        <c:Coldata Firstname="Dave" LastName="Oliva" age="28" />
        
          <c:Coldata Firstname="Dave1" LastName="Oliva1" age="29" />
        
          <c:Coldata Firstname="Dave2" LastName="Oliva2" age="30" />
        
          <c:Coldata Firstname="Dave3" LastName="Oliva3" age="31" />
        
        <c:Coldata2 att1="col2dataatt1" att2="col2dataatt2" />
        
          <c:Coldata2 att1="col2dataatt1" att2="col2dataatt2" />
               
    </c:Childcmp>  
</aura:component>

=========
Step 6:  Markup :Bodycommunication 
=========

<aura:application >
    <c:Parentcmp />
</aura:application>

Final output looks as below.


Thursday, September 13, 2018

Best way of using lightning helper method and Switch statements

JavaScript Controllers and Helpers play a key role in Lightning Components Framework. One of the first things people new to the framework wonder is: What exactly is the difference between JavaScript Controllers and JavaScript Helpers. 

 To understand it better, here I'm taking simple example to determine what would get from Helper and why we need to delegate logic to the helper from controller. Though this code incorporated with basic logic like add, sub, mul and div. It has lot of take away's in terms of frame work concepts.  Out put looks as below.







Earlier I have provided similar kind of code to demonstrate getters, setters, hide and seek mechanism, and many more with very basic example to keep the things simple. If you want to check it, please hit this link Simple calci for the same. 

================

Step 1: create a component with the name "NoHelpercmp" and  copy the below mark up code in the new component

Mark up: c:NoHelpercmp 

================
<aura:component implements="flexipage:availableForAllPageTypes" access="global" >

    

    <aura:attribute name="num1" type="integer" />

    <aura:attribute name="num2" type="integer" />    

    <aura:attribute name="num3" type="integer" />

    <aura:attribute name="str" type="String" default="None of them selected"/>
    <lightning:card variant="Narrow" title="My Caluclations" >

        <lightning:input name="input1" label="Enter first number" type="number" value="{!v.num1}" aura:id="abc" id="ccc"/>

        <lightning:input name="input2" label="Enter second number" type="number" value="{!v.num2}" aura:id="xyz"/>

        {!v.str}     <ui:outputNumber value="{!v.num3}"/>

        <aura:set attribute="actions">

            <lightning:buttonGroup >

                <lightning:button label="Div" variant="brand" onclick="{!c.Div}" title="Div Method"  />

                <lightning:button label="Add" variant="success" onclick="{!c.Add}" title="Add Method"  />

                <lightning:button label="Sub" variant="brand" onclick="{!c.Sub}"  />

                <lightning:button label="Mul" variant="destructive"  onclick="{!c.Mul}"  class=""/>

            </lightning:buttonGroup>

        </aura:set>
    </lightning:card>

</aura:component>

==============

Step 2: copy the below code and paste it in the NoHelpercmp Controller

=================

({
    Sub : function(component, event, helper) {

     var n1=parseInt(component.find("abc").get("v.value"));  //repeated code

         var n2=parseInt(component.find("xyz").get("v.value"));  //repeated code

         var c=n1-n2; 

         component.set("v.str","sub of 2 number");

          component.set("v.num3",c);

},

    Mul : function(component, event, helper) {

         var n1=parseInt(component.find("abc").get("v.value"));  //repeated code
         var n2=parseInt(component.find("xyz").get("v.value"));  //repeated code

         var c=n1*n2; 

          component.set("v.str","Mul of 2 number");

      component.set("v.num3",c);

},
Add : function(component, event, helper) {

     var n1=parseInt(component.find("abc").get("v.value"));  //repeated code

         var n2=parseInt(component.find("xyz").get("v.value"));  //repeated code

         var c=n1+n2; 

         component.set("v.str","sub of 2 number");

          component.set("v.num3",c);

},

    Div : function(component, event, helper) {

         var n1=parseInt(component.find("abc").get("v.value"));  //repeated code

         var n2=parseInt(component.find("xyz").get("v.value"));  //repeated code

         var c=n1%n2; 

          component.set("v.str","Mul of 2 number");

      component.set("v.num3",c);

}

})



============

Test the above component by using below application container, It still works but its not a best practice to handle the logic in the controller. Your Js controller methods were not desinged for re-usability  purpose.

step 3 : create aura:application container and replace following code and preview it.

============

<aura:application extends="force:slds">

    <c:NoHelpercmp/>


</aura:application>

================

Mark up: c:Helpercmp 

Follow the similar kind of steps which you followed from step 1 to step 3 and then additionally use the step 4(helper function) which is mentioned below.

================

<aura:component implements="flexipage:availableForAllPageTypes" access="global" >

    

    <aura:attribute name="num1" type="integer" />

    <aura:attribute name="num2" type="integer" />    

    <aura:attribute name="num3" type="integer" />

    <aura:attribute name="str" type="String" default="None of them selected"/>

    
    <lightning:card variant="Narrow" title="My Caluclations" >

        <lightning:input name="input1" label="Enter first number" type="number" value="{!v.num1}" aura:id="abc" id="ccc"/>


        <lightning:input name="input2" label="Enter second number" type="number" value="{!v.num2}" aura:id="xyz"/>

        {!v.str}     <ui:outputNumber value="{!v.num3}"/>

        <aura:set attribute="actions">

            <lightning:buttonGroup >

                <lightning:button label="Div" variant="brand" onclick="{!c.Allcaluclations}" title="Div Method"  />

                <lightning:button label="Add" variant="success" onclick="{!c.Allcaluclations}" title="Add Method"  />

                <lightning:button label="Sub" variant="brand" onclick="{!c.Allcaluclations}"  />

                <lightning:button label="Mul" variant="destructive"  onclick="{!c.Allcaluclations}"  />

            </lightning:buttonGroup>

        </aura:set>

        

        

    </lightning:card>

</aura:component>



=================

Js controller code with delegates business logic to helper.

=================



({

Allcaluclations : function(component, event, helper) {

      helper.Mymethod(component, event, helper);

}

})


==============

Step 4: Helper to perform all the calculations with in the same function

==============

({

    Mymethod : function(component, event, helper) {

        var buttonlabel=event.getSource().get('v.label');

        this.Myswtich(component, event, helper,buttonlabel);


    },


     Myswtich : function(component, event, helper,buttonlabel) {

            var a=parseInt(component.get('v.num1'));

        var b=parseInt(component.get('v.num2'));

        switch (buttonlabel) {

            case 'Add':

                component.set("v.str","Addition of two numbers");       

                var c=a+b; 

                break;

            case 'Sub':

                component.set("v.str","Sub of two numbers");

                var c=a-b; 

                break;

            case 'Mul':

                component.set("v.str","Mul of two numbers");

                var c=a*b; 

                break; 

            case 'Div':

                component.set("v.str","Div of two numbers");

                var c=a%b; 

                break; 

        }

        
        component.set("v.num3",c);


     }

    

})



============

Test the above component by using below application container.

============



<aura:application extends="force:slds">

    
    <c:Helpercmp/>



</aura:application>