<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Aura Archives - Michael Soriano</title>
	<atom:link href="https://michaelsoriano.com/tag/aura/feed/" rel="self" type="application/rss+xml" />
	<link>https://michaelsoriano.com/tag/aura/</link>
	<description>I turn code into captivating user experiences for the web</description>
	<lastBuildDate>Sun, 10 Jul 2022 17:49:19 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.4</generator>
	<item>
		<title>How to create simple Pagination using Lightning components and Apex</title>
		<link>https://michaelsoriano.com/how-to-create-simple-pagination-using-lightning-components-and-apex/</link>
					<comments>https://michaelsoriano.com/how-to-create-simple-pagination-using-lightning-components-and-apex/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Wed, 17 Apr 2019 21:37:17 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Salesforce]]></category>
		<category><![CDATA[Aura]]></category>
		<guid isPermaLink="false">http://michaelsoriano.com/?p=6850</guid>

					<description><![CDATA[<p>Let&#8217;s build something every web application needs in their results page: Pagination (aka Paging). This technique is necessary so we don&#8217;t bombard our users with all the items in our result page. Instead, we show them in &#8220;chunks&#8221; or &#8220;sets&#8221; of results. This is a very simplistic example &#8211; all we&#8217;re doing is a set [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/how-to-create-simple-pagination-using-lightning-components-and-apex/">How to create simple Pagination using Lightning components and Apex</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Let&#8217;s build something every web application needs in their results page: <strong>Pagination</strong> (aka Paging). This technique is necessary so we don&#8217;t bombard our users with all the items in our result page. Instead, we show them in &#8220;chunks&#8221; or &#8220;sets&#8221; of results. This is a very simplistic example &#8211; all we&#8217;re doing is a set of buttons that have page numbers on them. Once clicked, it will go ahead and fetch the results in that page. </p>



<p>A peak at what we&#8217;re building is shown below:</p>



<p>Disclaimer: I&#8217;m assuming you know how to work with Lightning components. I also hope you know JavaScript and HTML. There&#8217;s no downloadable code &#8211; you just simply have to follow along.</p>



<figure class="wp-block-image border"><img fetchpriority="high" decoding="async" width="644" height="363" src="https://michaelsoriano.com/wp-content/uploads/2019/03/paging-lightning.gif" alt="Lightning Pagination" class="wp-image-6852"/></figure>



<p>Currently, there are no built in lightning component for this type of functionality. Instead, we&#8217;re using  <strong>lightning:radioGroup</strong> with type &#8220;button&#8221;. This will setup our page links nicely in a row, with clickable links and active/inactive states already added. </p>



<p>Ready to get started? Let&#8217;s begin. </p>



<h3 class="wp-block-heading">Our Apex methods</h3>



<p>First and foremost, let&#8217;s start with the backend. If you guys are familiar with SOQL &#8211; which is Salesforce&#8217;s version of SQL, you know that we have the 3 necessary keywords for our paging to become possible: ORDER BY, LIMIT and OFFSET. </p>



<p><strong>ORDER BY</strong> &#8211; allows us to determine the order of our results. This makes it so that our result set will always follow a standard sort. This will make our paging deterministic and predictable.</p>



<p><strong>LIMIT</strong> &#8211; allows us to limit the results in the page. So when we click a page &#8211; we will only show these number of records.</p>



<p><strong>OFFSET</strong> &#8211; allows us to &#8220;skip&#8221; the records that we will not show. We&#8217;re &#8220;skipping&#8221; these records and start from the first record after our offset.  </p>



<p>I&#8217;m building a method that I can call from my lightning component. Note the &#8220;@auraEnabled&#8221; keyword. The function then takes 2 arguments: ofst and lmt. What it returns is simply our queried object, with the results using SOQL. </p>



<pre class="wp-block-code"><code lang="java" class="language-java line-numbers">@auraEnabled
public static List&lt;sObject&gt; getNewHires(Integer ofst, Integer lmt){
	List&lt;sObject&gt; onBoardingList = [SELECT
						Id,
						Name,
						FROM
						OnBoarding_Data__c
						ORDER BY Name DESC
						LIMIT :lmt
						OFFSET :ofst
						];
			return onBoardingList;
		}</code></pre>



<p>Now we need another method to find out the total number of records there are in the database. </p>



<pre class="wp-block-code"><code lang="java" class="language-java line-numbers">@auraEnabled
public static Integer getTotalItems(){
	Integer total = 0;
	String query = 'SELECT Id ';
	query += 'FROM OnBoarding_Data__c';
	List&lt;sObject&gt; onBoardingList = Database.query(query);
	total = onBoardingList.size();
return total;
}</code></pre>



<p>The above simply queries our same custom object, returning the total number of records.</p>



<p>My application uses a custom object for &#8220;on boarding&#8221; employees &#8211; so you will see OnBoarding references all through my sample code.  </p>



<p>Our simplified Apex is ready. Let&#8217;s move to the front end.  </p>



<h3 class="wp-block-heading">The HTML</h3>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx line-numbers"> &lt;aura:attribute name="limitPerPage" type="Integer" default="16"/&gt;
 &lt;aura:attribute name="offset" type="Integer" default="0"/&gt;
 &lt;aura:attribute name="pagesArray" type="List" default="[]"/&gt;
 &lt;aura:attribute name="curpage" type="String" default="1"/&gt;</code></pre>



<p>In our HTML, we&#8217;re setting up 4 attributes that we need for our pagination. You should be able to tell from their names what they&#8217;re for. We&#8217;re also setting the default values in them. Note the &#8220;<strong>pagesArray</strong>&#8221; attribute &#8211; is an array that will house the page objects that we need for our paging system.</p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx line-numbers">&lt;aura:if isTrue="{! v.pagesArray.length &gt; 1 }"&gt;
      &lt;div class="pagingRow slds-grid slds-wrap slds-gutters"&gt;
      &lt;div aura:id="pagingWrap"
        class="slds-col slds-size_1-of-1 slds-large-size_12-of-12 pagingWrap"&gt;
        &lt;lightning:radioGroup
            type="button"
            aura:id="pager"
            name="pager"
            label=""
            options="{! v.pagesArray }"
            onchange="{!c.doPaging}"
            value="{!v.curpage}"
            /&gt;
      &lt;/div&gt;
      &lt;/div&gt;
    &lt;/aura:if&gt;</code></pre>



<p>The above is the output of our code. You see div wrappers that have Lighting Design System classes, along with aura directives to process our code. Such as our use of the <strong>aura:if</strong> &#8211; which checks the length of our pagesArray. Meaning &#8211; we&#8217;re only showing paging if there are pages to show.</p>



<p>You see our use of <strong>lightning:radioGroup</strong>. We also pass in &#8220;value&#8221; and &#8220;options&#8221; &#8211; which corresponds to our attributes we defined above.</p>



<p>We also have an onchange attribute calling our &#8220;<strong>doPaging</strong>&#8221; handler. We haven&#8217;t built this yet, but is coming up.</p>



<p>Let&#8217;s move on to our JavaScript.</p>



<h3 class="wp-block-heading">The JavaScript</h3>



<p>Let&#8217;s get down to business. We have our markup, we have our Apex waiting in the back end. All we need to do is tie them all up together. We do this with JavaScript &#8211; ideally in our helper file.</p>



<p>First, we create a &#8220;<strong>buildPaging</strong>&#8221; method. This method ideally fires on page load. But you can also call this method if you have some kind of filter mechanism. </p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript line-numbers">buildPaging : function(component,event, helper){
		helper.callServer(component,'c.getTotalItems', function(response){
			var ttl = response;
			var lmt = component.get('v.limitPerPage');
			var pages = Math.ceil(parseInt(ttl) / parseInt(lmt));
			var pagesArray = [];
			for(var i=1; i&lt;=pages; i++){
				var obj = {};
				obj['label'] = i.toString();
				obj['value'] = i.toString();
				pagesArray.push(obj);
			}
			component.set('v.pagesArray',pagesArray);
		},{});
	},</code></pre>



<p>First thing you&#8217;ll see is our helper.callServer() method. This is basically our means of calling our Apex code above. To find out more about callServer() &#8211; see the post &#8220;<a href="https://michaelsoriano.com/call-apex-from-lightning-components/">Call Apex from Lightning</a>&#8220;.</p>



<p>So from our total records, we can build our pagesArray. We call our <strong>getTotalItems</strong> from the backend, then we grab our &#8220;<strong>limitPerPage</strong>&#8221; attribute. We divide the total by the limit, and we&#8217;re doing a &#8220;<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil">ceil()</a>&#8221; on it. This is so that we get a whole new page, even though there&#8217;s only 1 item in it.</p>



<p>Lastly, we&#8217;re building our pagesArray &#8211; but passing in the label and the value as an object. </p>



<p>Note the &#8220;<strong>toString()</strong>&#8221; method it. This is due to a bug with  <br><strong>lightning:radioGroup</strong>. It can only process strings. If you pass an integer &#8211; you would have to click it 2x to take effect! <em>Whatever</em>. </p>



<p>Let&#8217;s move on to our handler.  </p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript line-numbers">doPaging : function(component, event, helper){
		var lmt = component.get('v.limitPerPage');
		var val = event.getSource().get("v.value");
		var offset = parseInt((val-1) * lmt);
		component.set('v.curpage',val);
		component.set('v.offset',offset);
		helper.callServer(component,'c.getNewHires', function(response){
			if(response.length &gt; 0){
			component.set("v.newhires", response);
				}else{
					console.log('no records');
				}
		},{'ofst' : ofst, 'lmt' : lmt});
	},</code></pre>



