New Lightning Component for Maps

New Lightning Component for Maps

20180126 UPDATE!! I got some new and very useful information about maps. Please, go to Latest Update section if you have already read this entry

A couple of years ago, I wrote a post about how to visualise maps and locations on Visualforce pages, and without having that in mind, Winter ’19 helped me to deliver a second part of that one. Now, Salesforce has released a new Map Lightning Component, so I will give it a try before moving to Spring ’19 version.

You will also find a similar example on Winter ’19 maintenance exam challenge. My code is much simpler than the maintenance one, so maybe it is a good start point before making it more complex.

In a similar way as the old post, I need an object with the information to show. In my case, Doctor object with a record about my Dentist, including a Geolocation field, the Location__c one.

Having that, I need to write some code in order to deliver a Lightning Component that call the standard Map component.

I will start with the Controller in Apex in order to retrieve the information from the database. Remember that Geolocation fields is a compound field with 2 pieces, Latitude__s and Longitude__s.

public with sharing class DoctorMapController
   public static List<Doctor__c> getDoctors()
      List<Doctor__c> doctors = [Select Id,
                                 FROM Doctor__c];
      return doctors;

We will continue with the component.

First of all, we implement usual interfaces in order to be able to visualise the component on different areas/views of our environment.

Secondly, I will add the tag <lightning:map> and its properties in order to show map information. The most important is mapMarkers. It is an array of markers that will help us to set the usual “pointer globe” icon that google maps provides. After that, we can add others like markerTitle or zoomLevel but they are not required, they just add more value to the component and the visualisation itself.

So having to provide information to mapMarkers and others, we need attributes in order to retrieve the data from our component Controller. That’s why we have 2 <aura:attribute> They are like variables on an apex class. Define the type and name of the variables that you will use among the component to get and set the data you need.

Finally <aura:handler> that will execute the action that will initialise the component via the javascript Controller. It is like the start point.

<aura:component implements="force:appHostable,
                access="global" >
   <aura:attribute name="mapMarkers" type="Object" access="PRIVATE" />
   <aura:attribute name="markersTitle" type="String" access="PRIVATE" />
   <aura:handler name="init" value="{!this}" action="{!c.init}"/>
   <aura:if isTrue="{!!empty(v.mapMarkers)}" >

