One of the things that I have found makes development with Visualforce a lot easier (and in truth makes developing pages on Salesforce easier than other technology stacks) is their standard controller. Without writing a single line of code I can have support for retrieving a saving record(s) straight out of the box.
Currently within the Lightning Component Framework there is no similar structure - and I include the <force:recordView> and <force:recordEdit> components, both of which provide a nice way of displaying data but require you to write the code for saving and if you don’t have the record Id or want a list of records, retrieving. This adds an extra burden to developing Lightning Components which would be a limitation were you trying to learn how to build them coming from another language, platform or just trying to learn from the ground up without an intricate knowledge of Apex.
This is the situation I came across when I was talking to Kerry Townsend (@kerrytownsend) and offered to help her learn how to build Lightning Components for her Dreamforce presentation on the subject (watch this space for some more material to hopefully help others!) Kerry is a fantastic functional consultant who has a great understanding of the declarative side of the platform and has done some programming at university. She is not however a developer and has no deep knowledge of Apex meaning that to learn how to build Lightning Components she would also need to learn how to develop in Apex.
What is it?
The “library” is 3 classes in 2 class files and a couple of custom labels for error handling. Our classes are:
- LightningStandardController - the main class we will be using as our Apex controller.
- LightningStandardControllerException - a custom exception class for us to use.
- LightningStandardControllerTest - test class at 100% coverage for the entire codebase.
The LightningStandardController offers a set of utility methods for you to call from your Lightning component to aid in the saving and retrieval of records from Salesforce:
- Save (both a single record or a list of records)
- Query (with a query string, an object name and some fields or an object name, fields and parameters)
Just Show Me Some Code!
Firstly, we are going to create a very a simple component that displays the name and site of an account (in the case of retrieving many we simply display the first):
Firstly we have set the controller attribute of the component to be our LightningStandardController. That is all we need to do to get it connected. The <aura:attribute> we define is for the account we are going to display and two <force:outputField> components we bind to the Name and Site fields on the Account object. For our demo here we add a <ui:inputText> field which is going to be for searching by Account Name. Finally there is a button which is going to call the search method on our component controller, speaking of which:
That’s it really. Save, saveMany and runQuery are all called in a similar manner.
Firstly, as I was experimenting with I originally intended to use a custom Apex class for passing in the filter parameters (you can see this in an earlier commit on Github). However, there is a current issue with the Lightning framework whereby passing in a parameter of a custom Apex type throws an internal server error (See here) so this original plan had to be skipped.
Another update that was made was to remove the use of overloaded AuraEnabled methods, as it seems that the method with the largest number of parameters is selected and null values are passed in for missing parameters. As such, tweaks were made to ensure that we had a single query method to use for all queries where we are not passing in a pre-defined query string.
Hopefully Salesforce will fix the issue I highlighted in the asides and more importantly will provide standard controller functionality natively that makes this unrequired.