<p> So first you see, lmt &#8211; which is static (set in our attribute). Then you see &#8220;val&#8221; &#8211; which is what was clicked. We get that number and multiply by the limit &#8211; so we get our <strong>offset</strong>. </p>



<p>We then call our Apex method with those parameters:</p>



<pre class="wp-block-code"><code lang="json" class="language-json line-numbers">{'ofst' : ofst, 'lmt' : lmt}</code></pre>



<p>Inside our callback, we simply set our response to the newly fetched data from our server. </p>



<h3 class="wp-block-heading">Conclusion</h3>



<p>And that&#8217;s about it. We&#8217;ve just built ourselves a very simplistic pagination using Lightning and Apex. There are many things we can do to enhance our code &#8211; like having a &#8220;previous&#8221; and &#8220;next&#8221; buttons &#8211; but I&#8217;ll leave that up to you. </p>



<p>Feel free to comment below.</p>
<p>The post <a href="https://michaelsoriano.com/how-to-create-simple-pagination-using-lightning-components-and-apex/">How to create simple Pagination using Lightning components and Apex</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/how-to-create-simple-pagination-using-lightning-components-and-apex/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Repeating Inputs in Salesforce Lightning Components</title>
		<link>https://michaelsoriano.com/repeating-inputs-in-salesforce-lightning-components/</link>
					<comments>https://michaelsoriano.com/repeating-inputs-in-salesforce-lightning-components/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Fri, 23 Nov 2018 01:40:14 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Salesforce]]></category>
		<category><![CDATA[Aura]]></category>
		<guid isPermaLink="false">http://michaelsoriano.com/?p=6788</guid>

					<description><![CDATA[<p>What we&#8217;re building: An input field that can be duplicated (repeated) as part of a form. This is particularly useful when you want to capture information that you want to separate in different lines, and you don&#8217;t really want to use a textarea. This way, we&#8217;re forcing our user&#8217;s to enter a value per input.  [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/repeating-inputs-in-salesforce-lightning-components/">Repeating Inputs in Salesforce Lightning Components</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>What we&#8217;re building: An input field that can be duplicated (repeated) as part of a form. This is particularly useful when you want to capture information that you want to separate in different lines, and you don&#8217;t really want to use a textarea. </p>



<p>This way, we&#8217;re forcing our user&#8217;s to enter a value per input.  In this scenario, we&#8217;re trying to grab a list a set of File Paths.<br></p>



<p>We&#8217;re using Lightning components, which is the framework Salesforce is using for their UI. A screenshot showing the pieces of what we want to accomplish is shown below.<br></p>



<p><img decoding="async" width="600" height="319" class="alignnone size-full wp-image-6794" src="https://michaelsoriano.com/wp-content/uploads/2018/10/repeating-fields.png" alt="Salesforce - lightning repeat field" srcset="https://michaelsoriano.com/wp-content/uploads/2018/10/repeating-fields.png 600w, https://michaelsoriano.com/wp-content/uploads/2018/10/repeating-fields-300x160.png 300w" sizes="(max-width: 600px) 100vw, 600px" /><br></p>



<p>See that we have inputs, a &#8220;More&#8221; link, and a &#8220;minus&#8221; sign &#8211; so we can remove the input directly.<br></p>



<p>Ready to build? Let&#8217;s begin.<br></p>



<p>Let&#8217;s start by defining an attribute in our .cmp file. Let&#8217;s call it &#8220;fileShares&#8221;, and its a &#8220;List&#8221; type. In Salesforce &#8211; a &#8220;List&#8221; is a an array in JavaScript. Here is how it looks</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;aura:attribute name="fileShares" type="List" default="[]"/></code></pre>



<p>Our array will hold a set of Objects, which reflects each of the input that we&#8217;re building.</p>



<p>Now we&#8217;re ready to create our markup. We&#8217;re using <strong>lightning:input </strong>&#8211; which is nothing but an &#8220;input&#8221; in HTML. We give it several attributes, which is defined below:</p>



<ul class="wp-block-list"><li>aura:id with a value of fileShare.id</li><li>value &#8211; with a value of fileShare.value</li><li>label &#8211; with a value of fileShare.label</li><li>class &#8211; with a value of &#8220;fileShares&#8221; (nothing to do with our object, but simply for styling)</li></ul>



<p>We also want to wrap it inside a DIV with a class of &#8220;<strong>fileSharesItem</strong>&#8220;.</p>



<p>Now let&#8217;s wrap it inside a <strong>aura:iteration </strong>tag, which is how you loop through items in Lightning.</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;aura:iteration items="{!v.fileShares}" var="fileShare" indexVar="ivar">
       &lt;div class="fileSharesItem">
            &lt;lightning:input
             aura:id="{!fileShare.id}"
             value="{!fileShare.value}"
             label="{!fileShare.label}"
             class="fileShares"/>
       &lt;/div>
&lt;/aura:iteration></code></pre>



<p>Notice that we&#8217;re looping through <strong>v.fileShares </strong>&#8211; which is the aura:attibute we first defined. We prefixed it with a &#8220;v.&#8221;, because in Lightning &#8211; this means &#8220;value provider&#8221;. We also have two important attributes in our iterator: var and indexVar. Our variable &#8220;fileShare&#8221; declared in &#8220;var&#8221;, while &#8220;indexVar&#8221; holds the index &#8211; we&#8217;re calling &#8220;iVar&#8221; (the counter).<br></p>



<p>Let&#8217;s move on to our controller. This is the JavaScript file, that we first initialize the value of <strong>v.fileShares</strong>. Add the code below (ideally inside an initialize method during load).</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">component.set('v.fileShares', {'label': 'Enter Path', 'value': '','id': 'fileShare1'});</code></pre>



<p>See that we&#8217;re using <strong>component.set() </strong>&#8211; and passing two parameters. The first is the property to set, then the value. In the case above, we&#8217;re setting up the &#8216;v.fileShares&#8217; with an object. This means that we want just one field to show when the page loads.</p>



<h3 class="wp-block-heading" id="adding-an-input">Adding an Input</h3>



<p>Let&#8217;s add the button that when clicked, a new input will be added to our form. Lighting supports data binding. This means that since we&#8217;ve binded our loop, all we worry about is the data. Remember our aura:iteration tag?</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">addMoreShareHandler : function(component, event, helper){
	var inputs = component.get("v.fileShares");
	var id = inputs.length+1;
	var obj = {
		'label': '',
		'value': '',
		'id': 'fileShare'+id}
		inputs.push(obj);
		component.set("v.fileShares", inputs);
},</code></pre>



<p>Try it out and you should see our input repeated. Pretty neat right? How about removing the input? Let&#8217;s tackle that below.</p>



<h3 class="wp-block-heading" id="the-remove-button">The Remove Button</h3>



<p>Let&#8217;s create an anchor tag &#8211; with a custom click handler. Also, let&#8217;s add a couple of attributes &#8211; so we know which one to remove. These attributes have to start with <strong>data- </strong>which is also known as &#8220;<a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes">data-attributes</a>&#8220;. I&#8217;ll explain more in our handler.</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;a href="#" onclick="{!c.removeShareHandler}" data-idtoremove="{!fileShare.id}"
            data-index="{!ivar}" class=</code></pre>



<p>Now in our handler, we simply start with <strong>event.preventDefault()</strong> &#8211; which stops the link from behaving like a normal link. We don&#8217;t want the page to jump and refresh upon clicking.<br></p>



<p>Next, we grab the event, along with a property called <strong>currentTarget</strong>. What the currentTarget holds is information about what anchor tag was clicked.<br></p>



<p>So to access &#8220;<em>data-idtoremove</em>&#8220;, we do &#8220;<em>dataset.idtoremove</em>&#8220;</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">removeShareHandler : function(component, event, helper){
		event.preventDefault();
		var selectedItem = event.currentTarget;
                var idtoremove = selectedItem.dataset.idtoremove;
		var inputs = component.get("v.fileShares");
		for(var i=0;i&lt;inputs.length;i++){
			var obj = inputs[i];
			if(obj.id == idtoremove){
				inputs.splice(i,1)
			}
		}
		component.set("v.fileShares", inputs);
	}</code></pre>



<p>Then we loop through the inputs once again &#8211; by grabbing it from our component. We use .splice() to remove it from our array of objects.<br>Finally, let&#8217;s make the styles for our links.</p>



<h3 class="wp-block-heading" id="the-css">The CSS:</h3>



<p>For the remove link, we&#8217;re really trying to make it look like a &#8220;minus&#8221; button. We&#8217;re doing that with <strong>border-radius: 50%, </strong>along with a background color and a faint box-shadow. The rest of the CSS is mainly for positioning and sizing.</p>



