Search In This Blog

2025-07-14

Show LWC in smartphone.

 <targetConfig targets="lightning__RecordPage">

<property name="recordpage_display" type="Boolean" default="true"></property>

<supportedFormFactors>

<supportedFormFactor type="Large"/>

<supportedFormFactor type="Small" />

</supportedFormFactors>

</targetConfig>


Set lwc xml target

pc: large

pad: medium

phone: small

2025-01-07

Salesforce: Get all data categories apiName & Label

 Here is the sample code:


List<DescribeDataCategoryGroupResult> describeCategoryResult;

List<DescribeDataCategoryGroupStructureResult> describeCategoryStructureResult;

 

List<String> objType = new List<String>();

objType.add('KnowledgeArticleVersion');

describeCategoryResult = Schema.describeDataCategoryGroups(objType);

 

List<DataCategoryGroupSobjectTypePair> pairs = new List<DataCategoryGroupSobjectTypePair>();

 

for(DescribeDataCategoryGroupResult singleResult : describeCategoryResult){

    DataCategoryGroupSobjectTypePair p = new DataCategoryGroupSobjectTypePair();

    p.setSobject(singleResult.getSobject());

    p.setDataCategoryGroupName(singleResult.getName());

    pairs.add(p);

}

describeCategoryStructureResult = Schema.describeDataCategoryGroupStructures(pairs, false);

 

for(DescribeDataCategoryGroupStructureResult singleResult : describeCategoryStructureResult){

    System.debug(singleResult.getLabel());

    DataCategory [] toplevelCategories = singleResult.getTopCategories();

 

    DataCategory [] categoriesClone = toplevelCategories.clone();

    for(DataCategory category : categoriesClone){

        System.debug('top:' + category.getName());

        System.debug(category.getLabel());

 

        DataCategory[] childCategories = category.getChildCategories();

        for(DataCategory childCategory : childCategories){

            System.debug('childCategory:' + childCategory.getName());

            System.debug(childCategory.getLabel());

        }

    }

}

2024-07-30

How to use Einstein Generative AI in Todo(Task) object

In the Prompt Builder, it is not possible to select a ToDo object and create a prompt template using its fields. However, you can achieve similar functionality by utilizing a related object. Follow these steps:

  1. Create a Related Object: Create a related object to the ToDo object.

  2. Add a Field for Processing: Add a specific field on the related object for processing purposes.

  3. Generate a Common Record: Create a record for all ToDo records.

  4. Develop a Prompt Template: Design a prompt template on the field of the related object.

  5. Implement a Trigger Flow: Set up a trigger flow on the ToDo object. Step 1: retrieve the related object record by ToDo related record ID. Step 2: Assign the target field value of ToDo record to this related object record. Step 3: Update it within the flow. Step 4: Pass the related object record to the prompt template action, now it is able to obtain the prompt output for further updates or other actions.



2024-07-10

Salesforce Integration User License can not access account, etc by dataloader

Issue

Using the Salesforce Integration profile cannot find account, etc in object list.

Solution

Use Permission Set to allow acess to account, etc
When create Permission Set, select lisence as Salesforce API Integration. Don't select Salesforce Integration.
In Object Settings page, allow target objects permission.
If you want access to task, set the permission in System Permissions page. Check on "Access Activities" and "Edit Tasks".

2024-07-08

Some Considerations before you release Restriction Rules by Change Set

Restriction rules allow certain users to access only specified records. Restriction Rules are not actived as default, so you need to create a case to ask Salesforce to active Restriction Rules for your organization.

Restriction Rules can be release by change set, before that you need to make sure if Restriction Rules are actived in the target organization.

2024-05-07

Salesforce認定 AIアソシエイト合格体験記

Salesforce認定AIアソシエイト試験の合格体験記です。
〇試験について
難易度は低いです。誰も受験できます。
内容:多肢選択/複数選択方式の 40 問
試験時間:70 分
合格点:65 %(26 問以上で合格)
受験料:10,000 円(税抜)
再受験:無料試験

