Building a Sign-up Form with Lightning Components (Part 3)

This is the final part to my multi-part series on building a sign-up form using Lightning Components. If you have read the previous two posts in this series please read part 1 and part 2 before proceeding.

We ended part 2 with implementing a saving spinner, UI messaging, and data validity enforcement. Today we will be adding two more items to close off this project.

  • Allowing the user to remove forms added to the page.
  • Configuring a Salesforce community that allows the sign-up form to be accessed publicly without logging into Salesforce.

Let’s get started!

Adding Capability to Remove Forms

In part 1 we added the ability to have the user added multiple people in the sign up form. If we are going let people add additional forms then we might as well add the ability to remove them as well.

Updates to the PublicFormNewLeadComp Component

To handle request to remove a form we will be registering a new event called “removeLeadFormEvent”.

<aura:component >
<aura:attribute name=”count” type=”Decimal” />
<aura:attribute name=”newLead” type=”Lead” default=”{‘sobjectType’:’Lead’}”/>
<aura:attribute name=”showAddLeadBtn” type=”Boolean” default=”true”/>
<aura:attribute name=”showMsg” type=”Boolean” default=”false”/>
<aura:attribute name=”errMsg” type=”String” /><aura:registerEvent name=”addFormEvent” type=”c:addLeadFormEvent”/>
<aura:registerEvent name=”removeFormEvent” type=”c:removeLeadFormEvent”/><lightning:card >
<aura:set attribute=”title”>
New Sign-up ({!v.count})
</aura:set>

<lightning:recordEditForm objectApiName=”Lead” aura:id=”leadEdit”>
<!—->
<aura:if isTrue=”{!v.showMsg}” >
<ui:message aura:id=”msg” severity=”warning” class=”font-bold”>{!v.errMsg}</ui:message>
</aura:if>
<lightning:input label=”First Name” value=”{!v.newLead.FirstName}” required=”true”/>
<lightning:input label=”Last Name” value=”{!v.newLead.LastName}” required=”true”/>
<lightning:input label=”Company” value=”{!v.newLead.Company}” required=”true”/>
<lightning:input label=”Email” value=”{!v.newLead.Email}” required=”true”/>
<lightning:input label=”Phone” value=”{!v.newLead.Phone}” required=”true”/>

</lightning:recordEditForm>
<br />
<br />

<aura:if isTrue=”{!v.showAddLeadBtn}”>

<lightning:button variant=”brand” label=”Add Additional Person” onclick=”{!c.fireAddFormEvent}”/>
<aura:if isTrue=”{!v.count > 1}”>
<lightning:button variant=”destructive” label=”Remove Person” onclick=”{!c.fireRemoveFormEvent}” />
</aura:if>
</aura:if>

</lightning:card>

</aura:component>

In addition to the new event registration a lightning button will be added where users can click to remove the latest added form. The button is only displayed if it is not the initial form that is loaded since we want at least one form to be displayed for the sign-up page. The logic is controlled by an aura:if component that only renders the “Remove Person” button when the count attribute is greater than 1.

The button itself executes a new controller function labeled as fireRemoveFormEvent which will handle firing the remove event notifying any components that is listening for the event.

The Event

The remove event consists of two attributes that will store the current count attribute value of the lead form component and the count attribute value of the previously created component. The count values will be used by the PublicMainFormComp component when it detects the event fire.

<aura:event type=”COMPONENT” description=”Notifies listener to remove latest added form”>
<aura:attribute name=”currentCnt” type=”Decimal” />
<aura:attribute name=”previousCnt” type=”Decimal” />
</aura:event>

Updates to the PublicFormNewLeadComp Controller

As mentioned above, the Remove Person lightning button calls the fireRemoveFormEvent controller function. The function gets the count attribute value and the registered remove eventI The parameters are set and the event is fired.

fireRemoveFormEvent : function(component, event, helper){
var currCnt = component.get(‘v.count’);
var removeEvt = component.getEvent(‘removeFormEvent’);console.log(‘current count before event fire: ‘ + currCnt);removeEvt.setParams(
{
‘currentCnt’ : (currCnt-2),
‘previousCnt’ : –currCnt
}
);

removeEvt.fire();

},