<pre class="wp-block-code"><code lang="css" class="language-css">.THIS .slds-form-element.fileShares {
  margin-bottom:-5px;
}
.THIS .fileSharesItem {
  position:relative;
}
.THIS .removeShare {
  position: absolute;
  z-index: 999;
  right: -8px;
  top: 15px;
  border: 1px solid #ccc;
  width: 21px;
  line-height: 17px;
  padding: 0 0 2px 0;
  text-align: center;
  border-radius: 50%;
  font-size: 22px;
  background: #fff;
  box-shadow: 2px 2px 0 #e9e9e9;
}
.THIS .removeShare:hover,
.THIS .removeShare:active,
.THIS .removeShare:focus {
  text-decoration:none;
  background:#ebebeb;
}</code></pre>



<p>Finally, we&#8217;re setting some hover styles by using <strong>:hover</strong>, <strong>:active</strong> and <strong>:focus </strong>also known as &#8220;pseudo selectors&#8221;. We simply want the cursor to change into a pointer, along with a subtle background change.<br>The final output:</p>



<p><br><img decoding="async" width="410" height="257" class="alignnone size-full wp-image-6792" src="https://michaelsoriano.com/wp-content/uploads/2018/10/repeating-fields.gif" alt="Salesforce repeating fields"><br></p>



<p>So there it is. We just made a quick set of repeating inputs in Lightning. This also is a good crash course into Salesforce&#8217;s shiny new framework &#8211; which is gaining more popularity in the world of enterprise application development.<br></p>



