<< Previous | Home | Next >>

Using component.find in Salesforce Lightning Components

When developing Salesforce Lightning Components you very often use the aura:id attribute on components to tag them and component.find to find them again. This works very well and is documented nicely in the documentation (Finding Components by ID). If however you tag a component using aura:id in an iterator you may not know how many resulting components will be on the page. The component.find method may return undefined (if no matching components), a component instance (if a single match was found) or an array of component instances if multiple components with a matching aura:id was found. This is fine but if you want to loop over any found component Javascript may give you a headache as the resulting variable may contain an array or an object instance. Hmmm... You can either using Vanilla Javascript to figure out whether it's array (or cheat and use $A.util.isArray) and write code for the array case and code for the single instance case --- or you can take the short route.

I always take the short route...

Say you had markup like this using an aura:iteration component to loop over a variable containg 0, 1 or many values.

<aura:iteration var="item" items="{!v.items}">
	<lightning:input type="checkbox" label="{!item}" aura:id="mycheckbox" />
</aura:iteration>

Contrast the approach using "isArray"

const cmps = component.find("mycheckbox");
if (!cmps) return;
if ($A.util.isArray(cmps)) {
    cmps.forEach(cmp => {
        // do stuff...
        cmp.set("v.checked", true);
    })
} else {
    // do stuff on the instance
    cmp.set("v.checked", true);
}
...to the approach of simply concatenating into an array... I find this much nicer, cleaner and it avoids the duplication of code between the single instance and array case. If I know there would always be at least one component it could even be done on a single line i.e. loose the undefined check on the second line. Javascript terse-ness heaven!!
const cmps = component.find("mycheckbox");
if (!cmps) return;
[].concat(cmps).forEach(cmp => cmp.set("v.checked", true));

! vs # in Salesforce Lightning Components

Often when you read tutorials on developing Salesforce Lightning components they all contains expressions when passing data and variables into other components. Like say you have an attribute as an array and would like to iterate over the elements:

<aura:attribute name="arr" type="string[]" default="['foo', 'bar', 'baz']" />

<ul class="slds-list--dotted">
<aura:iteration items="{!v.arr}" var="item">
    <li>{!item}</li>
</aura:iteration>
</ul>
Now this is a very simple example but it shows the point. This component shows a simple bullet list with items - when the array attribute ("arr") changes the list will recalculate and update. Often this is what you want but sometimes the array will never change. A better way to do this - especially with arrays as Javascript has not easy / performant way to see if an array actually changed - is to use # instead of ! in your expressions. # means that the expression will not automatically update when the attribute is changed which may speed things up considerably when there are many attributes and many components on the page. Fewer attributes to monitor for changes by the framework leads to better perfornance.
<aura:attribute name="arr" type="string[]" default="['foo', 'bar', 'baz']" />

