Release - November 22
Search…
⌃K

Using a Package

Learning Objectives

  • What is a package?
  • Install a package from appexchange
  • Install a package from CLI
  • Add a package dependency to the project manifest
Time to complete: 40 minutes

Steps

Install the star rating component from AppExchange to playground 1

  • Open Playground 1
  • Install a Managed package from appexchange using this url <YourPlayGroundDomain>/packagingSetupUI/ipLanding.app?apvId=04t5I000001ecttQAA
  • Install a Managed package from appexchange using this url <YourPlayGroundDomain>/packagingSetupUI/ipLanding.app?apvId=04t6F000001D6LOQA0
  • Install a Unlocked package using this installation url <YourPlayGroundDomain>/packagingSetupUI/ipLanding.app?apvId=04t6F000001ZL7yQAG

Create a rating Field in the property object

  • Go to Setup --> Object Manager --> Search Property in Object finder--> Fields & Relationships --> New --> with below details
  • add the field below features field in the property layout
  • add the field permission to the dreamhouse permission set
    Field
    Value
    Field type
    Number
    Label
    Rating
    Length
    1
    Decimal
    1
    Default Value
    0
Retrieve the newly created field into the source from the org
Use the sfdx force:source:retrieve command to retrieve the newly created field

Add the star rating component from another package to the property tile component

Replace PropertyController.cls and propertyTile.html from your project with below snippet
PropertyController.cls
public with sharing class PropertyController {
@AuraEnabled(cacheable=true)
public static Property__c[] getPropertyList( String searchKey, Decimal maxPrice, Integer minBedrooms, Integer minBathrooms ) {
String key = '%' + searchKey + '%';
return [
SELECT Id, address__c, city__c, state__c, description__c, price__c, baths__c, beds__c, thumbnail__c, location__latitude__s, location__longitude__s, Rating__c, Features__c
FROM property__c
WHERE (city__c LIKE :key OR tags__c LIKE :key) AND price__c <= :maxPrice AND beds__c >= :minBedrooms AND baths__c >= :minBathrooms
// WITH SECURITY_ENFORCED
ORDER BY price__c
LIMIT 100
];
}
​
@AuraEnabled(cacheable=true)
public static PagedResult getPagedPropertyList( String searchKey, Decimal maxPrice, Integer minBedrooms, Integer minBathrooms, Integer pageSize, Integer pageNumber ) {
maxPrice = Decimal.valueOf(maxPrice + '');
minBedrooms = Integer.valueOf(minBedrooms + '');
minBathrooms = Integer.valueOf(minBathrooms + '');
pageSize = Integer.valueOf(pageSize + '');
pageNumber = Integer.valueOf(pageNumber + '');
​
Integer pSize = (Integer) pageSize;
String key = '%' + searchKey + '%';
Integer offset = ((Integer) pageNumber - 1) * pSize;
PagedResult result = new PagedResult();
result.pageSize = pSize;
result.pageNumber = (Integer) pageNumber;
result.totalItemCount = [
SELECT COUNT()
FROM property__c
WHERE (city__c LIKE :key OR tags__c LIKE :key) AND price__c <= :maxPrice AND beds__c >= :minBedrooms AND baths__c >= :minBathrooms
];
result.records = [ SELECT Id, address__c, city__c, state__c, description__c, price__c, baths__c, beds__c, thumbnail__c, Rating__c,Features__c
FROM property__c
WHERE (city__c LIKE :key OR tags__c LIKE :key) AND price__c <= :maxPrice AND beds__c >= :minBedrooms AND baths__c >= :minBathrooms
// WITH SECURITY_ENFORCED
ORDER BY price__c
LIMIT :pSize
OFFSET :offset
];
return result;
}
​
@AuraEnabled(cacheable=true)
public static List<ContentVersion> getPictures(Id propertyId) {
List<ContentDocumentLink> links = [
SELECT Id, LinkedEntityId, ContentDocumentId
FROM ContentDocumentLink
WHERE
LinkedEntityId = :propertyId
AND ContentDocument.FileType IN ('PNG', 'JPG', 'GIF')
// WITH SECURITY_ENFORCED
];
​
if (links.isEmpty()) {
return null;
}
​
Set<Id> contentIds = new Set<Id>();
​
for (ContentDocumentLink link : links) {
contentIds.add(link.ContentDocumentId);
}
​
return [
SELECT Id
FROM ContentVersion
WHERE ContentDocumentId IN :contentIds AND IsLatest = TRUE
// WITH SECURITY_ENFORCED
ORDER BY CreatedDate
];
}
}
propertyTile.html
<template>
<a onclick={handlePropertySelected}>
<div class="tile" style={backgroundImageStyle}>
<div class="lower-third">
<h1 class="truncate">{property.City__c}</h1>
<p>Beds: {property.Beds__c} - Baths: {property.Baths__c}</p>
<p>
<lightning-formatted-number
format-style="currency"
currency-code="USD"
value={property.Price__c}
></lightning-formatted-number>
</p>
<c-star-ratings static-color="green" rating={property.Rating__c} read-only show-half-stars="true" size="small"></c-star-ratings>
</div>
</div>
</a>
</template>

Deploy modified files to playground 1

Use sfdx force:source:deploy command to deploy the above modified files

Add package dependency to the sfdx-project.json file

{
"packageDirectories": [
{
"path": "dreamhouse-app",
"default": true,
"dependencies": [
{
"package": "dxatscale-base"
},
{
"package": "LWCC"
},
{
"package": "flowmagic"
}
]
}
],
"namespace": "",
"sourceApiVersion": "52.0",
"packageAliases": {
"dxatscale-base":"04t6F000001ZL7yQAG",
"LWCC":"04t5I000001ecttQAA",
"flowmagic": "04t6F000001D6LOQA0"
}
}

Install 2 packages to playground 2 using CLI command sfdx force:package:install​

sfdx force:package:install -p 04t6F000001ZL7yQAG -w 30 --apexcompile package --securitytype AdminsOnly --noprompt -u playground-2
​
sfdx force:package:install -p 04t5I000001ecttQAA -w 30 --apexcompile package --securitytype AdminsOnly --noprompt -u playground-2
​
sfdx force:package:install -p 04t6F000001D6LOQA0 -w 30 --apexcompile package --securitytype AdminsOnly --noprompt -u playground-2

Deploy all changes to playground 2 using sfdx force:source:deploy command

Use the sfdx force:source:deploy command to deploy all changes to playground 2. Once the metadata is successfully committed, commit your changes to the repo.

Recap

Packages deliver functionality with a defined lifecycle. Salesforce has many forms of packaging, what we are focused is on 2GP or Second-Generation Packaging, which can be used for ISV as a managed package or for others using unlocked packages.
By completing the challenge, you have understood, how to utilise a managed package from AppExchange for your development and deploying metadata/code that depends on these components