<p>If you find this tutorial useful, or would like to see more &#8211; leave your comments below.</p>
<p>The post <a href="https://michaelsoriano.com/repeating-inputs-in-salesforce-lightning-components/">Repeating Inputs in Salesforce Lightning Components</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/repeating-inputs-in-salesforce-lightning-components/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Let&#8217;s build a Map Application using Leaflet and Lightning Components</title>
		<link>https://michaelsoriano.com/lets-build-map-application-using-leaflet-and-lightning-components/</link>
					<comments>https://michaelsoriano.com/lets-build-map-application-using-leaflet-and-lightning-components/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Sat, 15 Sep 2018 23:57:59 +0000</pubDate>
				<category><![CDATA[Salesforce]]></category>
		<category><![CDATA[Apex]]></category>
		<category><![CDATA[Aura]]></category>
		<category><![CDATA[lightning]]></category>
		<guid isPermaLink="false">http://michaelsoriano.com/?p=6575</guid>

					<description><![CDATA[<p>Salesforce&#8217;s Lightning component system is quite a robust framework where you can build full pledged single-page applications in a heartbeat. I especially like it&#8217;s built-in SLDS (styles), so all you have to really think about is the logic of your application. In this walk trough, we&#8217;re building a real life map application with Lightning. We&#8217;re [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/lets-build-map-application-using-leaflet-and-lightning-components/">Let&#8217;s build a Map Application using Leaflet and Lightning Components</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Salesforce&#8217;s Lightning component system is quite a robust framework where you can build full pledged single-page applications in a heartbeat. I especially like it&#8217;s built-in SLDS (styles), so all you have to really think about is the logic of your application. In this walk trough, we&#8217;re building a real life map application with Lightning. </p>



<p>We&#8217;re using Google Places for our city lookup, as well as Leaflet for our map and finally Chatter for our chat component.<br></p>



<p>The goal is to have pins on the map &#8211; which is on the right side of our page. These pins are also shown in a list format on the left hand side of the page. Once a pin is clicked, the list on the left hand side is replaced by the pin details, along with the ability to chat about that specific pin directly below. When the &#8220;Close&#8221; button is clicked, the list re-appears, as well as the map zooms to its original view.</p>



<p><br>The same behavior is achieved when the pin on the map is clicked.</p>



<p><br><img decoding="async" width="930" height="465" class="alignnone size-full wp-image-6663" style="border: 1px solid #ededed;" src="https://michaelsoriano.com/wp-content/uploads/2018/07/map-application3.gif" alt="Salesforce Map"><br></p>



<p>We also have a custom form, that allows us to add a pin right in the same page. The form has an auto suggest field for the cities.<br></p>



<p>Note that this is going to be a high level tutorial. You should be well versed in Lightning Components and JavaScript to follow along. A working knowledge of Salesforce is also needed.<br></p>



<p>Read to get started? Let&#8217;s begin.</p>



<h3 class="wp-block-heading" id="setting-things-up">Setting things Up</h3>



<p>Before we can actually start coding, let&#8217;s back up and think about what we need. We will need a map software.&nbsp; We need to store the locations in a custom object in Salesforce. And we need an Apex class to fetch these records for us. Seems simple enough? Let&#8217;s continue.</p>



<p><br><strong>Static Resources</strong><br></p>



<p>We&#8217;re using Leaflet &#8211; an open source map software which allows us to build a map on the page. All we need to do is pass it an array of locations (Longitude + Latitude) and Leaflet will populate magically. We also need LeafletMarkerCluster, an add-on to Leaflet, which allows us to bundle our pins together. This prevents the ugly grouping of many pins together.<br></p>



<p>So add these two zip files as static resources to Salesforce:</p>



<ul class="wp-block-list"><li><a href="https://michaelsoriano.com/wp-content/uploads/2019/05/leaflet.zip">Leaflet</a></li><li><a href="https://michaelsoriano.com/wp-content/uploads/2019/05/leafletMarkerCluster.zip">LeafletMarkerCluster</a></li></ul>



<p><img decoding="async" width="579" height="500" class="alignnone size-full wp-image-6655" src="https://michaelsoriano.com/wp-content/uploads/2018/07/static-resources.png" alt="Static Resources" srcset="https://michaelsoriano.com/wp-content/uploads/2018/07/static-resources.png 579w, https://michaelsoriano.com/wp-content/uploads/2018/07/static-resources-300x259.png 300w" sizes="(max-width: 579px) 100vw, 579px" /><br></p>



<p><strong>Custom Object</strong><br></p>



<p>Each pin on the map is a record from a Custom Object in Salesforce. Let&#8217;s call ours &#8220;Pin&#8221;. Go ahead and build that custom object with the fields shown below.</p>



<p><br><img decoding="async" width="803" height="644" class="alignnone size-full wp-image-6671" src="https://michaelsoriano.com/wp-content/uploads/2018/07/custom-obj-pin.png" alt="custom object" srcset="https://michaelsoriano.com/wp-content/uploads/2018/07/custom-obj-pin.png 803w, https://michaelsoriano.com/wp-content/uploads/2018/07/custom-obj-pin-300x241.png 300w, https://michaelsoriano.com/wp-content/uploads/2018/07/custom-obj-pin-768x616.png 768w" sizes="(max-width: 803px) 100vw, 803px" /><br>You also might need to enter a few records. Since we&#8217;re dealing with coordinates, you will need to Google maps and grab this information. Don&#8217;t worry &#8211; this is just for the prototype. We are building our own custom form &#8211; that will take care of all this information for us.<br></p>



<p><strong>The Apex Class</strong><br></p>



<p>An Apex Class can behave sort of like a hash table that can hold our functions. This is how we&#8217;re going to interact with data from our Lightning components. Go ahead and create a class called &#8220;Pin&#8221;. Let&#8217;s add a method in there that grabs all of our Pins as well:</p>



<pre class="wp-block-code"><code lang="java" class="language-java">public with sharing class Pin {
    public static List&lt;Pin__c&gt; getPins(){
        String sql = 'select Name, City__c, Lat__c, Long__c, Content__c, 
        Country__c, Region__c, Continent__c from Pin__c ORDER BY CreatedDate  
        DESC';
        List&lt;Pin__c&gt; PinList = Database.query(sql);
        return PinList;
    }
}</code></pre>



<p>Above is a class that has one static method &#8220;<strong>getPins</strong>&#8220;. This means that we don&#8217;t have to instantiate the class to use the method. The <strong>@auraEnabled&nbsp;</strong>declaration also make it callable directly from our Lightning components.</p>



<p><br><strong>Component</strong><br></p>



<p>Once that&#8217;s done, go ahead and create a Lightning component &#8211; let&#8217;s call ours &#8220;<strong>Pin</strong>&#8220;. Open <strong>pin.cmp</strong> and add the code below:</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">
&lt;aura:component implements="flexipage:availableForAllPageTypes"  access="global" controller="Pin"&gt;
    &lt;ltng:require styles="{!$Resource.leaflet + '/leaflet.css'}" /&gt;
    &lt;ltng:require styles="{!$Resource.leafletMarkerCluster + '/leafletMarerClusterDefault.css'}" /&gt;
    &lt;ltng:require styles="{!$Resource.leafletMarkerCluster + '/leafletMarerCluster.css'}" /&gt;
    &lt;ltng:require scripts="{!join(',',$Resource.leaflet + '/leaflet.js', $Resource.leafletMarkerCluster + '/leafletMarerCluster.js')}" afterScriptsLoaded="{!c.jsLoaded}" /&gt;
&lt;/aura:component&gt;</code></pre>



<p>You will see that all we&#8217;re doing is setting our static resources up in our component file. We&#8217;re also doing&nbsp;<strong>controller=&#8221;Pin&#8221; </strong>in our component declaration. This means that we&#8217;re going to create an Apex class called &#8220;Pin&#8221;. We&#8217;ll get to that later.</p>



<p>Also note we have <strong>afterScriptsLoaded=&#8221;{!c.jsLoaded}&#8221; </strong>in our lightning scripts tag.&nbsp; This is because we want the function <strong>jsLoaded</strong> to run as soon as our scripts are loaded. We don&#8217;t have this function yet &#8211; so loading the page will cause an error. We&#8217;ll get to this function soon.</p>



<p>Let&#8217;s continue building the markup.</p>



<p>Still in our .cmp file, after our scripts and styles &#8211; add our markup below :</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;aura:attribute name="pins" type="List" default="[]"/&gt;
&lt;aura:attribute name="singlePin" type="Object" default="{}"/&gt;
&lt;div class="slds-grid"&gt;
        &lt;div class="leftcol-wrap slds-col slds-size_1-of-3"&gt;
            &lt;!--THIS IS THE LEFT HAND COLUMN, WHERE THE LOCATIONS WILL GO--&gt;
            &lt;!--THIS IS ALSO WHERE THE SINGLE LOCATION DETAIL WILL GO--&gt;
        &lt;/div&gt;&lt;!--leftcol-wrap--&gt;
        &lt;div class="map-wrap slds-col slds-size_2-of-3"&gt;
            &lt;div class="map" id="map" aura:id="map"&gt;&lt;/div&gt;
        &lt;/div&gt;&lt;!--end map-wrap--&gt;
&lt;/div&gt; &lt;!--end slds-grid--&gt;</code></pre>



<p>The &#8220;<strong>aura:attribute</strong>&#8221; named &#8220;<strong>pins</strong>&#8221; is simply a holder for the pins we&#8217;re grabbing from the controller. </p>



<p>More on this later.</p>



<p>The&nbsp;&#8220;<strong>aura:attribute</strong>&#8221; named &#8220;<strong>singlePin</strong>&#8221; is also a holder &#8211; for a pin that&#8217;s in focus. Again, more on this later.</p>



<p>This sets up our page. We&#8217;re splitting the page in two, one column is smaller (size_1-of-3) and the other bigger (size_2-of-3). We&#8217;re using built in Salesforce classes, with the prefix &#8220;slds&#8221;, stands for <a href="https://www.lightningdesignsystem.com">Salesforce Lightning Design System</a>. In case you&#8217;re not familiar with it &#8211; it&#8217;s sort of like Bootstrap and React fused into a single framework.</p>



<h3 class="wp-block-heading" id="the-map">The Map</h3>



<p>So we&#8217;re ready to load the page and initialize our Leaflet map. We have our temp data in our custom object, we should have our component &#8211; along with the JavaScript files in place. Let&#8217;s write the&nbsp;<strong>jsLoaded</strong>() function (this is called when our scripts are done loading):</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">jsLoaded: function(component, event, helper) {
	var mapOptions = {
		zoomControl: true,
		zoomAnimation:false, //fixes the error when zooming in...
		markerZoomAnimation:true
	}
        var map = L.map('map', mapOptions)
        map.setView([48.85661400000001, 2.3522219], 2);
        map.scrollWheelZoom.disable();
        helper.map = map;
        L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', {attribution: 'Location'}).addTo(map);
        helper.callServer(component,'c.getPins', function(response){
        	component.set('v.pins',response);
        	helper.buildMap(component, event, helper, response);
        },{});
	}</code></pre>



<p>Okay, a lot going on here. We&#8217;re setting some map default options (for more info on Leaflet, see their <a href="https://leafletjs.com/reference-1.3.2.html">documentation</a>).&nbsp;&nbsp;We also have a very important helper function called &#8220;.<strong>callServer()</strong>&#8220;. This function is responsible for making the call to our Apex class, and returns our data. Note that I talk about <strong>callServer</strong> in a previous <a href="https://michaelsoriano.com/call-apex-from-lightning-components/">post</a>. Simply add this function in your <strong>PinHelper.js</strong> file and that should be good to go.<br>Inside our callback we&#8217;re setting the <strong>v.pins</strong>&nbsp;in our .cmp file &#8211; which is an array of objects that came back from our server.</p>



<p>Right after we have a function called .<strong>buildMap()</strong>&nbsp;&#8211; which is a pretty big function and discussed in detail below.</p>



<h3 class="wp-block-heading" id="the-map">The Map</h3>



<p>So our pins our fetched from the server. I don&#8217;t know if you remember, that we are using a Leaflet add-on called <strong>LeafletMarkerCluster</strong> &#8211; which is what does the clustering of the pins &#8211; that are in the same proximity. What this does is &#8211; it creates a nice visual &#8211; the number of pins in a specific grouping, that you can click &#8211; and it will zoom in further to show the pins.</p>



<p>It also has a nice &#8220;spider&#8221; effect &#8211; for the clusters &#8211; which is really cool:</p>



<p><img decoding="async" width="669" height="380" class="alignnone size-full wp-image-6666" style="border: 1px solid #ededed;" src="https://michaelsoriano.com/wp-content/uploads/2018/07/clusters.gif" alt="Cluster"><br>So what we need is a way to group our pins. Notice our custom object earlier &#8211; we have a field called &#8220;Region&#8221;. A region is similar to a &#8220;State&#8221; in the United States. So every pin that share the same region &#8211; will be clustered. Make sure your test data have pins that have the same region, and some that don&#8217;t.</p>



<p>Don&#8217;t worry &#8211; we don&#8217;t have to figure out what region our pins need to be &#8211; remember we&#8217;re building our own form.</p>



<p><strong>The .buildMap() function</strong></p>



<p>Now let&#8217;s dig in to the actual code that adds and groups the pins to the map. Open <strong>PinHelper.js</strong> and add the code below:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">map : {},
mapLayers : {},
markerGroups : [],
markerList : [],
buildMap : function(component, event, helper, response){
        var map = helper.map;
        function onMarkerClick(e){
            //TODO: ADD LOGIC WHEN MARKER IS CLICKED
        }
        function onlyUnique(value, index, self) {
            return self.indexOf(value) === index;
        }
        function popupHtml(pinName){
            return '&lt;strong&gt;' + pinName + '&lt;/strong&gt;';
        }
        var markerGroups = helper.markerGroups;
        for(var y=0; y&lt;markerGroups.length;y++){
            markerGroups[y].clearLayers();
        }
        var groups = [];
        for(var i=0; i&lt;response.length;i++){
           groups.push(response[i].Region__c);
        }
        var uniqueGroups = groups.filter(onlyUnique);
        var markerOpts = {
            draggable : false
        }
        var markerList = [];
        for(var x=0; x&lt;uniqueGroups.length;x++){
            var markers;
            markers = L.markerClusterGroup();
            helper.markerGroups.push(markers);
            for(var i=0; i&lt;response.length;i++){
                if(response[i].Region__c == uniqueGroups[x]){
                    markerOpts.alt = response[i].Id; //marker options
                    markerOpts.icon = L.icon({iconUrl : 'YOURICONIMAGE.png'});
                    var mark = L.marker([response[i].Lat__c,response[i].Long__c],markerOpts).on('click', onMarkerClick);
                    var popup = mark.bindPopup(popupHtml(response[i].Name));
                    popup.on('popupclose',function(){
                        helper.closeSinglePin(component, event, helper);
                    })
                    markers.addLayer(mark).addTo(map);
                    markerList[response[i].Id]=mark;
                }
            }
        }
        helper.markerList = markerList;
    },</code></pre>



<p>First, let&#8217;s set some variables in our helper (lines 1-4). These will act as a container as we pass them around from our controller to helper and vice versa.</p>



<p>Then the actual buildMap() function. We have gone through our pins and determined the unique regions and stuffed them into&nbsp;<strong>helper.markerGroups. </strong>Now starting in line 39, we loop through each of pin and add them to the map &#8211; according to their respective groups (region). Passing along the necessary options for each pin.</p>



<p>Your map should now load with the clusters and the pins.</p>



<h3 class="wp-block-heading" id="the-list-of-pins-left-side">The List of Pins (Left Side)</h3>



<p>On the left side of the application &#8211; we show all of the pins &#8211; sorted by latest entry. Remember that we set our pins as a component attribute in our <strong>jsLoaded() </strong>function? Now all we need to do is loop through this in our component. But first, we have to check if there&#8217;s a&nbsp;<strong>singlePin </strong>&#8211; why you ask? This is to determine if we clicked on a marker on the map OR we clicked on any of the item in our list (which we&#8217;re still building).</p>



<p>We do this by using the&nbsp;<strong>aura:if </strong>directive<strong>.</strong></p>



<p>The code below goes into the left hand section.</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;aura:if isTrue="{!v.singlePin.Id}"&gt;
	&lt;div class="singlePin" aura:id="singlePin"&gt;
		&lt;lightning:button class="closeSinglePin" onclick="{!c.closeSinglePin}"&gt;Close&lt;/lightning:button&gt;
		 &lt;h3&gt;{!v.singlePin.Name}&lt;/h3&gt;
		 &lt;div class="singleMeta"&gt;
			&lt;span&gt;{!v.singlePin.Region__c}, &amp;nbsp;&lt;/span&gt;
			&lt;span&gt;{!v.singlePin.Continent__c}&lt;/span&gt;
		 &lt;/div&gt;
		 &lt;div class="singleContent"&gt;
			 &lt;aura:unescapedHtml value="{!v.singlePin.Content__c}" /&gt;
		 &lt;/div&gt;
		 &lt;forceChatter:publisher context="RECORD" recordId="{!v.singlePin.Id}" /&gt;
		 &lt;forceChatter:feed type="Record" subjectId="{!v.singlePin.Id}" /&gt;
	&lt;/div&gt;
	&lt;aura:set attribute="else"&gt;
		&lt;h3 class="pinstitle"&gt;Locations&lt;/h3&gt;
		&lt;aura:iteration items="{!v.pins}" var="pin"&gt;
		&lt;lightning:button class="pinListItem" name="{!pin.Id}" onclick="{!c.markerClick}" &gt;
			&lt;div class="pin-name"&gt;{!pin.Name}&lt;/div&gt;
			&lt;div class="pin-meta"&gt;
				&lt;span class="pin-region"&gt;{!pin.Region__c}&lt;/span&gt;&amp;nbsp;
				&lt;span class="pin-country"&gt;{!pin.Country__c}&lt;/span&gt;
			&lt;/div&gt;
		&lt;/lightning:button&gt;
		&lt;/aura:iteration&gt;
	&lt;/aura:set&gt;
&lt;/aura:if&gt;</code></pre>



<p>Let&#8217;s look at the singlePin scenario first &#8211; which is when an item is clicked. We are simply displaying some data from the singlePin &#8211; along with a button to close it (this <strong>.closeSinglePin() </strong>is not built yet). Then notice the use of&nbsp;&nbsp;<strong>forceChatter:publisher</strong> and&nbsp;<strong>forceChatter:feed</strong>. These components are built in to Lightning &#8211; all we need to do is pass it a Id &#8211; and voila!</p>



<p>This will display our single pin nicely &#8211; along with a Chatter component right below it.</p>



<p><br><img decoding="async" width="534" height="551" class="alignnone size-full wp-image-6664" style="border: 1px solid #ededed;" src="https://michaelsoriano.com/wp-content/uploads/2018/07/chatter.gif" alt="Locations with Chatter"><br></p>



<p>For the list, you see how we wrapped each pin as a <strong>lightning:button</strong>? That&#8217;s because we can click each item and something will happen. We have a <strong>c.markerClick </strong>handler on each item that we haven&#8217;t built yet.<br>The rest is simply markup of the pin details. Let&#8217;s create that handler.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">markerClick : function(component, event, helper){
	var markerId = event.getSource().get("v.name");
	var marker = helper.markerList[markerId];
	var markerGroupId = marker['__parent']['_group']['_leaflet_id'];
	var parentChildCount = marker['__parent']['_childCount'];
	if(parentChildCount &gt; 1){
		 for(var i=0; i&lt;helper.markerGroups.length; i++){
			if(helper.markerGroups[i]._leaflet_id == markerGroupId){
				helper.markerGroups[i].zoomToShowLayer(marker, function () {
					console.log('zoomed to layer');
					marker.fire('click')
					marker.openPopup();
				});
			}
		 }
	}else{
		marker.fire('click')
		marker.openPopup();
	}
}</code></pre>