<ul class="slds-list--dotted">
<aura:iteration items="{#v.arr}" var="item">
    <li>{#item}</li>
</aura:iteration>
</ul>
Another reason for using # instead of ! could be to control the data binding between parent and child components.

There is a nice article on the matter in the Salesforce documentation - Data Binding Between Components.

Salesforce week 24

Last week was all about getting the next component for my customer into production. For one of their business lines they had some very specific requirements for a search so we built a search from scratch. Now Salesforce comes with a built in fulltext search functionality but the customer only wanted results from a specific object type and a specific record type at that. So that's what we built. The solution was deployed on Thursday and have been running since. Main hickup in the deployment was some weird "cannot access childNodes of null" errors that kept surfacing from the Lightning component I built to display what search filters were in place. The component was basically just a wrapper around a number of arrays showing the filters as pills and showing a filter count. The markup was basically like this (c:Pill is simply a wrapper component for the pill):

<div class="filters">
    <div>{!v.filtersCount} filters added</div>
    <div aura:id="filters_expand" class="">
        <aura:iteration var="filter" items="{!v.accountDisplayObjects}">
            <c:Pill displayText="{#filter.displayText}" object="{#filter}" colorClass="orange" />
        </aura:iteration>
        ...
        ...
        <aura:iteration var="filter" items="{!v.geoDisplayObjects}">
            <c:Pill displayText="{#filter.displayText}" object="{#filter}" colorClass="lightorange" />
        </aura:iteration>
    </div>
</div>
We kept however getting the errors and I narrowed down the issue to being with the aura:iteration components and if multiple subsequence display object arrays were being changed after one another. The fix turned out - as always - to be very simple. I simply wrapped each aura:iteration component in its own span-tag.
<div class="filters">
    <div>{!v.filtersCount} filters added</div>
    <div aura:id="filters_expand" class="">
        <span><aura:iteration var="filter" items="{!v.accountDisplayObjects}">
            <c:Pill displayText="{#filter.displayText}" object="{#filter}" colorClass="orange" />
        </aura:iteration></span>
        ...
        ...
        <span><aura:iteration var="filter" items="{!v.geoDisplayObjects}">
            <c:Pill displayText="{#filter.displayText}" object="{#filter}" colorClass="lightorange" />
        </aura:iteration></span>
    </div>
</div>
Oh well another bug bites the dust and another lesson learned...

Besides this we got a new team member as another one of the existing team members is graduating into management. So now we also have a Salesforce Business Architect from the UK office. Nice.

What did I learn

  • Span your aura:iteration components
  • Troubleshooting Lightning Style
  • There is a reason for having a staging environment but make sure it contains representative data...

Status after this week

Trailhead points: 85325
Trailhead badges: 100
Certifications: 5 (Salesforce Certified Administrator, Salesforce Certified Platform App Builder, Salesforce Certified Advanced Administrator, Salesforce Certified Sales Cloud Consultant, Salesforce Certified Service Cloud Consultant)

Tags :

Salesforce week 20-23

Wow I'm behind on these... I'll have to sum up the last 4 weeks and get better at doing these.

At the end of March I made Trailhead Ranger! I'm very happy that the ambitious goal of making Trailhead Ranger by the end of March was accomplished. On the Wednesday night in the bar of my second home (Radisson Hotel in Stockholm) I earned the last badges to bring me over the line. Great! I hurried over to my V2MOM to complete that measure on my FY18 V2MOM. Check! Next up is getting started on my Certified Developer I certification.

I also received emails about certification renewal. Oh well...

Last week was of course the terrorist attack in Stockholm :( The truck hit the building just 100m or so from one of the Salesforce offices. So sad and frustrating why people cannot just agree to disagree....

What else? I've been head down in work finishing of the first release at my customer I have been a part of and working on new existing stuff. I already had one big component deployed to production and on next Tuesday my next big contribution is being rolled into production and I'm really excited about it. Both are Salesforce Lightning components and they are pretty slick. Really shows what can be done. Once these are out I promise to record a video and post it. I also have loads of experiences and new stuff about Lightning development to share here on this blog.

On a more sad note my on-boarding buddy Rasmus got a new role inside Salesforce and will be switching teams. I'm really excited for him but I'm sad to see him leave our team and my current project. He's really a nice guy and a super competent architect. Glad he's still part of the Ohana though.

What did I learn

  • Lightning, Lightning, Lightning
  • More Lightning
  • Funky quirks about picklists from SOQL now that all picklists contains both an alias and a value
  • APEX performs really really well

Status after this week

Trailhead points: 85325
Trailhead badges: 100
Certifications: 5 (Salesforce Certified Administrator, Salesforce Certified Platform App Builder, Salesforce Certified Advanced Administrator, Salesforce Certified Sales Cloud Consultant, Salesforce Certified Service Cloud Consultant)

Tags :

Case in point - why we have API limits

This week the customer I'm working for went live with the next phase of their Salesforce rollout. The phase includes a Contact Sychronization feature where Salesforce contact objects are synchronized to users mobile devices using their Google Account. The contacts are flagged either in bulk or specifically using a Lightning Component on the Contact Page, has Salesforce1 integration to allow users to perform and manage sync on the go as well as a delegation feature to allow other users to manage their synchronization settings on their behalf. Think managing partners etc...

Anyway we went live on Monday morning and Tuesday morning the news hit. We had hit the API limit. The API limit is a hard upper limit on the number of API calls any customer may do towards Salesforce from external applications. There are a number of factors deciding the actual limit such as user count, license types etc. but in this case the limit was 500.000 calls in a 24 hour rolling period. We were at 555.593! Not good and and it was only 9am. Hmmm what could be wrong?

After looking into the matter we found out that the culprit was - you guessed it - the Contact Sync. The actual sync component that does the reads from Salesforce and writes to the Google Accounts of the Contact Sync feature was set to run every 10 seconds and not every 15 minutes as planned. At this rate the customer would hit an estimated 20.000.000 (20 million) API calls in a 24 hour window. Not good. A simple reconfiguration and we were back on track.

Talking to the friendly people at Salesforce Support we were even given an extra allowance of API calls for the day and the customer were back in business.

But case in point - this is exactly why there are (API) limits. If you hit the limits you are probably doing something you shouldn't. Well hopefully that's why you hit the limit.

Tags :

Salesforce week 19

Another busy week where all focus was on getting our customer ready for the launch of their next release on 3 April. Again I've been a bit optimistic about my estimates but all it good and the customer is happy. They just signed an extension to our contract so we will probably be here until the end of the year. Great testament to the value we are providing. Next week I'm going to be two days in Stockholm and 3 days the following week in the week of the release. After that we have a short sprint of 2 weeks to complete a custom search component - again entirely in Lightning. Cool. Cool. Cool.

On the personal front I felt great joy when talking to my former employer. The last thing I did before I left them in November was deliver a project integrating the OnTime Group Calendar for Microsoft with the Danish national system for sending SMS reminders called NemSMS. Intravision is getting ready to sell the solution to the second customer which is great by itself but the potential customer has been in contact with the existing customer to gather experience with the system and their only comments were: "simple to use" and "just works". Great!! I have to make a mental note to do a write up of the solution.

What did I learn

  • Another busy week
  • Writing your work V2MOM makes you want to do it on a personal front but it may ruin my procrastination

Status after this week

Trailhead points: 80150
Trailhead badges: 82
Certifications: 5 (Salesforce Certified Administrator, Salesforce Certified Platform App Builder, Salesforce Certified Advanced Administrator, Salesforce Certified Sales Cloud Consultant, Salesforce Certified Service Cloud Consultant)

Tags :

Salesforce week 18

This week marked my 4th month at Salesforce! That's so crazy. 4 months already - where did the time go? Joining Salesforce was a big decision and since I joined the time has flown by. It has taken some time but I'm starting to feel at home in my new role in CSG here at Salesforce. As always change is hard and a change of job is no different. Well it's probably hard for me to say that as this is the first "real" job I've had as I've been self employed / co-owner of the company I've worked at for the last 20 some years. But it has been a bit hard but as I said before I'm starting to feel at home in the #SalesforceOhana.

It's been a bit of a change from being at a tiny ISV working with what I see now as legacy technologies to working at one of the largest software companies in the World. And an innovative cloud company at that. I'm really enjoying the change of perspective and change of technologies and I can feel that I'm making a difference with what I do and what I bring to the customer I'm at. Great.

On the "normal job front" the week was busy as most weeks are. Two consecutive days in Stockholm where I flew there and back both days to get enough points to make SAS Gold again. It seemed really stupid at the time and the Wednesday 6.15am flight was really stupid but it will all be worth it in the end March when I make Gold again. The FastTrack and the Lounge access is really nice and especially when it looks like the project will be on until the end of the year.

I almost finished the Lighting Components I've been developing for the customer we are totally changing the look and feel of Salesforce. I cannot wait to show it off on this blog when it's all done and I've anonymised it :) Project wise we are also getting ready to launch the next sprint on April 3rd where we are bringing an entire new business line onto Salesforce. That launch will contain 3 major components that I either developed or played I major part in which is pretty neat!

What did I learn

  • It takes time to settle in
  • Although it's spring in Copenhagen doesn't mean that's the case in Stockholm
  • Tons and tons about Lightning Components

Status after this week

Trailhead points: 80150
Trailhead badges: 82
Certifications: 5 (Salesforce Certified Administrator, Salesforce Certified Platform App Builder, Salesforce Certified Advanced Administrator, Salesforce Certified Sales Cloud Consultant, Salesforce Certified Service Cloud Consultant)

Tags :

Using preformatted HTML in a Salesforce Lightning Component

Had to output preformatted HTML richtext from a richtext field in a Lighting Component the other day. Looking through the documentation I found the ui:outputRichText component but it didn't really work the way it's mentioned in the documentation. Instead of the body of the tag containing the HTML the HTML had to be in the value-attribute as shown below.

<ui:outputRichText value="{!v.data.Contact.Bio}" class="bio" />
The "bio" CSS class I added is to actually apply the formatting I need. Although the HTML contains the HTML tags the CSS on the Lighting Pages stripped the UL and LI formatting I needed so I had to manually add that back. The CSS I applied is below.
.THIS .bio {
    margin-left: 15px;
}
.THIS .bio ul ol {
    margin-top: 10px;
    margin-bottom: 10px;
}
.THIS .bio p {
    margin-top: 10px;
    margin-bottom: 5px;
}
.THIS .bio li {
    display: list-item;
    list-style-type: disc;
}