〇問題範囲について
AI の基本事項: 全問中 17%
CRM での AI 機能: 全問中 8%
AI の倫理的な考慮事項: 全問中 39%
AI 用のデータ: 全問中 36%

〇学習方法について
筆者は公式のTrailmixで勉強しました。一発合格です。
https://trailhead.salesforce.com/ja/users/strailhead/trailmixes/prepare-for-your-salesforce-ai-associate-credential
※Trailmix中のモジュールにある練習問題は実際試験中に出ました。
Trailmixの内容を理解できていれば、合格できると思います。元々AI知識を持っている人なら、「CRM での AI 機能」をメインに勉強すれば、簡単に合格できるかもしれません。

2024-04-24

Jest issue: Fix TypeError getAccountInfo(...).then is not a function (test apex class inside @wire method)

To mock an Apex class
import getAccountInfo from "@salesforce/apex/CustomCtrl.getAccountInfo"

@wire(getRecord,[...])
wireRecord() {
    getAccountInfo(accountId).then(do somethings)
}

Create the jest mock.
jest.mock(
    "@salesforce/apex/CustomCtrl.getAccountInfo",
    () => { return { default: jest.fn(), } }, { virtual: true }
)
 
But mocked apex is called inside of @wire method, then getAccountInfo(...).then is not a function error is happened. Need to fix the mock as below:
jest.mock(
    "@salesforce/apex/CustomCtrl.getAccountInfo",
    () => {
        return {
            default: jest.fn((data) => {
                let mockData;
                if (data.accountId == "0000000000") {
                    mockData = [{
                    "Id": "0011700000xxxxx000",
                    "Name": "test"
                    }];
                } else if (data.accountId == "0000000001") {
                    mockData = [{
                    "Id": "0011700000xxxxx001",
                    "Name": "test1"
                    }];
                }
                // use Promise to mock getAccountInfo(...).then
                return Promise.resolve(mockData);
            }),
        };
    }, { virtual: true }
);


2023-12-27

SingleEmailMessage

When setOrgWideEmailAddressId is not set, sender will be excutor.

2023-08-08

Not Admin User, How to delete/insert FinServ__FinancialAccount by Apex

Apex should be "without sharing".

Remove sObject.SObjectType.getDescribe().isDeletable() or sObject.SObjectType.getDescribe().isUpdateable() or sObject.SObjectType.getDescribe().isCreateable()

Inactive record in FinServ__RollupByLookupConfig__c, if need.


To Delete

Before delete, update "OwnerId" to current user. Like: FinServ__FinancialAccount.OwnerId = UserInfo.getUserId(). Then user can delete FinServ__FinancialAccount record.


To insert

If you want the special user can edit this FinServ__FinancialAccount record, don't forget to update "OwnerId" to the special user's id after insert.

2022-12-23

Catch System.LimitException in LWC

System.LimitException cannot catch by [try...catch...] in Apex.

When call Apex method in lwc and LimitException occurred in Apex source, [try...catch...] also not working in js.

But LimitException can be catched by [Promise.catch]

Sample
Promise.all([
    promise1,
    promise2,
    promise3
]).then((values) => {
    console.log(values);
}).catch((error) => {
    // LimitException can be catched here
    console.error(error);
}).finally(() => {
    console.log('Experiment completed');
});

2022-11-30

Custom auto open utility bar without popout button by aura

cmp
<aura:compomemt implements="lightning:utilityItem">
    <!-- define popout to false -->
    <aura:attribute name="supportsPopOut" type="Boolean" default="false" />

    <!-- auto open utility bar when init -->
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

    <!-- use lightning:utilityBarAPI -->
    <lightning:utilityBarAPI aura:id="utilitybar" />

    someting else
</aura:compomemt>

controller.js
doInit: function(component) {
    var utilityApi = component.find("utilitybar");
    utilityApi.getAllUtilityInfo().then(fuction (response) {
        if (typeof response != "undefined") {
            utilityApi.openUtility();
        }
    });
}

Get recordId in LWC