<p>Remember, each item in our list &#8211; when clicked, will have the same behavior as clicking the pin (marker) on the map. So the above code is simply a trigger (using <strong>marker.fire()</strong>). But the check before that is to determine &#8211; if the marker is inside a cluster. If it is &#8211; we zoom to the layer first (using&nbsp;<strong>.zoomToShowLayer()</strong>), then fire.</p>



<p>Also, remember that we don&#8217;t have any behavior yet in when we click our pins (we have it as a TODO in our <strong>.buildMap()</strong> function above). Let&#8217;s go back and create that now.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function onMarkerClick(e){
	component.set('v.singlePin',{});  //resets to {}
	var id = e.target.options.alt;
	var latLong = e.target.getLatLng();
	if(e.target['_preSpiderfyLatlng']){
		latLong = e.target['_preSpiderfyLatlng']
	}
	map.setView(latLong);
	var pins = component.get('v.pins');
	for(var x=0; x&lt;pins.length;x++){
		if(pins[x].Id == id){
			component.set('v.singlePin',pins[x]);
		}
	}
}</code></pre>



<p>The handler above reset&#8217;s the singlePin to an empty object. Then we get the lat and long from the marker (we get it from &#8220;<strong>e</strong>&#8221; &#8211; or the <strong>event</strong>). We set the view on the map according to the coordinates.&nbsp; Then finally &#8211; we loop through our pins &#8211; and set the <strong>v.singlePin&nbsp;</strong>into the one clicked.</p>



<p>Lastly, the&nbsp;<strong>.closeSinglePin() </strong>function:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">closeSinglePin : function(component, event, helper){
        var map = helper.map;
        var defaultChatterFeed = component.find('defaultChatterFeed');
        var singlePin = component.find('singlePin');
        $A.util.removeClass(defaultChatterFeed, 'slds-hide');
        $A.util.addClass(singlePin, 'slds-hide');
        component.set('v.singlePin',{});
	map.setView([48.85661400000001, 2.3522219], 2);
        map.closePopup();
    },</code></pre>



<p>The above simply hides our Single Pin and Chatter, resets the singlePin variable, then resets the map.</p>



<h3 class="wp-block-heading" id="the-form">The Form</h3>



<p>Finally, we come to the data entry section &#8211; where it will make it easy for us to add pins to our map. This form will have the necessary fields for our custom object &#8211; but most importantly, the auto-suggest field &#8211; that will auto populate the longitude, latitude, region etc.</p>



<p><img decoding="async" width="747" height="326" class="alignnone size-full wp-image-6665" style="border: 1px solid #ededed;" src="https://michaelsoriano.com/wp-content/uploads/2018/07/cities.gif" alt="City autocomplete"></p>



<p><br>I wrote a <a href="https://michaelsoriano.com/lightning-component-google-places/">tutorial</a> about this Auto-suggest field &#8211; using Google Places API, so I&#8217;m not going to get into that code. I&#8217;m simply going to go through the rest of the logic &#8211; that makes our form.</p>



<p>First off, we&#8217;re showing our form in a modal. Still in the same component, let&#8217;s add this to the lower section of our <strong>.cmp</strong> file:</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;lightning:button name="openNewPin" onclick="{!c.openNewPin}"&gt;Add New&lt;/lightning:button&gt;
&lt;aura:attribute name="newPin" type="Pin__c" default="{}"/&gt;
&lt;aura:attribute name="predictions" type="List" default="[]"/&gt;
&lt;aura:attribute name="validationErrors" type="List" default="[]"/&gt;
&lt;div role="dialog" tabindex="-1" aura:id="newPinModal" class="slds-modal"&gt;
	&lt;div class="slds-modal__container"&gt;
		&lt;div class="slds-modal__header"&gt;
			&lt;button class="slds-button slds-modal__close slds-button--icon-inverse" title="Close" onclick="{!c.closenewPin}"&gt;&lt;span class="slds-assistive-text"&gt;Close&lt;/span&gt;
			&lt;/button&gt;
			&lt;h2 id="header43" class="slds-text-heading--medium"&gt;Add New Pin&lt;/h2&gt;
		&lt;/div&gt;
		&lt;div class="slds-modal__content slds-p-around--medium"&gt;
			&lt;div&gt;
				&lt;aura:if isTrue="{!v.validationErrors.length &gt; 0}"&gt;
				&lt;ul class="validationErrorList"&gt;
				&lt;aura:iteration items="{!v.validationErrors}" var="validationError"&gt;
					&lt;li&gt;{!validationError}&lt;/li&gt;
				&lt;/aura:iteration&gt;
				&lt;/ul&gt;
				&lt;/aura:if&gt;
				&lt;lightning:input label="Name" value="{!v.newPin.Name}"/&gt;
				&lt;label style="margin:12px 0 3px; display:block;"&gt;Content&lt;/label&gt;
				&lt;lightning:inputRichText value="{!v.newPin.Content__c}" /&gt;
				&lt;div style="position:relative;"&gt;
				&lt;lightning:input label="City"
					value="{!v.newPin.City__c}"
					onchange="{!c.getCities}" /&gt;
					&lt;aura:if isTrue="{!v.predictions.length &gt; 0}"&gt;
						&lt;ul class="city_predictions"&gt;
							&lt;aura:iteration items="{!v.predictions}" var="prediction"&gt;
							&lt;li class="slds-listbox__item"&gt;
								&lt;a onclick="{!c.getCityDetails}" data-placeid="{!prediction.place_id}"&gt;{!prediction.description}&lt;/a&gt;
							&lt;/li&gt;
							&lt;/aura:iteration&gt;
						&lt;/ul&gt;
					&lt;/aura:if&gt;
				&lt;lightning:input value="{!v.newPin.Lat__c}" class="slds-hide" /&gt;
				&lt;lightning:input value="{!v.newPin.Long__c}" class="slds-hide"/&gt;
				&lt;lightning:input value="{!v.newPin.Region__c}" class="slds-hide"/&gt;
				&lt;lightning:input value="{!v.newPin.Country__c}"  class="slds-hide"/&gt;
				&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div class="slds-modal__footer"&gt;
			&lt;lightning:button onclick="{!c.saveRecord}"&gt;Submit&lt;/lightning:button&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/div&gt;
&lt;!--end new pin--&gt;
&lt;div class="slds-backdrop " aura:id="Modalbackdrop"&gt;&lt;/div&gt;
&lt;lightning:notificationsLibrary aura:id="notifLib"/&gt;&lt;!--toast message--&gt;</code></pre>



