0

I'm attempting to make an LWC that lets an Experience Cloud user edit their own contact information, in theory on the same page as other, similar LWCs that let the user manage related records all in one spot.

I've implemented similar functionality with Flows by setting an input variable and passing {!$User.ContactId} to said input variable in Experience Cloud.

The code is pretty minimal, uses default LDS record form:

HTML:

<template>
    <lightning-record-form
    object-api-name={objectApiName}
    record-id={contactId}
    layout-type={layoutType}>

    </lightning-record-form>
</template>

JS

import { LightningElement, api } from 'lwc';

import CONTACT_OBJECT from '@salesforce/schema/Contact';

export default class EditContactExternalForm extends LightningElement {
    // Expose recordId to get info from parent
    @api contactId;

    objectApiName = CONTACT_OBJECT;
    layoutType = 'Full';

}

XML

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightningCommunity__Page</target>
        <target>lightningCommunity__Default</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightningCommunity__Default">
            <property name="contactId" type="String" required="true"/>
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>

As expected since I'm setting required to true on the contactId property, the component fails with an error message if I leave the input field blank, but the unexpected behavior is that it displays the form fine when I pass it {!$User.ContactId}, but does not populate any data.

It may not be the most elegant solution, but I've added in a text tag that display {contactId} and can confirm that its value seems to be null. When I provide a default value, the value still shows null, even if I un-require the property and remove the parameter from the Experience instance to ensure it isn't being overwritten.

How can I actually pass this id through?

EDIT: Variables with the @api decorator and a valid entry in the XML document can be exposed for input in Exp. Cloud, I thought in the same way as checking "Available for input" on a Flow variable would.

An example flow component with input variable populated with {!$User.ContactId}: Drag and Drop Flow Component with Active_Contact custom input I'm trying to do the same thing with an LWC. the automatic recordId binding won't work in this case because I want to put this flow on a standard page with flows pulling from multiple records and objects:

Drag and Drop LWC with ContactId custom input

Edit2: @nbrown's linked resource below lead me back to the doc page I based my current config on: https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.use_config_for_community_builder

3
  • 2
    It's not clear to me how you are passing in this value. You're passing in a string "{!$User.ContactId}" to the contactId property after you drag and drop the component onto a page in experience builder? As far as I know, the only dynamic value you can anticipate to be available on an experience builder record page is {!recordId}. I think you will need to rely on using getRecord to grab the ContactId for a logged in user or use a record page and navigate a user to their Contact.
    – nbrown
    Nov 5, 2021 at 18:09
  • @nbrown {!recordId} seems to be a special, context-aware input. Using it in place of ContactId has the expected result of throwing an error because this LWC does not necessarily live on a Record Detail Page. However, you can use the \@api decorator and <input> tag to expose arbitrary inputs to Experience builder, and I expected that I could manually pass variables Exp Builder is aware of, like {!$User.ContactId} into the LWC in the same way I can with flows. Post updated with pictures and clarification
    – T. Rivet
    Nov 8, 2021 at 21:03
  • That Flow example you shared is new to me. It could be that, since $User is a global variable available in a Flow context that's why it works in that context - but it would only work in that context. If a record page isn't an option, I would look into leveraging the user's ID in the LWC and work your way to the ContactId (which, unfortunately, isn't available directly with the @salesforce/user module).
    – nbrown
    Nov 8, 2021 at 21:22

1 Answer 1

0

I'm missing some specifics, but I'll give the closest thing to the solution I could find.

On not being able to access default values

If you add a default value to the tag in the metadata file, the behavior is that it prepopulates the input field with that default value. When you edit that property, the component no longer follows the default value. This includes if you edit the field to be blank -- the default value never repopulates unless you delete and recreate the element.

This is not generally useful for retrieving a germane record, but is nice to know, definitely saved me some time copying down Ids testing this LWC.

On not passing in variables

@nbrown's hypothesis that passing $User worked in flows because it's a global variable in the flow context, but not in LWCs because it isn't defined in that context seems to be the case. I could not pass any sort of global variable into the input property, only {!recordId}. If you need data other than recordId, it needs to be resolved outside of the LWC and the Id itself passed into the variable.

Ultimately, my solution was to put the LWC on the User profile page (as it is a User Record Detail Page) to get the User Id from {!recordId}, and within the component use an LDS wire to lookup the ContactId I needed for the form:

JS:

import { LightningElement, api, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';

import CONTACT_OBJECT from '@salesforce/schema/Contact';
import USER_CONTACT_FIELD from '@salesforce/schema/User.ContactId';

export default class EditContactExternalForm extends LightningElement {
    // Expose recordId to get info from parent
    @api recordId;
    @wire(getRecord, { recordId : '$recordId', fields: [USER_CONTACT_FIELD]}) user;

    get contactId() {
        return getFieldValue(this.user.data, USER_CONTACT_FIELD);
    }

    objectApiName = CONTACT_OBJECT;
    layoutType = 'Full';

}

HTML

<template>
    <lightning-record-form
    object-api-name={objectApiName}
    record-id={contactId}
    layout-type={layoutType}>

    </lightning-record-form>
</template>

XML

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightningCommunity__Page</target>
        <target>lightningCommunity__Default</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightningCommunity__Default">
            <property name="recordId" type="String" required="false"/>
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.