salesforce.com development
Understanding Expressions in Lightning
Hi All,
Yesterday I stuck with Expressions in Lightning. While solving this I came to know about different ways of using Expressions and different types of these.
An expression is any set of literal values, variables, sub-expressions, or operators that can be resolved to a single value. You can use expressions for dynamic output or passing values into components by assigning them to attributes. Expressions are also used to provide action methods for user interface events(i.e. OnClick,OnHover).
Bound Expressions
Bound expression syntax is: {!expression}. Curly braces with “!” bang operator is used for Bound expressions.
If you are making any change using Bound expression it will immediately reflected on your component. Bound expressions are used to reflect changes on your Lightning Component. Below are examples of Bound expressions in component.
<aura:component> <!-- Accessing Fields and Related Objects --> <p>{!v.accounts.Name}</p> <!-- Concatinate value with String --> <p>{!'Hello ' + v.msg}</p> <!-- Ternary Operator --> <ui:button aura:id="likeBtn" label="{!(v.likeId == null) ? 'Like It' : 'Unlike It'}" /> <!-- Conditional Markup --> <aura:attribute name="edit" type="Boolean" default="true"/> <aura:if isTrue="{!v.edit}"> <ui:button label="Edit"/> <aura:set attribute="else"> You can’t edit this. </aura:set> </aura:if> <!-- Adding two items --> {!(v.item1) + (v.item2)} <!-- Using Global Variables --> {!$Browser.isPhone} {!$Locale.timezone} <!-- Action Method --> <ui:button aura:id="likeBtn" label="Press Me" press="{!c.update}"/> <!-- Array Length --> {!v.myArray && v.myArray.length > 0} </component>
Unbound Expressions
Unbound expression syntax is: {#expression}. Curly braces with “#” hash operator is used for Unbound expressions.
If you are making any change using unbound expression, it will not immediately reflect on your component. If you don’t want to reflect changes, you can use unbound expressions.
Note : Unbound expression changes are not reflected on component but they can be seen by javascript.
Below example show use of unbound expression in component.
//Component1.cmp <aura:component> <aura:attribute name="truthy" type="Boolean"></aura:attribute> <aura:if isTrue="{#v.truthy}"> True <aura:set attribute="else"> False </aura:set> </aura:if> <ui:button aura:id="button" label="Check" press="{!c.update}"/> </aura:component> //Component1Controller.js ({ update : function(component, event, helper) { component.set("v.truthy","false"); console.log('----> '+component.get("v.truthy")); } }) //Component1Renderer.js ({ rerender: function(cmp, helper) { console.log('rerender'); return this.superRerender() }, })
In above code when you click on “Check” button it will udpate unbound expression {!#v.truthy} in javascript controller. You will be able to see changes in console but they are not reflected on component.
Hope this will be helpful. Happy coding 🙂
Lightning Component Best Practices PART 2
Hi All,
Few days before I wrote an article on best practices of Lightning Components. In that article I told you about best practices of Lightning Component Bundle(Controller, Helper, Renderer) and Events. Today I will tell you about best practices to create secure Lightning Components.
In Winter 16 release Salesforce introduced an important change to Lightning Component, In order to run Lightning Components in your org, you will be required to use the My Domain feature.
Why My Domain? At Salesforce, Trust is their number one value. The security team that reviews all changes to the Force.com platform have determined that requiring of My Domain will allow Salesforce to enact even better security around Lightning Components. And better security is good for everyone.
Because of this new feature insecurity is not neccessorily coming from Lightning Components but can come from JavaScript(Client Side) or Apex(Server Side). All the insecurities may come from JavaScript rather than from Lightning Component. Reason for this is the JavaScript from same domain can actually access,modify and read everything. You should follow below best practices to avoid insecurities from Client Side and Server Side. I tried to explore them.
Client Side
- When modifying the DOM, avoid the use of HTML rendering functions such as innerHTML or $().append(). Rather use component getters and setters whenever possible.
//Component1.cmp <aura:component> <aura:attribute name="msg" type="String"></aura:attribute> <div><b>{!v.msg}</b></div> </aura:component> //Component1Helper.js ({ changeValue : function(component) { component.set("v.msg","Changed value before Render"); // Modifying DOM using setter }, }) //Component1Renderer.js ({ render: function(cmp, helper) { console.log('render'); helper.changeValue(cmp); // Modifying DOM in renderer return this.superRender() }, })
In above code I am modifying DOM using setter.
The DOM may only be modified in a renderer. Outside a renderer, the DOM is read-only. Suppose if you are trying to modify DOM in a controller than you are playing out side of the cycle of aura. If you do modification in controller the renderer will wipe all the DOM modification and you will end up with no result.
In above code I am modifying DOM in renderer.
Note : JS code within a component can only modify DOM elements belonging to the component. For example, it cannot modify document head or directly access the DOM element belonging to another component. In order to modify a parent or sibling component, an event should be passed to the target component. Child components should only be accessed via their attributes, and not by accessing the DOM of the child component directly.
Use $A.util.toggleClass() for component instead of a DOM element.
//toggleCss.cmp <aura:component> <div aura:id="changeIt">Change Me!</div><br /> <ui:button press="{!c.applyCSS}" label="Add Style" /> <ui:button press="{!c.removeCSS}" label="Remove Style" /> </aura:component> //toggleCssController.js ({ applyCSS: function(cmp, event) { var cmpTarget = cmp.find('changeIt'); $A.util.addClass(cmpTarget, 'changeMe'); }, removeCSS: function(cmp, event) { var cmpTarget = cmp.find('changeIt'); $A.util.removeClass(cmpTarget, 'changeMe'); } }) //toggleCss.css .THIS.changeMe { background-color:yellow; width:200px; }
window.setTimeout( $A.getCallback(function() { if (cmp.isValid()) { cmp.set("v.visible", true); } }), 5000 )
This sample sets the visible attribute on a component to true after a five-second delay.
<div onmouseover="myfunction" >foo</div> //bad <div onmouseover="c.myControllerFunction" >foo</div> //OK
window.onload = function () { //some code } document.write = function() { //some code }
<link type='text/css' rel='stylesheet' href='YOUR_CSS_FILE.css' /> //bad <script src="YOUR_JS_FILE.js"></script> //bad <ltng:require styles="CSS FILE 1,CSS FILE 2,..." scripts="JS FILE 1,JS FILE 2,.."></ltng:require> //OK
Server Side
- All controller classes must have the with sharing keyword. There are no exceptions. In some cases, your code will need to elevate privileges beyond those of the logged in user.
public class DemoController() { //Unsafe @AuraEnabled public static String getSummary() { //code } } public with sharing class DemoController() { //safe @AuraEnabled public static String getSummary() { //code } }
public with sharing class DemoController() { @AuraEnabled public static Contact getContact(String fieldName) { //safe if(Schema.SObjectType.Contact.fields.getMap().get('Name').getDescribe().isAccessible()){ //code } } }
Above best practices will help your Lightning Components in passing through security review of AppExchange.
Hope this will be helpful cheers!! 🙂