<p>The&nbsp;<strong>lightning:button </strong>in the beginning, is what opens up the modal. It&#8217;s up to you how you want to show this button, and who to show it to.</p>



<p>The next three lines you&#8217;ll notice that we&#8217;re setting some new attributes. Again, these act as a containers for the variables we&#8217;re using in our component.</p>



<p>The SLDS dialog box contain a close button, a header, a footer&nbsp; and a backdrop. The close button triggers a function&nbsp;<strong>closenewPin()&nbsp;</strong>when clicked. We&#8217;ll get to this later. Then we have a validation error list, then the form fields.</p>



<p>The &#8220;City&#8221; has an onchange handler called&nbsp;<strong>getCities() </strong>&#8211; which grabs the predictions from our Apex class. Again this was in a <a href="https://michaelsoriano.com/lightning-component-google-places/">previous tutorial</a> and find out how it&#8217;s done there.&nbsp; The&nbsp;<strong>lightning:input </strong>fields that have a class &#8220;<strong>slds-hide</strong>&#8221; &#8211; are hidden fields. These fields are automatically filled &#8211; and will require no user interaction.</p>



<p>Finally, the&nbsp;<strong>lightning:button&nbsp;</strong>that takes care of saving the record.</p>



<p>Oh, we also have&nbsp;<strong>lightning:notificationsLibrary </strong>at the very end &#8211; which is Salesforce&#8217;s toast notification. We use this for messaging when successful.</p>



<p><strong>Saving the Record</strong></p>



<p>First let&#8217;s take care of the entering our record. Open the controller and add the method &#8220;<strong>saveRecord</strong>&#8221; below:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">saveRecord : function(component, event, helper){
	var newPin = component.get('v.newPin');
	var str = JSON.stringify(newPin);
	//validation
	var errors = [];
	if(!newPin['Name']){
		errors.push('Name cannot be empty');
	}
	if(!newPin['City__c']){
		errors.push('City cannot be empty');
	}
	component.set('v.validationErrors', errors);
	if(errors.length &gt; 0){
		return false;
	}
	helper.callServer(component,"c.savePin",function(data){
		helper.callServer(component,'c.getPins', function(response){
			component.set('v.Pins',response);
			component.set('v.newPin',{});
			helper.buildMap(component, event, helper, response);
			helper.closeModal(component, 'newPinModal');
			helper.showToast(component, 'success', 'A Pin has been added.');
		},{});
	},{"strsRecord" : str});
},</code></pre>



<p>This function gets called as soon as the user clicks the &#8220;<strong>Save</strong>&#8221; button. First, we do some validation &#8211; and see if our required fields are filled in. If not, we set the <strong>validationErrors&nbsp;</strong>array up and exits.</p>



<p>Otherwise, we do a <strong>.callServer() </strong>twice. First to save the pin &#8211; and inside it&#8217;s callback, we do another&nbsp;<strong>.callServer() </strong>to get all of the pins. This is so that once we add a new pin &#8211; it grabs the new set of pins &#8211; so we can see it right away on the map. Remember I discussed about the <strong>.callServer() </strong>function in &#8220;<a href="https://michaelsoriano.com/call-apex-from-lightning-components/">Call Apex from Lightning components</a>&#8220;.</p>



<p>This is the part that actually does the saving to the database. Add this to your Apex class &#8211; as another method:</p>



<pre class="wp-block-code"><code lang="java" class="language-java">@AuraEnabled
public static Pin__c savePin(String strsRecord){
	Pin__c strsRecord2 = (Pin__c)JSON.deserialize(strsRecord,Pin__c.class);
	try{
		if(strsRecord2 != null){
			insert strsRecord2;
		}
	}catch (Exception ex){
	}
	return strsRecord2;
}</code></pre>



<p>Finally, we call&nbsp;<strong>.buildMap(), .closeModal() </strong>and <strong>.showToast(). </strong>You get what those functions are doing. Let&#8217;s add what&#8217;s missing in our helper. Open <strong>PinHelper.js</strong>&nbsp;and add the code below:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">closeModal : function(component, modal){
	var cmpTarget = component.find(modal);
	var cmpBack = component.find('Modalbackdrop');
	$A.util.removeClass(cmpBack,'slds-backdrop--open');
	$A.util.removeClass(cmpTarget, 'slds-fade-in-open');
},
openModal : function(component,modal){
	var cmpTarget = component.find(modal);
	var cmpBack = component.find('Modalbackdrop');
	$A.util.addClass(cmpTarget, 'slds-fade-in-open');
	$A.util.addClass(cmpBack, 'slds-backdrop--open');
},
showToast : function(component, variant, msg){
	var toastSettings = {
		"title": variant,
		"message": msg,
		"variant" : variant,
		"mode" : "dismissable"
	}
	component.find('notifLib').showToast(toastSettings);
},</code></pre>



<p>The helper functions above are pretty self-explanatory. For further explanation &#8211; especially about the utilities available in the $A object &#8211; refer to this <a href="https://salesforce.stackexchange.com/questions/54032/what-are-the-available-a-javascript-functions-in-lightning">question</a> in StackOverflow.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">closeNewPin : function(component, event, helper){
		helper.closeModal(component, 'newPinModal');
},
openNewPin : function(component, event, helper){
	helper.openModal(component, 'newPinModal');
},
closeSinglePin : function(component, event, helper){
	helper.closeSinglePin(component, event, helper)
},</code></pre>



<p>Lastly, the above methods are in our helper, but we need to access them using our controller. Simply add the code below to our controller:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">closeNewPin : function(component, event, helper){
		helper.closeModal(component, 'newPinModal');
},
openNewPin : function(component, event, helper){
	helper.openModal(component, 'newPinModal');
},
closeSinglePin : function(component, event, helper){
	helper.closeSinglePin(component, event, helper)
},</code></pre>



<p>And after all is in place, our form should now be working:</p>



<p><img decoding="async" width="633" height="547" class="alignnone size-full wp-image-6700" src="https://michaelsoriano.com/wp-content/uploads/2018/07/form.gif" alt="Form"></p>



<h3 class="wp-block-heading" id="conclusion">Conclusion</h3>



<p>There you have it. A cool map with events, clusters, a custom form &#8211; a good start of a real world application you can build inside Salesforce. Keep in mind these are mostly using Lightning &#8211; unless we had to build it ourselves. </p>



