Apex Class Explorer using Custom LWC

apexClassExplorer.html

<template>
    <lightning-card title="Apex Class Search" icon-name="custom:custom57">
        <div class="slds-var-m-around_medium">
            <lightning-input type="search" onchange={handleKeyChange}
                class="slds-show slds-is-relative slds-var-m-bottom_small" label="Search">
            </lightning-input>
            <template if:true={apexClasses}>
                <template for:each={apexClasses} for:item="apex">
                    <lightning-card key={apex.Id}>
                        <h3 slot="title">
                            <lightning-icon icon-name="doctype:xml" alternative-text="XML file" title="XML">
                            </lightning-icon>
                            {apex.Name}
                        </h3>
                        <lightning-button label="Edit" onclick={handleEdit} slot="actions" data-url={apex.Id}>
                        </lightning-button>
                        <lightning-button label="View" onclick={handleView} data-id={apex.Id} slot="actions">
                        </lightning-button>
                        <lightning-button if:true={apex.showCode} label="Hide" onclick={handleHide} data-id={apex.Id}
                            slot="actions">
                        </lightning-button>
                        <div class="slds-scrollable">
                            <div class="slds-text-longform">
                                <div class="slds-page-header__row slds-page-header__row_gutters">
                                    <div class="slds-page-header__col-details">
                                        <ul class="slds-page-header__detail-row" style="list-style: none;">
                                            <li class="slds-page-header__detail-block">
                                                <div class="slds-text-title slds-truncate" title="Api Version">Api
                                                    Version
                                                </div>
                                                <div class="slds-truncate" title={apex.ApiVersion}>{apex.ApiVersion}
                                                </div>
                                            </li>
                                            <li class="slds-page-header__detail-block">
                                                <div class="slds-text-title slds-truncate" title="Status">Status</div>
                                                <div class="slds-truncate" title={apex.Status}>{apex.Status}</div>
                                            </li>
                                            <li class="slds-page-header__detail-block">
                                                <div class="slds-text-title slds-truncate" title="Namespace Prefix">
                                                    Namespace Prefix
                                                </div>
                                                <div class="slds-truncate" title={apex.NamespacePrefix}>
                                                    {apex.NamespacePrefix}
                                                </div>
                                            </li>
                                            <li class="slds-page-header__detail-block">
                                                <div class="slds-text-title slds-truncate" title="IsValid">Created Date
                                                </div>
                                                <div class="slds-truncate" title={apex.IsValid}>{apex.CreatedDate}</div>
                                            </li>
                                            <li class="slds-page-header__detail-block">
                                                <div class="slds-text-title slds-truncate" title="IsValid">Created By
                                                    Name
                                                </div>
                                                <div class="slds-truncate" title={apex.IsValid}>{apex.CreatedBy.Name}
                                                </div>
                                            </li>
                                            <li class="slds-page-header__detail-block">
                                                <div class="slds-text-title slds-truncate" title="IsValid">Last Modified
                                                    Date
                                                </div>
                                                <div class="slds-truncate" title={apex.IsValid}>{apex.LastModifiedDate}
                                                </div>
                                            </li>
                                            <li class="slds-page-header__detail-block">
                                                <div class="slds-text-title slds-truncate" title="IsValid">Last Modified
                                                    By Name
                                                </div>
                                                <div class="slds-truncate" title={apex.IsValid}>
                                                    {apex.LastModifiedBy.Name}
                                                </div>
                                            </li>
                                        </ul>
                                    </div>
                                </div>
                                <blockquote if:true={apex.showCode}>
                                    <pre>
                                        <code class="language-html">
                                            {apex.Body}
                                        </code>
                                    </pre>
                                </blockquote>
                            </div>
                        </div>
                    </lightning-card>
                </template>
            </template>
        </div>
    </lightning-card>
</template>

apexClassExplorer.js

import { LightningElement, track } from 'lwc';
import fetchApexClass from '@salesforce/apex/apexClassExplorerController.fetchApexClass';
/** The delay used when debouncing event handlers before invoking Apex. */
const DELAY = 350;
export default class ApexClassExplorer extends LightningElement {
    @track apexClasses;
    error;

    handleKeyChange(event) {
        // Debouncing this method: Do not actually invoke the Apex call as long as this function is
        // being called within a delay of DELAY. This is to avoid a very large number of Apex method calls.
        window.clearTimeout(this.delayTimeout);
        const searchKey = event.target.value;
        // eslint-disable-next-line @lwc/lwc/no-async-operation
        this.delayTimeout = setTimeout(() => {
            fetchApexClass({ searchKey: searchKey })
                .then((result) => {
                    result.forEach(element => {
                        element.showCode = false;
                    });
                    this.apexClasses = result;
                    this.error = undefined;
                })
                .catch((error) => {
                    this.error = error;
                    this.apexClasses = undefined;
                });
        }, DELAY);
    }

    handleView(event) {
        const dataid = event.target.dataset.id;
        this.apexClasses = this.apexClasses.map(x => {
            if (x.Id == dataid) {
                x.showCode = true;
            }
            return x;
        });
    }

    handleHide(event) {
        const dataid = event.target.dataset.id;
        this.apexClasses = this.apexClasses.map(x => {
            if (x.Id == dataid) {
                x.showCode = false;
            }
            return x;
        });
    }

    handleEdit(event) {
        const url = window.location.origin + '/' + event.target.dataset.url;
        window.open(url);
    }
}

apexClassExplorerController

public with sharing class apexClassExplorerController {
    @AuraEnabled
    public static List<ApexClass> fetchApexClass(String searchKey){
        String key = '%' + searchKey + '%';
        try {
            return [SELECT Id, NamespacePrefix, Name, ApiVersion, Status, IsValid, BodyCrc, Body, LengthWithoutComments, CreatedDate, CreatedBy.Name, LastModifiedDate, LastModifiedBy.Name, SystemModstamp FROM ApexClass WHERE Name LIKE :key];
        } catch (Exception e) {
            throw new AuraHandledException(e.getMessage());
        }
    }
}

apexClassExplorer.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>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>
Apex Explorer Screenshot

Published by Sandeep Kumar

He is a Salesforce Certified Application Architect having 11+ years of experience in Salesforce.

Leave a Reply