const express = require("express");
const app = express();
const Joi = require("joi");
app.use(express.json());
const genres = [
{ id: 1, name: "Action" },
{ id: 2, name: "Horror" },
{ id: 3, name: "Romance" }
];
app.get("/api/genres", (req, res) => {
res.send(genres);
});
app.get("/api/genres/:id", (req, res) => {
const genre = genres.find(c => c.id === parseInt(req.params.id));
if (!genre)
return res.status(404).send("The genre with the given ID was not found.");
res.send(genre);
});
app.post("/api/genres", (req, res) => {
const { error } = validateGenre(req.body);
if (error) return res.status(400).send(error.details[0].message);
const genre = {
id: genres.length + 1,
name: req.body.name
};
genres.push(genre);
res.send(genre);
});
app.put("/api/genres/:id", (req, res) => {
const genre = genres.find(c => c.id === parseInt(req.params.id));
if (!genre)
return res.status(404).send("The genre with the given ID was not found.");
const { error } = validateGenre(req.body);
if (error) return res.status(400).send(error.details[0].message);
genre.name = req.body.name;
res.send(genre);
});
app.delete("/api/genres/:id", (req, res) => {
const genre = genres.find(c => c.id === parseInt(req.params.id));
if (!genre)
return res.status(404).send("The genre with the given ID was not found.");
const index = genres.indexOf(genre);
genres.splice(index, 1);
res.send(genre);
});
function validateGenre(genre) {
const schema = {
name: Joi.string()
.min(3)
.required()
};
return Joi.validate(genre, schema);
}
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}...`));
Sunday, May 13, 2018
Monday, April 16, 2018
Salesforce Lightning: How to deal with cookies
You can use the below helper method to create a cookie.
So as an example, to create a cookie that stores the name of a visitor, you can call the helper method like below:
helper.createCookie('username', 'John Doe', 7);
To create a session cookie, don't pass any value for days. So you will be calling the helper method like below:
helper.createCookie('username', 'John Doe');
After executing the code above, the name of the cookie generated is
LSKey[c]username
. The name of the cookie is prefixed with LSKey[<c>]
where c
is the namespace. So to retrieve the value of this cookie, use the below code:So as an example, to retrieve the cookie value, you can call the helper method like below:
helper.getCookie('username');
Check the link in the references section to check how to delete the cookie.
References: https://www.sitepoint.com/how-to-deal-with-cookies-in-javascript/
Saturday, April 14, 2018
Testing the performance of Salesforce Lightning components
Unlike regular timestamps created with
Date.now()
, a high resolution timestamp is precise to a thousandth of a millisecond. Having this level of precision can be very useful when testing code that needs to run really fast. For those that work in environments that demand lightning fast code execution, this new level of accuracy is incredibly useful. To generate a high resolution timestamp, you need to use the now
method that is available on the performance
object.Please note that whileDate.now()
returns the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC,performance.now()
returns the number of milliseconds, with microseconds in the fractional part, fromperformance.timing.navigationStart()
, the start of navigation of the document, to theperformance.now()
call.
How to use performance.now() ?
You need to create a variable before and after the piece of code you wish to test, and populate those variables with the value returned by
performance.now()
. Subtracting the first variable from the second variable will then give you the amount of time that your code took to execute.The code below shows a simple example of how to do this. I am calling a server-side controller action from a client-side controller of a Lightning component. Before adding the server-side controller action to the queue of actions to be executed, I have declared
startTime
variable, populating with the value returned by performance.now()
. After the server-side action is completed, I am checking the amount of time the code took to execute.callServer: function (component, method, params, helper, callback) {
var action = component.get(method);
if (params) {
action.setParams(params);
}
action.setCallback(this, function (response) {
console.log('Time taken:', (performance.now() - startTime));
var state = response.getState();
if (state === "SUCCESS") {
callback.call(this, response.getReturnValue());
} else if (state === "ERROR") {
console.log(response.getError());
}
});
var startTime = performance.now();
$A.enqueueAction(action);
}
Sunday, April 8, 2018
Salesforce Lightning: Fetch data from an external API using Ajax
We will be using a very simple API which takes a GET request formatted as a certain URL, returning some random Chuck Norris jokes...lol, without requiring Apex code. So user will enter a number, and on click of Search button, will make a request to http://api.icndb.com/jokes/random/ API, get the response, parse it and display it on the page.
<aura:application extends="force:slds">
<aura:attribute name="number" type="Integer" default="5"/>
<aura:attribute name="html" type="String"/>
<div class="slds-p-left_large">
<h2 class="slds-text-heading_large">Chuck Norris Jokes Generator</h2>
<lightning:input type="number"
aura:id="number"
label="Enter a number"
class="slds-m-around_small slds-size_1-of-8"/>
<lightning:button variant="brand"
label="Get Jokes"
class="slds-m-around_medium"
onclick="{!c.handleClick }"/>
<aura:unescapedHtml value="{!v.html}"/>
</div>
</aura:application>
({
handleClick : function(component, event, helper) {
const number = component.find('number').get('v.value');
if (number) {
component.set('v.number', number);
helper.handleAjaxRequest(component, event, helper);
}
}
})
({
handleAjaxRequest : function(component, event, helper) {
const xhr = new XMLHttpRequest();
const number = component.get('v.number');
const url = 'http://api.icndb.com/jokes/random/' + number;
xhr.open('GET', url, true);
xhr.onload = function() {
if(this.status === 200) {
const response = JSON.parse(this.responseText);
let output = '<ul class=\'slds-list--dotted\'>';
if(response.type === 'success') {
response.value.forEach(function(joke){
output += `<li>${joke.joke}</li>`;
});
}
output += '<ul>';
component.set('v.html', output);
}
};
xhr.send();
}
})
The XHR object has properties and methods associated with it, one of which is
open
, where we specify type of request we want to make and the URL we want to make it to. The 3rd parameter is set as true
as we want to make it asynchronous. The rest of the code is self-explainable.As a last step, we need to add http://api.icndb.com as a trusted site or else our Lightning component will not be able to make a request and you will notice an error message in console something like this: Refused to connect to 'https://api.icndb.com/jokes/random/6' because it violates the following Content Security Policy directive:....."
So navigate to Setup → CSP Trusted Sites, and add the following entry.
That's it. Enjoy the jokes.
Now authentication is required for a lot of external APIs which are intricate ones using OAuth, and that can get complicated. So just remember that not all APIs give you as much freedom as they do here. You normally have to register your application with their systems and then you will have to authenticate. Different rules, different APIs.
Wednesday, March 28, 2018
Customize lightning:combobox (picklist) component using only CSS
The code below will create a dropdown list of selectable options. This code is taken from the Lightning documentation:
https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/aura_compref_lightning_combobox.htm
This is how it looks:
To hide the text label (Status), override this css class
As per the current implementation, this component doesn't support selection of multiple options. So there is no need of displaying the check-icon besides the option values. To hide this icon, override this css class
Now when the dropdown list is visible, we notice that the arrow icon is still pointing downwards. Let's manipulate this icon so that it points upwards in this scenario. For this, add a
This is how it looks now:
Now let's change the background color of selectable options on hover.
This is how it looks now:
Notice the blue border glow around the read-only inputbox. You can change this color to cyan like below:
This is how the lightning:combobox looks now, quite a simple one:
Finally, this is how the CSS style resource looks like:
https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/aura_compref_lightning_combobox.htm
<aura:application extends="force:slds">
<aura:attribute name="statusOptions" type="List" default="[]"/>
<aura:handler name="init" value="{! this }" action="{! c.loadOptions }"/>
<div class="slds-size--1-of-4 slds-p-around--large">
<lightning:combobox aura:id="selectItem" name="status" label="Status"
placeholder="Choose Status"
value="new"
onchange="{!c.handleOptionSelected}"
options="{!v.statusOptions}"/>
</div>
</aura:application>
({
loadOptions: function (component, event, helper) {
var options = [
{value: "new", label: "New"},
{value: "in-progress", label: "In Progress"},
{value: "finished", label: "Finished"}
];
component.set("v.statusOptions", options);
},
handleOptionSelected: function (component, event) {
var selectedOptionValue = event.getParam("value");
console.log(selectedOptionValue);
}
})
This is how it looks:
To hide the text label (Status), override this css class
slds-form-element__label
, and set display
property as none. You can also set the variant
attribute of this component as label-hidden
.As per the current implementation, this component doesn't support selection of multiple options. So there is no need of displaying the check-icon besides the option values. To hide this icon, override this css class
slds-listbox__icon-selected
and set display
property as none. This is how the picklist looks now:Now when the dropdown list is visible, we notice that the arrow icon is still pointing downwards. Let's manipulate this icon so that it points upwards in this scenario. For this, add a
transform
property to this element and rotate 180 degrees, like below:.THIS .slds-dropdown-trigger.slds-is-open .slds-combobox__form-element .slds-icon {
transform: rotate(180deg);
}
This is how it looks now:
Now let's change the background color of selectable options on hover.
.THIS .slds-dropdown-trigger.slds-is-open .slds-listbox__option.slds-has-focus {
background-color: cyan;
}
This is how it looks now:
Notice the blue border glow around the read-only inputbox. You can change this color to cyan like below:
.THIS .slds-input:focus, .THIS .slds-input:active {
border-color: cyan;
box-shadow: 0 0 3px cyan;
}
This is how the lightning:combobox looks now, quite a simple one:
Finally, this is how the CSS style resource looks like:
.THIS .slds-form-element__label, .THIS .slds-listbox__icon-selected {
display: none;
}
.THIS .slds-dropdown-trigger.slds-is-open .slds-combobox__form-element .slds-icon {
transform: rotate(180deg);
}
.THIS .slds-dropdown-trigger.slds-is-open .slds-listbox__option.slds-has-focus {
background-color: cyan;
}
.THIS .slds-input:focus, .THIS .slds-input:active {
border-color: cyan;
box-shadow: 0 0 3px cyan;
}
Subscribe to:
Posts (Atom)