<p>Next up should be filtering the results, adding a better Hover callout on the pins, maybe even having the latest chatter in the hover. The possibilities are endless.</p>
<p>The post <a href="https://michaelsoriano.com/lets-build-map-application-using-leaflet-and-lightning-components/">Let&#8217;s build a Map Application using Leaflet and Lightning Components</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/lets-build-map-application-using-leaflet-and-lightning-components/feed/</wfw:commentRss>
			<slash:comments>25</slash:comments>
		
		
			</item>
		<item>
		<title>Let&#8217;s Build an AutoSuggest Lightning Component with Google Places API</title>
		<link>https://michaelsoriano.com/lightning-component-google-places/</link>
					<comments>https://michaelsoriano.com/lightning-component-google-places/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Fri, 11 May 2018 22:18:19 +0000</pubDate>
				<category><![CDATA[Salesforce]]></category>
		<category><![CDATA[Aura]]></category>
		<guid isPermaLink="false">http://michaelsoriano.com/?p=6511</guid>

					<description><![CDATA[<p>I had the challenge of building an input form that brings up a list of cities as you type. One that has the coordinates of each city &#8211; because I&#8217;ll need to enter that into a map. An &#8220;auto-suggest&#8221; or &#8220;auto-complete&#8221; city input &#8211; inside a custom form inside Salesforce. It turns out, that it [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/lightning-component-google-places/">Let&#8217;s Build an AutoSuggest Lightning Component with Google Places API</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I had the challenge of building an input form that brings up a list of cities as you type. One that has the coordinates of each city &#8211; because I&#8217;ll need to enter that into a map. An &#8220;auto-suggest&#8221; or &#8220;auto-complete&#8221; city input &#8211; inside a custom form inside Salesforce. It turns out, that it wasn&#8217;t so bad.</p>



<p>We&#8217;re using <a href="https://developers.google.com/places/">Google Places</a> for our API and Lightning Components for our Front End. If you&#8217;re not familiar with Lightning, check their <a href="https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/intro_framework.htm">documentation</a>.</p>



<p>Our component will look like below.</p>



<p><img decoding="async" width="617" height="214" class="alignnone size-full wp-image-6512" src="https://michaelsoriano.com/wp-content/uploads/2018/04/auto-suggest.png" alt="lightning input autosuggest" srcset="https://michaelsoriano.com/wp-content/uploads/2018/04/auto-suggest.png 617w, https://michaelsoriano.com/wp-content/uploads/2018/04/auto-suggest-300x104.png 300w" sizes="(max-width: 617px) 100vw, 617px" /></p>



<p>Ready to start coding? Let&#8217;s start.</p>



<h3 class="wp-block-heading" id="api-setup">API Setup</h3>



<p>Let&#8217;s get Google going. Remember, each time a user type a character &#8211; it will ping Google for suggestions. Also, the suggestions does not contain coordinates for each item, so we will need to ping the API as soon as the user selects a place.</p>



<p>I&#8217;m going to assume that you know how to get an API key from your Google account. If not, here is their <a href="https://developers.google.com/places/web-service/intro">API documentation</a>.</p>



<p>The first part is getting the suggestions. Below is the URL that we need for that:</p>



<p><strong>https://maps.googleapis.com/maps/api/place/autocomplete/json?input=TERM&amp;key=YOURKEY</strong></p>



<p>Looking at the above, we&#8217;re passing in what the user is typing where it says &#8220;TERM&#8221;.<br>The second part is when the user selects an item:</p>



<p><strong>https://maps.googleapis.com/maps/api/place/details/json?placeid=PLACEID&amp;key=YOURKEY</strong></p>



<p>The above shows a &#8220;placeid&#8221; parameter that we get from each suggestion. So when the user clicks &#8211; we pass the id to the above URL.</p>



<p>Now that we have our Places API setup. Let&#8217;s move forward to our Salesforce code.</p>



<h3 class="wp-block-heading" id="build-the-apex-class">Build the Apex Class</h3>



<p>One thing to note is that our Lighting components cannot reach out to Places API directly. Google doesn&#8217;t allow CORS to their endpoints &#8211; so we simply cannot do this. Nor would we want to &#8211; because if we do this via JavaScript &#8211; we will be exposing our keys. So we need the server to do the calls. In Salesforce, we use Apex.</p>



<p>We also have to add &#8220;maps.googleapis.com&#8221; to the remote site settings in Salesforce. To do this, go to &#8220;Setup&#8221; > &#8220;Security&#8221; > &#8220;Remote Site Settings&#8221;.</p>



<p>Click on &#8220;New Remote Site&#8221; and add the required fields:</p>



<p><img decoding="async" width="565" height="489" class="alignnone size-full wp-image-6551" src="https://michaelsoriano.com/wp-content/uploads/2018/05/remote-site-settings.png" alt="Remote site settings - Salesflorce" srcset="https://michaelsoriano.com/wp-content/uploads/2018/05/remote-site-settings.png 565w, https://michaelsoriano.com/wp-content/uploads/2018/05/remote-site-settings-300x260.png 300w" sizes="(max-width: 565px) 100vw, 565px" /></p>



<p>Now, let&#8217;s create our Apex Class. Copy the code below and add it to your Class:</p>



<pre class="wp-block-code"><code lang="java" class="language-java">@AuraEnabled
	public static string getSuggestions(String input) {
	    String url = 'https://maps.googleapis.com/maps/api/place/autocomplete/json?'
	            + 'input=' + EncodingUtil.urlEncode(input, 'UTF-8')
	            + '&amp;types=(cities)' + getKey();
	    String response = getResponse(url);
	    return response;
	}
@AuraEnabled
	public static string getPlaceDetails(String placeId) {
     	String url = 'https://maps.googleapis.com/maps/api/place/details/json?'
	            + 'placeid=' + EncodingUtil.urlEncode(placeId, 'UTF-8')
	            + getKey();
	    String response = getResponse(url);
	    return response;
	}
	public static string getResponse(string strURL){
		Http h = new Http();
		HttpRequest req = new HttpRequest();
		HttpResponse res = new HttpResponse();
		req.setMethod('GET');
		req.setEndpoint(strURL);
		req.setTimeout(120000);
		res = h.send(req);
		String responseBody = res.getBody();
		return responseBody;
	}
	public static string getKey(){
		string key = 'xxxxxxxxxxxxx';
		string output = '&amp;key=' + key;
		return output;
	}</code></pre>



<p>Note the two methods that have <strong>@AuraEnabled</strong>: getSuggestions() and getPlaceDetails(). These are the two endpoints we will be calling from our JavaScript in our Lightning component. Both methods are quite explanatory, they simply accept parameters from our front end, go out to Google and return the results.</p>



<p>Don&#8217;t forget to add your API key to the method getKey().</p>



<p>Let&#8217;s move on.</p>



<h3 class="wp-block-heading" id="our-component">Our&nbsp;Component</h3>



<p>The component (.cmp file) will need a few things. First, we need a couple of attributes to hold our values. One for location and one called &#8220;predictions&#8221;. The location is the value that will be in our input, while the predictions is what will show directly beneath it &#8211; in an unordered list. Note that this is what comes back from our API.  So add that first to your component.</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;aura:attribute name="location" type="string" default=""/>
&lt;aura:attribute name="predictions" type="List" default="[]"/></code></pre>



<p>We&#8217;re using &#8220;<strong>lightning:input</strong>&#8221; for our form field. We add a label, name, an aura:id, a value and an onchange attribute. The label and name is pretty straightforward, the aura:id &#8211; is simply a way for us to reference it in our controller.</p>



<p>The <strong>value</strong> &#8211; binds the input to our attribute &#8220;location&#8221;. Which we show as &#8220;<strong>v.location</strong>&#8220;.</p>



<p>The <strong>onchange &#8211; </strong>we&#8217;re attaching to a function in our controller named <strong>getCities(), </strong>which we refer to as &#8220;<strong>c.getCities</strong>&#8220;.</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;lightning:input label="Location"
                        name="location"
                        aura:id="location"
                        value="{!v.location}"
                        onchange="{!c.getCities}" /></code></pre>



<p>We&#8217;re using an unordered list for our suggestions. So we use the code below:</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;aura:if isTrue="{!v.predictions.length > 0}">
 	&lt;ul class="city_predictions">
		&lt;aura:iteration items="{!v.predictions}" var="prediction">
			&lt;li class="slds-listbox__item">
				&lt;a onclick="{!c.getCityDetails}" data-placeid="{!prediction.place_id}">{!prediction.description}&lt;/a>
			&lt;/li>
		&lt;/aura:iteration>
	&lt;/ul>
&lt;/aura:if></code></pre>



<p>Notice we wrap it an &#8220;<strong>aura:if</strong>&#8221;  &#8211; which determines if our predictions object has more than zero length. Remember, predictions is coming straight from the API.</p>



<p>Then we have an &#8220;<strong>aura:iteration</strong>&#8221; for each prediction to show up in a list item > anchor tag. Each anchor tag has an &#8220;onclick&#8221; (which we&#8217;re attaching to getCityDetails()) and a &#8220;data-placeid&#8221; (I&#8217;ll explain later).</p>



<h3 class="wp-block-heading" id="the-controller">The Controller</h3>



<p>So remember in our component we have 2 methods: getCities() and getCityDetails()? Those both go in our controller.</p>



<p>Our <strong>getCities() </strong>method is called every time we change the input field. Meaning &#8211; every time we type a letter, it calls this method.</p>



<p>First it sets up an object called &#8220;<strong>params</strong>&#8220;, which has one item in it called &#8220;<strong>input</strong>&#8220;. This is what we&#8217;re sending our Apex class through the use of <strong>helper.callServer()</strong>. This helper is explained in my previous post &#8220;<a href="https://michaelsoriano.com/call-apex-from-lightning-components/">Call Apex from Lightning</a>&#8220;. Once our Apex responds with some suggestions &#8211; we parse it through JSON.parse() and set it to our component attribute called &#8220;predictions&#8221;.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">getCities : function(component, event, helper){
	var params = {
	  "input" : component.get('v.location')
	}
	helper.callServer(component,"c.getSuggestions",function(response){
		var resp = JSON.parse(response);
		console.log(resp.predictions);
		component.set('v.predictions',resp.predictions);
	},params);
}</code></pre>



<p>So our UL of suggestions will only populate if there&#8217;s a response from the server.</p>



<p>Finally, <strong>getCityDetails()</strong> get&#8217;s triggered when we choose an item from our UL (or click the anchor tag).<br>Remember the &#8220;data-placeid&#8221; attribute that we have for each anchor tag? This is where we will need it.</p>



<p>We grab the value of &#8220;data-placeid&#8221; (which is the Place Id required for our API) through the event.currentTarget. We then create the &#8220;params&#8221; object like we did above.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">getCityDetails : function(component, event, helper){
	var selectedItem = event.currentTarget;
        var placeid = selectedItem.dataset.placeid;
	var params = {
	   "placeId" : placeid
	}
	helper.callServer(component,"c.getPlaceDetails",function(response){
		var placeDetails = JSON.parse(response);
		component.set('v.location',placeDetails.result.name);
		component.set('v.predictions',[]);
	},params);
}</code></pre>



<p>We then do a <strong>helper.callServer() </strong>and when finished, we parse then set the v.location (the input value) and v.predictions back to empty.</p>



<p>I specifically needed the coordinates for the selected location, which can easily be grabbed from the response. You can do something similar.</p>



<h3 class="wp-block-heading" id="the-final-product">The Final Product:</h3>



<p>Below is a short screengrab of the final output. The <strong>lightning:input</strong> makes our field look better than just a regular input. Also, this is a &#8220;barebones&#8221; solution for an auto suggest field. You can greatly enhance by adding icons, additional description for each place, maybe some more events (like on tab, enter etc).</p>



