The Lightning Email Grid Component

Challenge

A colleague put out a challenge to me and another colleague asking us to create a Lightning component that allows someone to select one or more records and then click a button to email an internal Salesforce user one email for each selected record.

The colleague was saying this for fun and was not meant to be taken seriously but this sounded like a fun learning opportunity so here’s my rough cut.

Email Grid Overview

Lightning_EmailGrid

This Lightning component is a generic component that lets one define the records to be retrieved and the Salesforce email template used to email a specified user one email per selected record. The component’s configuration is specified at design time when it’s added to a page via attributes.

Benefits

  • Highly configurable to allow someone to specify which fields to display from any queryable object that’s user accessible.
  • Easily reused in different places by using different parameters.

Considerations

  • This is a proof-of-concept component and is bare bones. It doesn’t have the bells and whistles of a production grade component like paging, searching, filtering, sorting, or better styling.
  • It uses standard Salesforce emailing capabilities to email a specific Salesforce user using email templates.
  • Use only for a reasonable number of records say 100 or less.
  • Success and Error Messaging needs to be added.

Component Markup

The component uses the “EmailGridController” apex class for retrieving its records and emailing the specified individual using the selected records. It invokes the component controller’s init method to query the desired records. The records are then rendered dynamically using the table markup given. The table styling came from the Lightning Design System Data Table Styling Guide.

Attributes

  • objectName – The API name of the standard or custom object to query records from. This is bound to from the design attribute.
  • fieldSet – The API name of the fieldset on the specified object that’s used to allow one to specify which fields to show in the table.  This is bound to from the design attribute.
  • whereClause – The where clause to use in the SOQL query so one can easily show the desired records.  This is bound to from the design attribute.
  • emailButtonLabel – The button text to show on the “Email” button.  This is bound to from the design attribute.
  • emailTemplate – The name of the email template to use to email the specified Salesforce user. This allows an admin to use different email templates that they configure.  This is bound to from the design attribute.
  • recipientUserId – The Salesforce record id of the Salesforce user to email.  This is bound to from the design attribute.
  • records – These are the typeless wrapper objects that represent the records queried and each record’s fields. This is used internally by the component.
  • columnNames – The list of column names to show as specified from the fieldset. This is used internally by the component.
  • columnAPINames – Unused at this time. May be useful for future enhancements. This would be used internally by the component.

Design Attributes

The design attributes bind to the component’s attributes with the same name. See the attributes above for more information about usage.

Component Controller

Init Method

The Init method takes the objectName, fieldSet, and whereClause, builds the request parameter object from it, and then invokes the getRecords apex method asynchronously. On success, the records aand column names are bound to the component’s records, columnNames, and columnAPINames attributes for rendering the records in the component.

doEmailRecords Method

The doEmailRecords method identifies the selected records, if any, and builds an email request to invoke the emailRecords function on the apex controller to email the specified user one email for each selected record using the email template specified.

Note the use of JSON.stringify to build a JSON string for the request parameter object. The framework isn’t smart enough to deserialize the request object into its corresponding Apex Request object so it has to be passed in its JSON string representation and then manually deserialized server side.

Apex EmailGridController Class

getRecords Function

The getRecords function takes in a RecordsRequest parameter that is used to dynamically query Salesforce records and return them using a list of typeless records using a record wrapper.

Debug statements were intentionally left in to make troubleshooting easier.

emailRecords Function

The emailRecords function emails the specified Salesforce user one email for each Salesforce record selected using the email template chosen. The records, emailtemplate and id of the user to email are located in the EmailRecordsRequest.

There’s pending work to pass the email results back in the response.

Record Subclass

This class is a wrapper class that represents a row in the table in the component. The Record property isn’t actually used at this time because the Lightning component framework doesn’t allow subscripting into it dynamically like you could with Visualforce. To get around that, a simple list<String> contains the values for each field on the record. Since the order of them corresponds to the order of the column names, they’re easily traversed using the Aura:Iterator to show the record’s values.

Other Thoughts

  • The component can be genericized further to allow one to specify any desired action to be done with a set of selected records after clicking the button.
  • The formatting of dates and datetimes may look undesirable in the table since String.valueOf is being used to convert the value to an SObject field value to a string.
  • It took about 5 hours to get this basic sample working. The two main challenges were 1) trying to figure out why my object requests weren’t invoking the server side functions and that’s because the Lightning component framework doesn’t support automatically serializing and deserializing complex parameter types. 2) Figuring out how to dynamically show the columns and their values since the Lightning component framework doesn’t support direct SObject field access like Visualforce does at this time.

What did you think of this solution? What other features would you implement? How did you implement generating a dynamic list of records and columns to be shown in a component?