Way 1
In js-meta.xml, set targets page
<isExposed>true<isExposed>
<targets>
    <target>lightning__RecordPage<target/>
</targets>

Then use @api to get recordId
import { LightningElement, api } from 'lwc';
export default class Sample extends LightningElement {
    @api recordId;
}

Way 2
Use CurrentPageReference
import { LightningElement, wire } from 'lwc';
import { CurrentPageReference } from 'lightning/navigation';
export default class Sample extends LightningElement {
    currentPageReference;

    @wire(CurrentPageReference)
    setCurrentPageReference(currentPageReference) {
        this.currentPageReference = currentPageReference;
        console.log('recordId: ' + this.currentPageReference.attributes.recordId);
    }
}

2022-11-29

Delete by record id use Schema SObjectType

public without sharing class CustomDeleteCmpController {

    @AuraEnabled(cacheable=true)

    public static String init(Id recordId) {

        // object name

        return recordId.getSobjectType().getDescribe().getLabel();

   }

 

    @AuraEnabled

    public static String doDelete(Id recordId) {

        try {

            String objApiName;

            RecordDelete.deleteLists(new List<SObject>{recordId.getSobjectType().newSObject(recordId)});

            if (String.isNotBlank(recordId)) {

                objApiName = String.valueOf(recordId.getSObjectType());

            }

            return objApiName;

        } catch (Exception ex) {

            throw ex;

        }

    }

}

Use 3rd Party Resource in LWC

import { loadStyle, loadScript } from 'lightning/platformResourceLoader';
// static resource
import myResourceName from '@salesforce/resourceUrl/myResourceName';


initianlized = false;
Use in renderedCallback() {
    if (this.initianlized) {
        return;
    }
    this.initianlized = true;
    Promise.all([
        loadStyle(this, myResourceName + '/css/myResourceName.css'),
        loadScript(this, myResourceName + '/js/myResourceName.js'),
    ]).then(() => {
        // do some thing
    });
}
myResourceName zip
/js/myResourceName.js
/css/myResourceName.css

2022-11-01

ReGet data without reload page

Reget data and raletive list data, but not reload page or redirect url.


In AURA

$A.get('e.force:refreshView').fire();


In LWC

import { getRecordNotifyChange } from 'lightning/uiRecordApi';

getRecordNotifyChange([{recordId: this.recordId1},{recordId: this.recordId2}]);

or

setTimeout(() => {
    eval("$A.get('e.force:refreshView').fire();");
},1000)

オブジェクト項目レベルセキュリティの一括管理

ツールなど経由して作成した項目はよく項目レベルセキュリティー権限をセットしていないです。

個別で項目レベルセキュリティーを設定するのは時間かかります。

一括管理の方法

1権限セット

2プロファイル:設定>プロファイル>項目レベルセキュリティ


2022-09-07

LWC: refresh record detail page

import { LightningElement, api } from 'lwc';

import { getRecordNotifyChange } from 'lightning/uiRecordApi';

 

export default class PageCmp extends LightningElement {

    @api recordId;

 

    doChanged() {

        // Refresh Detail Page

        getRecordNotifyChange([{recordId: this.recordId}]);

    }

}

DOMException: Failed to execute 'querySelectorAll' on 'Element': '#1' is not a valid selector.

<div id="1">HELLO</div>

When id is number likes: 1,

CSS.escape(1)

 

document.querySelector("#\\31");

 

2022-08-29

The selected number not displayed in the "lightning-combobox"?

The value of your options is a number, while event.detail.value holds a string.

After selecting an option, this. currentValue will hold a wrong value, i.e. '2022' instead of 2022.

convert to number: 
handleChange (event) {
    this.currentValue = +event.detail.value;
}

2022-07-02

Get browser type in Lightning Aura/LWC

In Aura

if ($A.get("$Browser.formFactor") != 'DESKTOP') {

    // do something for mobile only here

}


In LWC

import formFactorPropertyName from '@salesforce/client/formFactor'

if (formFactorPropertyName == "Large") {

    // Large—A desktop client.

    // Medium—A tablet client.

    // Small—A phone client.

}