<p><br><img decoding="async" width="639" height="324" class="alignnone size-full wp-image-6514" style="margin-top: -15px;" src="https://michaelsoriano.com/wp-content/uploads/2018/04/auto-suggest.gif" alt="Lightning Auto Suggest"></p>
<p>The post <a href="https://michaelsoriano.com/lightning-component-google-places/">Let&#8217;s Build an AutoSuggest Lightning Component with Google Places API</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/lightning-component-google-places/feed/</wfw:commentRss>
			<slash:comments>14</slash:comments>
		
		
			</item>
		<item>
		<title>Call Apex from Lightning components</title>
		<link>https://michaelsoriano.com/call-apex-from-lightning-components/</link>
					<comments>https://michaelsoriano.com/call-apex-from-lightning-components/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Mon, 07 May 2018 17:20:45 +0000</pubDate>
				<category><![CDATA[Salesforce]]></category>
		<category><![CDATA[Aura]]></category>
		<guid isPermaLink="false">http://michaelsoriano.com/?p=6523</guid>

					<description><![CDATA[<p>I&#8217;ve decided to do some write up on Salesforce &#8211; especially Lightning development. Lightning is basically Salesforce&#8217;s proprietary JavaScript and CSS Framework bundled into one. It&#8217;s a component-based system, mobile friendly, with the power of a server side language (Apex), just in case you need it. In the following tutorials, you might see a &#8220;helper.callServer()&#8221; [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/call-apex-from-lightning-components/">Call Apex from Lightning components</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;ve decided to do some write up on Salesforce &#8211; especially Lightning development. <a href="https://www.lightningdesignsystem.com">Lightning</a> is basically Salesforce&#8217;s proprietary JavaScript and CSS Framework bundled into one. It&#8217;s a component-based system, mobile friendly, with the power of a server side language (Apex), just in case you need it.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="810" height="405" src="https://michaelsoriano.com/wp-content/uploads/2022/07/lighting-web-components.png" alt="lightning web components" class="wp-image-7767" srcset="https://michaelsoriano.com/wp-content/uploads/2022/07/lighting-web-components.png 810w, https://michaelsoriano.com/wp-content/uploads/2022/07/lighting-web-components-300x150.png 300w, https://michaelsoriano.com/wp-content/uploads/2022/07/lighting-web-components-768x384.png 768w" sizes="(max-width: 810px) 100vw, 810px" /></figure>



<p>In the following tutorials, you might see a &#8220;<strong>helper.callServer()</strong>&#8221; method &#8211; which I&#8217;m outlining below:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">callServer : function(component,method,callback,params) {
        var action = component.get(method);
        if (params) {
            action.setParams(params);
        }
        action.setCallback(this,function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                // pass returned value to callback function
                callback.call(this,response.getReturnValue());
            } else if (state === "ERROR") {
                // generic error handler
                var errors = response.getError();
                if (errors) {
                    console.log("Errors", errors);
                    if (errors[0] &amp;&amp; errors[0].message) {
                        throw new Error("Error" + errors[0].message);
                    }
                } else {
                    throw new Error("Unknown Error");
                }
            }
        });
        $A.enqueueAction(action);
    }</code></pre>



<p>If you&#8217;re ever going to do some kind of call to an Apex class &#8211; this is a must have in your helper. Think of it as sort of like jQuery&#8217;s $.ajax() method &#8211; but limited to a specific class.</p>



<p>Salesforce has the same exact code in this <a href="https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/controllers_server_actions_call.htm">doc</a>&nbsp;with some explanation, but I wanted to write it up in my own words.&nbsp;Let&#8217;s break it down below.</p>



<p>As mentioned, this is what we need to call an Apex class from our components. It is basically a wrapper to an&nbsp;<a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest</a>, along with other utilities to make our JavaScript easier.</p>



<p>Again, components are front end code &#8211; Apex sits in the server. This method is the communication between the two.</p>



<h3 class="wp-block-heading">Set up Apex</h3>



<p>First, you declare a class. This is done in our .cmp (component) file, way at the top &#8211; it looks like below:</p>



<p><strong>&lt;aura:component implements=&#8221;&#8230;&#8221; controller=&#8221;MyClass&#8221;&gt;</strong></p>



<p>Now we&#8217;re set up with an Apex class called &#8220;MyClass&#8221;. Let&#8217;s build that class, with a method called &#8220;doSomething()&#8221;:</p>



<pre class="wp-block-code"><code lang="java" class="language-java">public with sharing class MyClass{
   @auraEnabled
   public static string doSomething(String input) {
      return input
   }
}</code></pre>



<p>Note the &#8220;@auraEnabled&#8221; declaration. This allows us to access it from our JavaScript.</p>



<p>With the our helper in place, all we need to do in our controller will be something like below:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">helper.callServer(component,"c.doSomething",function(response){
    //INSIDE OUR CALLBACK
    console.log(response) //RESPONSE FROM OUR APEX METHOD
},{})</code></pre>



<p>You see, our helper had arguments that looked like below:</p>



<p><strong>callServer : function(component,method,callback,params) {&#8230;</strong></p>



<p>Which is what we&#8217;re doing in our controller. The second parameter &#8220;c.doSomething&#8221; &#8211; is the method in our Apex class. The 3rd parameter &#8220;callback&#8221; &#8211; is an anonymous function that get&#8217;s triggered through &#8220;.apply()&#8221; in our helper. This is executed when our Ajax call finishes. And we&#8217;ll have access to the response.</p>



<h3 class="wp-block-heading">Sending Parameters</h3>



<p>You can send information to your Apex class by setting an object to the last parameter called &#8220;params&#8221;. In our example above, we&#8217;re simply passing an empty object &#8220;{}&#8221;. But in reality, you will most likely send something to the server.</p>



<p>Our method &#8220;doSomething&#8221; is expecting a string called &#8220;input&#8221;.</p>



<p>The object we can pass will look like below:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">{
  "input" : "somevalue"
}</code></pre>



<p>Notice the key &#8220;input&#8221; must match our server variable &#8220;input&#8221;.</p>



<p>If you would like to pass another value, simply add another key:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">{
  "input" : "somevalue",
  "input2" : "somevalue2"
}</code></pre>



<p>In our doSomething method:</p>



<p><strong>doSomething(String input, String input2)</strong></p>



<p>You can also pass multiple values as a JSON string, so in your controller:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">var str = JSON.stringify({"input1":"somevalue","input2":"somevalue2"});
var params = {"strsRecord" : str};
helper.callServer(component,"c.doSomething",function(){}, params);</code></pre>



<p>In your Apex class:</p>



<pre class="wp-block-code"><code class="">doSomething(strsRecord){
   List st = JSON.deserialize(strsRecord);
   System.debug('Here is the params:' +st);</code></pre>



<h3 class="wp-block-heading">&#8220;Promise&#8221; Style</h3>



<p>In JavaScript, a <a href="https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-promise-27fc71e77261">promise</a> is &#8220;<em>an object that may produce a single value some time in the future</em>&#8220;. So our helper above is a perfect example of this. Let&#8217;s rewrite it using a promise, so we can use it more efficiently, and elegantly.</p>



<p>By this, I mean avoiding &#8220;callback&#8221; hell. See, callbacks are okay if we&#8217;re dealing with a single call. But if we were to make multiple nested calls (especially one that needs relies on the first response etc), it gets ugly real fast like below:&nbsp;</p>



<p><strong>Callback hell:</strong></p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">helper.callServer(component,"c.doSomething1",function(response1){
     helper.callServer(component,"c.doSomething2",function(response2){
         helper.callServer(component,"c.doSomething3",function(response3){
               //THIS GETS UGLY...
          },{})
     },{})
},{})</code></pre>



<p>So let&#8217;s convert it to use a JavaScript promise instead: </p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">callServer : function(component,method,params) {     //PROMISE BASED
        var promiseObj = new Promise(
            function(resolve, reject){
                var action = component.get(method);
                if (params) {
                    action.setParams(params);
                }
                action.setCallback(this,function(response) {
                    var state = response.getState();
                    if (state === "SUCCESS") {
                        var data = response.getReturnValue();
                        resolve(data)
                    } else if (state === "ERROR") {
                        var errors = response.getError();
                        console.log(errors);
                        reject(errors);
                    }
                });
                $A.enqueueAction(action);
            }
        );
        return promiseObj;
    }</code></pre>



<p>As you can see above, there are no more callbacks being passed. All we need are the 3 parameters: &#8220;component&#8221;, &#8220;method&#8221; and &#8220;params&#8221;. </p>



<p>Now we can use this like below:</p>



<pre class="wp-block-code"><code class="">helper.callServer(component,"c.doSomething",{}).then(function(response){
   console.log(response)
})</code></pre>



<p>You see the use of &#8220;.then()&#8221;. We&#8217;re no longer restricted to a single callback function we were previously. We can even use multiple .then() methods all over our code:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">var ajax = helper.callServer(component,"c.doSomething",{});
//first .then()
ajax.then(function(response){
   console.log('do something here');
})
//second.then()
ajax.then(function(response){
   console.log('do more stuff here');
})</code></pre>



<p>We can also chain Promise methods like so: </p>



<pre class="wp-block-code"><code class="">var ajax = helper.callServer(component,"c.doSomething",{});
ajax.then(function(response){
   console.log(response);
}).catch(function(error){
   console.log(error)
}).finally(function(){
   console.log('this always runs')
})</code></pre>



<p>As you can see, the &#8220;Promise&#8221; style of the helper can help you write more efficient code. </p>



<p>So keep this in your Lightning helper, in order to communicate with Apex. Its almost always guaranteed to be used at least once in your Salesforce applications. </p>
<p>The post <a href="https://michaelsoriano.com/call-apex-from-lightning-components/">Call Apex from Lightning components</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/call-apex-from-lightning-components/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