And the init, points to here, the javascript Controller. It depends on the way you develop. Actually you can add all method logics to here, but it is a good practice to have it on the Helper, and on the Controller, just a call to there.

   init : function(component, event, helper) {
	helper.initHelper(component, event, helper);

Finally a Helper where we will find main methods. If you are familizarize with Javascript, it will not be very difficult to understand.

Basically the variable action, access our Apex Controller getDoctors method in order to retrieve all Doctor__c records.

With this information, we can iterate over there and show all doctors on our map. But my case is much simpler, I get the first one, and populate another variable with its information. Finally I will set the values to the component attributes, markTitle and mapMarkers.

But let me focus for a second on the variable that is assigned to mapMarkers attribute. The variable markers is an array because, as I mentioned at the beginning, mapMarkers parameter is an array with locations. But what do I need to specify there? The main one is Location that could be populated with the Geolocation field data or with a direction itself. After that we only have some more descriptive data like the title or the description. They add value to the map but the required one is Location.

   initHelper : function(component, event, helper) {
        helper.defineMarkers(component, event, helper);
   defineMarkers : function(component, event, helper) {
	let action = component.get("c.getDoctors");
	action.setCallback(this, function(response) {
	   const data = response.getReturnValue();
	   const dataSize = data.length;
	   let markers = [];
           //I will only show my single record
	   const dentist = data[0]; 
                'location': {
                'title' : dentist.SurgeryName__c,
                'description' : 
                      dentist.SurgeryName__c + 
                      ' dentist Location at ' + 
                         'Out and About Communications Dentist 
	   component.set('v.mapMarkers', markers);

And here you can find the result, a map with the “Moyua Square” with a pointer to my dentist place.

Reading this entry you can realise that using <lightning:map> is very simple and that actually, I focused on explain how to build the component itself, but if you would like to know more or create more complex pieces of code, take a look at the documentation and do some searches on internet. I’m sure people share their experiences with the new <lightning:map>.

Latest Update:

After reading this entry, my friend Alba Rivas told me she was doing some researches on maps too, and found out some useful information that shared with me:

If an address is specified for a marker, instead of its latitude and longitude, the component makes API requests to the google geolocation, and per Google documentation, it seems it has a cost. Also I would like to know if there is an event that I can listen when a marker is selected.

The API key is from Salesforce, and there are no current limitations on its use. We are going to add a click handler for selecting a marker in an upcoming release

Alba Rivas question and Salesforce response

Visual Flow & Lightning Components (I)

Visual Flow & Lightning Components (I)

It’s a fact that Visual Flow needed something that could make it more attractive to developers, and Salesforce did it.

Now we are able to integrate a Lightning Component as part of the Flow with just drag and drop and this blog will explain how easy it is.

Please, take into account that if your org is on Spring ’19, the look and feel of the Cloud Flow designer would be different because Salesforce is going to deliver Flow Builder

Using Standard Lightning Component

When we add a new screen to the flow, the first action is to add some new fields to show them. If we click on “Add a Field” tab, we  can scroll down and under Extensions section, we can find Lightning Components label.

Captura de pantalla 2018-11-30 a las 20.30.40

After adding it to the screen, you need to highlight it, so that you would be able to see all Standard Lightning Components that Salesforce already provides and we can use.

My example already have 2 radio buttons in order to decide if I would like to go ahead with the booking process or I prefer to stop it.

Captura de pantalla 2018-11-30 a las 20.34.09.png

And I would like to show something nicer like a toggle, the one that I already selected.

Winter ’19 provides new Lightning Components we can add to flows. Toggle is one of them.

So the result would be like below image.

Using Custom Lightning Component

But what about if you don’t find the Lightning Component you really need on Flow? That is not a problem, because you can also create your custom Lightning Component and add it to the Flow.

Let’s talk about another example. We will create a simple Flow with 2 DatePickers. The first one is provided by Flow, however the second is a custom Lighting Component. How does it look like?

Captura de pantalla 2018-12-20 a las 9.46.35.png

Their look and feel are similar and both work like tweens. The only difference with the Lightning component is that we can customize it. For instance, you can see that the size is larger than the flow one. Or you can change background color for instance.

How can we visualize in the Flow? First of all, remember that the DatePicker is a custom Lighting Component, so yes, you need to be sure that you implement a new interface in order to make it visible: lightning:availableForFlowScreens

Captura de pantalla 2018-12-20 a las 13.07.27

So doing that, it will appear on flow with all standard lightning components that Salesforce already provide, so it is just a matter of drag and drop.

Captura de pantalla 2018-12-20 a las 13.17.47

And that’s all, you have integrate your custom Lightning Component into your Flow.

Now Flow is beautiful as well as useful

API to Create a Sandbox Org

Some weeks ago I published my first try  with Tooling API where I could explain how to create a Custom field with this API, but when I worked on that, what I really needed was to create a Sandbox programatically. OMG!! A Sandbox!! And how can I do it?

At the end, a Sandbox is metadata, and as we learnt on my previous blog, Tooling API will help you to create metadata records. SandboxInfo is the object that represents a Sandbox, and we will use it to create our new environment.

SandboxInfo supports Get, Post, Patch and Delete REST API calls, that means, that with Post we will create a new Sandbox, with Patch we will do an update, a refresh at the end, and the Delete would remove the organization.

As you can see in the link there are lot of options when you create a Sandbox, like create the copy Chatter from production to Sandbox, or event it gives you the option to use Template to create the org. But if you need a simple environment, with below JSON body is more than enough:

   "Description": "New Test Sandbox",
   "HistoryDays": 0,
   "LicenseType": "DEVELOPER",
   "SandboxName": "SandboxTest"

And in order to execute it you can make a Post REST call with this url:


This call will return an Id that you can use in order to check the creation progress via another object, SandboxProcess. You can perform a query against this object filtering by SandboxInfoId field, and get useful information such us CopyProgress that represents how much of the copy has been already performed.

Finally I would like to remind you that you could only make this call against a Production org, and if your user has the rights to create Sandboxes. Otherwise, it will fail.


From Attachment to File via Flow?

Some days ago I got a message asking me if it was possible to move from Attachments to Files in Salesforce using the #clicksnotcode tool VisualFlow and after some researches I would say no, this is not possible without code. But if you find the way, please, please, please, leave me a message so that I can update this post.

So, what is this post about? My researches and how I got that the answer is no.

First of all, the use case. As you know we cannot create Attachments in Lightning Experience, only Files are available in LEX, so anything that we want to keep should be also migrated.

But how?

  • Manually? That could be a really expensive option, and tired, to be honest.
  • Via code? Yes!! I like this option. At the end, a File is a Salesforce Object, ContentVersion , and as you can find on this blog, with a really simple piece of code you can create a new File record. Below piece adds the query to an attachment. After that, find the image with the new file and also the result of a query done in  Workbench.
List<Attachment> attList = [SELECT 
                            FROM Attachment limit 1];
Attachment att = attList.get(0);

String fileContent = att.body.toString();
ContentVersion conVer = new ContentVersion();
conVer.PathOnClient = 'MigratedFile.txt';
conVer.Title = 'MigratedFile.txt';
conVer.Description = att.Name + ' migrated';
conVer.VersionData = EncodingUtil.base64Decode(fileContent);
conVer.FirstPublishLocationId = '001B000000hYespIAC'; 
insert conVer;

Captura de pantalla 2018-06-28 a las 17.15.33

Captura de pantalla 2018-06-28 a las 17.20.22

And what about VisualFlow?

I created something really simple, 4 steps flow. But it has a welcome and a thanks screen, so actually the job is done in 2 steps.

Captura de pantalla 2018-06-28 a las 17.30.46

First one is Record Lookup where I retrieve the single attachment that I have in my organization. Please, keep in mind that if you have a list of Attachments, and use a Record Lookup, it will return a single record, but if your idea is to retrieve all attachments, you need to use a Fast Record Lookup step.

Captura de pantalla 2018-06-28 a las 17.31.10

This step is going to store data into the variable that I created, and all of them are similar, Text variables.

Captura de pantalla 2018-06-28 a las 17.31.48

The second step is to create the ContentVersion record, assigning the variable data that I got on the previous step.

Captura de pantalla 2018-06-28 a las 17.32.00

And that is all. Yes, so simple.

However, when I run it I got an error and this email where I can see that there is an issue on VersionData field.

Captura de pantalla 2018-06-28 a las 17.42.18

The reason is simple. Attachment Body returns a Blob that I need to convert into String in order to be able to encode and pass to the Content file.

String fileContent = att.body.toString();
conVer.VersionData = EncodingUtil.base64Decode(fileContent);

Is there a way to fix it? No as far as I could find. My first idea was to check what the variable was returning, adding a middle step to show the body value

Captura de pantalla 2018-06-28 a las 17.55.06

And as I expected that is not my body text

Captura de pantalla 2018-06-28 a las 17.54.46

So the next thought was to try to create a formula in flow or make any transform, something that could help me, but I couldn’t find any.

Captura de pantalla 2018-06-28 a las 17.51.16

So I think that the only way to do it is via some Apex code. We can create a class that has InvocableMethod annotation and do the transform there and call the class as it was an step, but, to be honest, why do I want to do it when I can run the whole transform from an apex class as I explained before?

At the end, I would advice to create your own ApexClass that execute the process to do the migration if you do not want to use the tool that Salesforce provides.

Good luck!!

API to Create CustomField

In the last few weeks, and for my first time, I started working with the Salesforce Tooling API. This scared me a bit because new beginnings are hard for me, but at the same time I liked the challenge.

In a similar way other Salesforce APIs help you to get records data, Tooling API is used in order to access / create metadata. But Tooling could sound weird, how can I run this one? Not difficult at all as this is also accesible via SOAP and REST API. What does it mean? You can make Tooling API calls via REST calls as long as the Object says that. For instance, ApexCodeCoverage supports Query and Get REST API calls, while with CustomField you can also do Post and Patch calls.

Let’s dig a bi. If you open Workbench and execute


you get information about this Salesforce object, so the Get REST API call works.

Captura de pantalla 2018-06-03 a las 14.22.08

But what about if I need to retrieve information about a certain CustomField? Same as you were trying to get information about a certain Account record.

Having the custom field Field1__c, I only need to look for its Id

Captura de pantalla 2018-06-03 a las 14.26.42Captura de pantalla 2018-06-03 a las 14.26.52

and use it in the get call


Getting this result

Captura de pantalla 2018-06-03 a las 14.29.51Captura de pantalla 2018-06-03 a las 14.30.08Captura de pantalla 2018-06-03 a las 14.30.18

That is really cool, but what I really need is to create a new custom field related to CO1__c custom object, and maybe I didn’t write the right words in google, but I didn’t find it anywhere so I took me few rounds till I get it.

My first try was to create a JSON body following Salesforce help:

   "DeveloperName": "CO1__c.test__c", 
   "ManageableState": "unmanaged", 
   "Metadata": { 
      "label": "test", 
      "description": "my new test field", 
      "length": "32", 
      "type": "string" 

And after running a POST call with the url:


I got this error:

Captura de pantalla 2018-06-03 a las 14.40.51.png

So I continued testing things. Removing fields, changing values etc, till I got it with the following JSON body

   "FullName": "CO1__c.test__c", 
   "Metadata": { 
      "label": "test", 
      "description": "my new test field", 
      "required": false, 
      "externalId": false, 
      "type": "Text", 
      "length": 32 

Getting the result:

Captura de pantalla 2018-06-03 a las 14.45.05

And in the org the new field created

Captura de pantalla 2018-06-03 a las 14.45.22

What about if I need to do it in Apex? With a simple HTTPRequest call you can run same code I executed in workbench.

Another alternative is create your own ToolingAPI wrapper class as Andy Fawcett explains on this old entry.

And that is all for this entry, but don’t think this was my original challenge. What I was asked to do was to check if I could create a Sandbox environment via the Tooling API … keep an eye on future blogs because I will publish it if I get it 😉

Visualforce y Lightning Experience

Después de un gran parón en mi blog debido a dreamOlé y otros eventos, hoy me gustaría publicar un post muy pero que muy pequeñín sobre una funcionalidad que nos trae la Summer ’18: visualizar una página Visualforce con estilo Lightning Experience.

Lo primero de todo, comencemos con la pregunta:

¿Trabajas en Lightning Experience?

Si, tu respuesta es NO … no eres el único, ya que una servidora sigue abriendo Classic UI casi siempre, pero chicos, hay que ser valientes y movernos a LEX !!!

Una de las razones por las que sigo en Classic es porque soy de la vieja escuela, y cuando tengo que montar una nueva UI me voy a Visualforce en vez de Lightning Components. Segundo error …. es hora de perder el miedo a Lightning Components y empezar a desarrollar UI de la forma que Salesforce nos aconseja.

¿Qué pasa si mi producto tiene ya cientos de páginas Visualforce? ¿Debo migrar todo a Lightning Components?

Teniendo en cuenta que el tiempo que puedes necesitar para ello puede ser elevado, y que desgraciadamente Lightning Components no ofrece toda la funcionalidad de Visualforce, yo migraría aquello que fuera sencillo. Por otro lado, si hay que hacer una nueva UI, revisad primero si Lightning Components os sirve.

¿Qué hacemos con el resto?

Salesforce responde a nuestras súplicas, y en mi caso, casi me echo a llorar cuando vi lo sencillo que era aplicar el estilo Lightning Experience a una página existente, de forma que pasamos de esto:

Captura de pantalla 2018-05-25 a las 11.44.33

A esto:

Captura de pantalla 2018-05-25 a las 11.45.42

¿Cómo lo hemos conseguido? Fácil.

Para ello necesitamos una Visualforce, que hemos rescatado de esta entrada, donde creábamos una vista alternativa a una cuenta, junto con su listado de oportunidades.

Una vez que tenemos nuestra página Visualforce, tenemos que asegurarnos que será visible en Lightning Experience, para lo que tenemos que marcar el checkbox “Available for Lightning Experience, Lightning Communities and the mobile app”

Captura de pantalla 2018-05-25 a las 11.43.51

Con esto conseguimos visualizar la página en Lightning Experience. Es decir, sin este checkbox, aunque usemos esta página para sobre-escribir la vista de un registro de Account, y la visualicemos en Classic UI, si nos movemos a LEX, visualizaremos la página Standard de Salesforce en LEX en vez de la nuestra.

Y por último (si un último paso!!) sólo tenemos que añadir lightningStyleSheets="true" al tag <apex:page> de forma que nuestra página quedaría así:

<apex:page standardController="Account" lightningStyleSheets="true">
 <apex:form >
  <apex:pageBlock title="Vista Cuenta">
   <apex:pageBlockButtons >
    <apex:commandButton value="Edit" action="{!edit}"/>

   <apex:pageBlockSection title="Campos Cuenta" columns="2">
    <apex:outputField value="{!}"/>
    <apex:outputField value="{!}"/>
    <apex:outputField value="{!account.type}"/>
    <apex:outputField value="{!account.accountNumber}"/>
 <apex:relatedList list="Opportunities" />

Si quieres saber más, échale un ojo a este link.


BigObjects and Triggers

Some months ago I wrote an entry about BigObjects and since that moment I go lot of comments with questions and some useful information that I missed in my post and I would like to include here because sometimes, we do not read comments.

Not all SOQL statements are valid. For now, the !=, LIKE, NOT IN, EXCLUDES, and INCLUDES operators are not valid in any query.

There are already some Standard Big Objects like FieldHistoryArchive, so do not try to create one directly, and check before if it already exist.

Unfortunately SOSL is not supported by BigObjects.

But maybe the most important one was the fact that people was not able to create BigObject records from Triggers. It was a big surprise for me because documentation said that you could not create triggers related to a Big Object, but nothing about not be able to create Big Object records from triggers. So today I decided to give it a try.

If you have taken a look at my blog, the use case was to archive Code Review records so that we could end up with Code Review History records. Although it doesn’t make too much sense, create History records in a trigger, I decided to make it simple and continue with these objects.

So the first idea was to create a Trigger related to CodeReview__c:

trigger CodeReviewTrigger on CodeReview__c (after insert)
   List<CodeReviewHistoric__b> crhToInsert = new List<CodeReviewHistoric__b>(); 
   for (CodeReview__c cr:    
      CodeReviewHistoric__b crh = new CodeReviewHistoric__b();        
      crh.CanBeMerged__c = cr.CanBeMerged__c ? 'true' : 'false';        
      crh.CodeReviewDate__c = cr.CodeReviewDate__c;         
      crh.Comments__c = cr.Comments__c;        
      crh.Employee__c = cr.Employee__c;        
      crh.Score__c = cr.Score__c;        
      crh.Story__c = cr.Story__c;        

However, when I tried to create a Code Review record via the UI, I got below error

Captura de pantalla 2018-02-18 a las 15.16.26

and if I checked log, I also got this one.

Captura de pantalla 2018-02-18 a las 15.16.54

So came back to BigObjects product manager suggestion:

However a workaround could be to put the insertImmediate() call into a queueable method

But why queuable method? I think the key point is that we need a different context, a new transaction, so it doesn’t matter the way to get it, and I decided to keep things simple using a @future method in order to perform the Database.insertInmediate action. Then, this method will be called from the trigger.

But this annotation has several restrictions, like argument types. It doesn’t support a list of SObjects, but it allows a List of Ids.

So Trigger will look like this:

trigger CodeReviewTrigger on CodeReview__c (after insert)
   List<Id> codeReviewIds = new List<Id>(); 
   for (CodeReview__c cr:    

And @future one like this:

public with sharing class AsyncProcess
   public static void createBigObjectRecords(List<Id> crIds)
      List<CodeReviewHistory__b> crhToInsert = new List<CodeReviewHistory__b>();
      for (CodeReview__c cr: [Select Id, 
                               From CodeReview__c 
                               Where Id In :crIds])    
         CodeReviewHistory__b crh = new CodeReviewHistory__b();
         crh.CanBeMerged__c = cr.CanBeMerged__c ? 'true' : 'false';            
         crh.CodeReviewDate__c = cr.CodeReviewDate__c;             
         crh.Comments__c = cr.Comments__c;            
         crh.Employee__c = cr.Employee__c;            
         crh.Score__c = cr.Score__c;            
         crh.Story__c = cr.Story__c;            

And now it works sucessfuly

Captura de pantalla 2018-02-18 a las 16.37.46

Captura de pantalla 2018-02-18 a las 16.39.40.png

Any other options? Batch Apex, Queueable, even, you can use Async SOQL via a http call.

I’m sure that I still miss things about BigObjects but another amazing resource to check is the Salesforce MVP Alba A. Rivas blogs about this technology.