[SalesForce] LWC “Record Detail Page” for Custom Metadata Type

I'm exploring a concept that involves exposing Custom Metadata Type records to business users in a read-only format in a kind of pseudo-record-detail-page in Lightning Experience. My requirements are:

  1. Use LWC to create "detail pages" for Custom Metadata Type records + an Apex controller to query for them.
  2. Let users open these detail pages in Lightning Experience via URL formula field links on custom object records that pseudo-"look up" to those metadata records via a text field.
  3. The detail pages should open within the Lightning Experience navigation.
  4. The solution should avoid Visualforce wrappers so we don't end up with a fixed-height page. (Also: because Visualforce is so not what we want to be using anymore when building cool Lightning stuff in 2020)

Based on #3, I think I'm forced to use a Lightning Page, i.e. no standalone Aura apps. Of the 3 types of Lightning Page available, I believe the only one that accepts and passes along a URL parameter is Record Page — and it will only pass along a record ID for a standard or custom object — no Custom Metadata identifiers.

I have tried both window.location.search and CurrentPageReference with URL parameters in a Lightning App Page as suggested here — but both of these turn up empty. Based on what I'm seeing, it looks like Lightning Experience is nuking all added URL parameters on these types of pages before it loads the components.

Any solutions I haven't thought of yet?

Best Answer

OK, the main part of the answer turns out to be...

Put your LWC in an Aura component that implements lightning:isUrlAddressable (see ref)

Here's an example with a Custom Metadata Type called Region__mdt. You can access it via the relative URL /lightning/cmp/c__Region?c__apiName=YOUR_IDENTIFIER_HERE:

Region.cmp (Aura)

<aura:component implements="lightning:isUrlAddressable" description="Region: {!v.apiName}" >
    <aura:attribute name="apiName" type="String" />
    <aura:handler name="init" value="{!this}" action="{!c.onPageReferenceChange}"/>
    <aura:handler name="change" value="{!v.pageReference}" action="{!c.onPageReferenceChange}"/>
    <!-- Embed the LWC like this -->
    <c:regionDetail apiName="{!v.apiName}" />
</aura:component>

RegionController.js (Aura)

({
    onPageReferenceChange: function(component) {
        var myPageRef = component.get('v.pageReference');
        component.set('v.apiName', myPageRef.state.c__apiName);
    }
})

regionDetail.html (LWC)

<template>
    <header class="slds-page-header slds-page-header__row slds-page-header__col-title slds-media slds-m-bottom_medium">
        <lightning-icon class="slds-media__figure" icon-name="custom:custom78"></lightning-icon>
        <h1 class="slds-media__body slds-page-header__name slds-page-header__name-title slds-page-header__title">
            {region.Label}
        </h1>
    </header>
    <section class="slds-box slds-theme_default">
        <dl class="slds-list_stacked">
            <dt class="slds-item_label slds-text-color_weak slds-truncate">Region ID</dt>
            <dd class="slds-item_detail slds-truncate slds-m-bottom_small">{apiName}</dd>
            <dt class="slds-item_label slds-text-color_weak slds-truncate">Area Factor</dt>
            <dd class="slds-item_detail slds-truncate slds-m-bottom_small">{region.Area_Factor__c}</dd>
        </dl>
    </section>
</template>

regionDetail.js (LWC)

import { LightningElement, api, track, wire } from 'lwc';
import getRegion from '@salesforce/apex/RegionController.getRegion';

export default class RegionDetail extends LightningElement {
    @api apiName;
    @track region = {};

    @wire(getRegion, { developerName: '$apiName' })
    loadRegion(response) {
        if (response && response.data) {
            this.region = response.data;
        }
    }
}

RegionController.cls (Apex)

public with sharing class RegionController {
    @AuraEnabled(cacheable=true)
    public static Region__mdt getRegion(String developerName) {
        return [SELECT DeveloperName, Label, Area_Factor__c
            FROM Region__mdt WHERE DeveloperName = :developerName];
    }
}
Related Topic