Notice that I am decrementing the current count value by two when setting it as a parameter for the event. You might be asking why I am doing this. Recall in part 1 of this series I am dynamically creating form components and in order to accomplish that I needed to add the v.body attribute to the end of the body of the PublicFormMainComp component. As far as I can tell any components dynamically added to page document will start with an index position of zero (0). I needed to take in consideration of this in order to reference to correct component to be removed when handling the event in the PublicFormMainComp controller. So for instance if the count value is 2, the component’s position index is actually at zero (since the first form component is not dynamically added to to the page document.

Updates to the PublicFormMainComp Component

The only addition to this component is handling the event being fired.

<aura:component controller=”PublicContactFormController”>


<aura:attribute name=”personCnt” type=”Decimal” default=”1″/>
<aura:attribute name=”showSpinner” type=”Boolean” default=”false” />
<aura:attribute name=”showMessage” type=”Boolean” default=”false” />
<aura:attribute name=”showForm” type=”Boolean” default=”true” />
<aura:attribute name=”message” type=”String” />


<aura:handler name=”addFormEvent” event=”c:addLeadFormEvent” action=”{!c.handleAddLeadEvent}” />
<aura:handler name=”removeFormEvent” event=”c:removeLeadFormEvent” action=”{!c.handleRemoveLeadEvent}” />

…………………………………..

The controller function handleRemoveLeadEvent will be called when the event occurs.

Updates to the PublicFormMainComp Controller

As mentioned above the event handler will execute the handleRemoveLeadEvent function. The function will retrieve the parameter values from the fired event. The body of the document will also be retrieved from the component. The value of currCnt will be used to remove the latest lead form component from the page document via the body.splice function.

handleRemoveLeadEvent : function(component, event, helper){
console.log(‘handling remove form event’);
var currCnt = parseInt(event.getParam(“currentCnt”));
var prevCnt = event.getParam(“previousCnt”);
var body = component.get(‘v.body’);console.log(‘current index: ‘ + currCnt);
console.log(‘previous count: ‘ + prevCnt);//remove component by current count as index
body.splice(currCnt, 1);

//push updated body back to component
component.set(“v.body”, body);

var prevFormCmp = component.find(‘cntFrm’ + prevCnt);

if(prevFormCmp){
prevFormCmp.set(‘v.showAddLeadBtn’, true);
}

var personCnt = component.get(‘v.personCnt’);
–personCnt;
component.set(‘v.personCnt’, personCnt);

},

After removing the component from the body we will push the update back to the component by setting the value of v.body. The previously added component will also be updated so that the “Add Additional Person” button is displayed (since it is now the most current lead form component on the page). The personCnt attribute will also be decremented by 1 in order to keep the correct count of lead form components.

Update Lightning App to be publicly accessible

Making the lightning app publicly accessible requires the user of a Salesforce community and using Lightning Out and Allow Guest Access features. I will set up a community that uses Tab + Visualforce and have the main page load a Visualforce page where I will surfacing the lightning app.

The Community

We will be using a Tab + Visualforce community for this exercise.

From the Admin settings of the community I will set the Community Home to the Visualforce page that will be hosting the Lightning App.

Lightning Out App

I created a separate Lightning App that extends ltng:outApp and ltng:allowGuestAccess. The visualforce page will be referencing this new app. The app consists of a dependency referencing the PublicFormMainComp component.

<aura:application extends=”ltng:outApp” implements=”ltng:allowGuestAccess”>
<aura:dependency resource=”c:PublicFormMainComp” />
</aura:application>

The Visualforce Page

The page will not be using any visualforce components, we will be using a div to indicate where the lightning app and its components should be loaded. In order to use lightning components within a visualforce page we must include the apex:includeLightning tag which will include all resources needed.

<apex:page standardStylesheets=”false” showHeader=”false” sidebar=”false”>

<apex:includeLightning />

<div id=”lightning”>

</div>

<script type=”text/javascript”>

$Lightning.use(“c:PublicFormLtngOutApp”, // name of the Lightning app
function() { // Callback once framework and app loaded
$Lightning.createComponent(
“c:PublicFormMainComp”, // top-level component of your app
{ }, // attributes to set on the component when created
“lightning”, // the DOM location to insert the component
function(cmp) {
console.log(‘component created’);
}
);
},
https://tccloudlab1-developer-edition.na40.force.com/signup&#8217; // Community endpoint
);

</script>

</apex:page>

The above javascript code will execute which will load the lightning app by referencing the name of the app, the name of the dependent component, a callback function (which will only print a message to console for this page), and the community url.

The url referenced in the code sample actually does work so feel free to check out the components in action for yourselves (I put measures in place to clear our any lead records created in case anyone wants to use up all the data storage of the dev org 😉 ).

Conclusion

This multi-part series now draws to an end. I hope you enjoyed reading the posts and found it helpful in learning how to build lightning apps. All completed code is already available my Github repo so please feel free to check it out from there as well!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.