Using a Package
- 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
- 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
- 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 setFieldValueField typeNumberLabelRatingLength1Decimal1Default Value0
Retrieve the newly created field into the source from the org
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>
{
"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"
}
}
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
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.
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
Last modified 2mo ago