• Rebekah Lilly
  • NEWBIE
  • 20 Points
  • Member since 2020

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 7
    Questions
  • 6
    Replies
Hi, I would like to be able to create an Apex class that uses the Tooling API to see if a User (by ID or Email Address) is a recipient on email alerts or if their ID or Email Address is used in any metadata fields. I have written HTTP Callouts before, but having a bit of trouble figuring out how to access use the Tooling API to access my own org. I can't seem to figure out how to scan all email alerts for the main recipient. I can see the ccemails on the WorkFlowAlert object, but where is the main recipient? 
Hi, I am looking for some suggestions (and possible examples) for a custom path component.

My primary requirements are that the component retain the step wording (not changing to the checkmark after passing a step), be able to edit the colors for each step of the path, and the key fields may have more than 5 fields for a step.

It does not have to be a "path component" since it will be custom, but my client likes the look of the path. However, this path is for projects that often require them to skip a step or complete a future step before a current step. So I would like to be able to customize the colors and leave the words. If they have completed all necessary fields, I want to show the step in green, if there are fields left to be completed, show it in yellow, and if nothing is completed it can be white/gray, etc. I also want to leave the words so they can easily see the step names.

I have looked at both aura component and LWC. I prefer LWC development but it looked like aura components might be easier to adjust the colors on?  The other requirement is that I need to be able to have more than five fields, which in a custom component shouldn't be an issue since I can show/hide the form data myself.

Anyone have any suggestions based on creating custom paths? Or a suggestion on which way to proceed, aura or LWC, and why.

Thanks in advance, 
Rebekah
 
Hello, 
I have a very simple LWC that uses getRecord from 'lightning/uiRecordApi' to retrieve an Account record and two custom fields. It displays a banner message based on the values in the two fields. It does not update the fields, just retrieves the values. The field values, however, are being updated by a separate process that uses a future call for external processing. If I refresh the page, the banner changes or goes away, as it should. I would like it to refresh automatically once the fields are updated, without having to refresh the page manually. I have read about the getRecordNotifyChange, but I am unsure how to use it if the LWC is not making the changes. If I created an Apex class and used it, I know I could do a refreshApex, but again, this LWC is not making any changes, so it would need to do it after a delay to allow time for the external process to finish. Is there a better way to poll for record changes and refresh the LWC when these two values change?

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

import FIELD1 from '@salesforce/schema/Account.Field1__c';
import FIELD2 from '@salesforce/schema/Account.Field2__c';

const fields = [FIELD1, FIELD2];

export default class Status_Display extends LightningElement {

    @api recordId;
    status1;
    status2;
    alert = false;
    invalid = false;
    
   @wire( getRecord, { recordId: '$recordId', fields })
    account({error, data}) {
        if (error) {
            this.alert = false;
            this.invalid = false;
        }
        else if (data) {
            this.status1 = data.fields.Field1__c.value;
            if (this.status1 === 'Alert') {
                this.alert = true;
            }
            
            this.status2 = data.fields.Field2__c.value;
            if (this.status2 === 'Invalid') {
                this.invalid = true;
            }
            
        }
    }

}
 
I have a custom button on a related list to allow the users to select records and then update a field with a single click. I only want the button on the related list, not on list views, and I toyed with various methods of processing the list, but a VisualForce page seems to be the easiest and most efficient and gives me the expected results. The user clicks the button, the VF page displays briefly, the selected records (if any) are updated, and the page redirects back to the record. Everything works as expected. The problem is that when the VisualForce page is shown... it is blank and I would like to show some wording that it is processing or ideally a spinner. I am using an action attribute and I don't want the user to have to click on anything else... I would just like them to know something is happening instead of seeing a blank white page.

Suggestions greatly appreciated.

VF Page:
<apex:page standardController="PPR_Line__c" recordSetVar="listLines" extensions="PPRLine_UpdateController" action="{!updatePPRLines}" > </apex:page>

Apex:
public class PPRLine_UpdateController {
    
    public List<String> pprLinesSet    { get; set; }
    public List<PPR_Line__c> selectedPPRLineRecords    { get; set; }
    public Id pprId { get; set; }
    public String currentRecId { get; set; }
    
    public PPRLine_UpdateController(ApexPages.StandardSetController setController) {
        currentRecId = ApexPages.currentPage().getParameters().get('id');
        selectedPPRLineRecords = (PPR_Line__c[])setController.getSelected();
        pprLinesSet = new List<String>();
        for(sObject sobj : setController.getSelected()) {
            pprLinesSet.add( (String)sObj.get('Id') );
        }
    }
    
    public PageReference updatePPRLines() {
        
        List<PPR_Line__c> pprLines = [SELECT Id, Parts_Received__c 
                                      FROM PPR_Line__c 
                                      WHERE Id IN :pprLinesSet];
        List<PPR_Line__c> pprLinesToUpdate = new List<PPR_Line__c>();
        if (!pprLines.isEmpty()) {
            for(PPR_Line__c line : pprLines) {
                     PPR_Line__c updline = new PPR_Line__c();
                    updline.id = line.id;
                    updline.Parts_Received__c = true;
                    pprLinesToUpdate.add(updline);
            }
            update pprLinesToUpdate;
        
            List<PPR__c> pprUpdate = new List<PPR__c>();
            PPR__c upd = new PPR__c();
            upd.id = currentRecId;
            upd.Refresh__c = true;
            pprUpdate.add(upd);
            update pprUpdate;
        }
        
        // return to page
        PageReference pageRef = new PageReference('/' + currentRecId);
        pageRef.setRedirect(true);
        return pageRef;
        
    }

}
I am struggling to get a spinner to display during a table refresh and an imperative call. When the component is initially displayed, it loads data into a table and the spinner works perfectly:

 connectedCallback() {
        this.showLoading = true;
 }

@wire(fetchShipments, {inputId: '$inputId', inputFromDate: null, inputToDate: null})
wiredFetchShipments({ error, data }) {
        if (data) {
            this.shipments = data;
            this.allshipments = data;            
        } else if (error) {
            this.error = error;
            this.shipments = undefined;
            this.allshipments = undefined;
       }
        this.showLoading = false;
        this.isLoaded = true;
    }

However, if users want to filter the data, I have various search fields and a "Refresh List" button. The Refresh List works perfectly to reload the table, but does not display the spinner. I played around with it and added an await and a delay... is this the only way to get a spinner to show for something like this? If the user changes the dates to be outside of the defaults that were originall fetched from the server, then I must make another call to load new records... the spinner does not display there either. I am trying to work with async and await, but struggling to get it to work. There has to be a better way:

showLoadingDelay() {
        return new Promise(resolve => {
            setTimeout(function() {
                resolve(false)
            }, 4000)
        })
    }

 async handleRefresh( event ) {
        if (( dates selected are outside of the current default date range fetched from server) {
            const newdata = await this.handleDateUpdate(); // fetch new records from server
            this.showLoading = true;  // show spinner 
        } else {
            this.showLoading = true; // show spinner
        }
        this.shipments = this.allshipments;
        let recs = [];
        for (let rec of this.shipments) {
             let pushrec = true;
             //filter records based on user specified criteria
            if ( pushrec === true ) {
                 recs.push( rec );
            }
        }
        this.showLoading = await this.showLoadingDelay(); // trying to make it show spinner
        this.shipments = recs;
    }

async resetDates( event ) {
        fetchShipments({inputId: this.accountId, inputFromDate: null, inputToDate: null})
            .then(result => {
                this.shipments = result;
                this.allshipments = result;
            })
            .catch(error => {
                this.shipments = undefined;
                this.allshipments = undefined;
            })
    }

All the refreshes of the data work perfectly. From watching it in the debugger, it is retreiving the correct records when it should but I cannot get the darn spinner to show during the refresh because it happens so fast. That is why I was attempting the delay method. It retreives new records from the server fairly quickly too... so again I was trying the delay to get the spinner to show.

Any suggestions?
I have a fairly simply program that I am using to retreive some records via Apex and then allow the user to filter them in the JS controller. I also have an Export List button that is currently allowing them to download the list they have filtered as a CSV file. The problem is that leading zeroes do not show up in Excel. This is not an LWC or Salesforce issue, but an issue with how Excel handles the data. I would like to create a real XLSX file. Is there a way to do this natively? Or will I need to use a third-party library? What would be the recommended library to use? xlsx.js?

Thanks,
Rebekah

handleExport() {
        let rowEnd = '\n';
        let csvString = '';
        this.exportHeader.forEach(element => {
            csvString += element + ',';
        });
        csvString += rowEnd;
        this.orders.forEach(record => {
            csvString += Customer__c + ',';
            csvString += '"' + record.ShipToLocationID__c + '",';
            csvString += '"' + record.PONumber__c + '",';
            if (record.POLineNumber__c == undefined) {
                csvString += ' ,';
            } else {
                csvString += record.POLineNumber__c + ',';
            }
            if (record.CustomerItemNumber__c == undefined) {
                csvString += ' ,';
            } else {
               csvString += '"' + record.CustomerItemNumber__c + '",';
            }
            csvString += '"' + record.ItemNumber__c + '",';
            csvString += '"' + record.CONumber__c + '",';
            csvString += '"' + record.ERP_ProductItem__r.ItemDescription__c + '",';
            csvString += record.PromisedDeliveryDate__c + ',';
            csvString += record.COLineNumber__c + ',';
            csvString += record.ItemOrderedQuantity__c + ',';
            csvString += record.OpenQuantity__c + ',';
            csvString += record.UnitPrice__c + ',';
            csvString += record.ExtendedPrice__c + ',';
            csvString += rowEnd;
        });
       
        var element = 'data:text/csv;charset=utf-8,' + encodeURIComponent(csvString);
        let downloadElement = document.createElement('a');
        downloadElement.href = element;
        downloadElement.target = '_self';
        downloadElement.download = 'Sales Order Lines.csv';
        document.body.appendChild(downloadElement);
        downloadElement.click();
    }
I have a very simple lightning:recordEditForm:
<lightning:recordEditForm aura:id="recordEditForm" 
                                       objectApiName="CustomObject__c"
                                       onsubmit="{!c.handleCreate}"
                                       onsuccess="{!c.goToNewRecord}" >
    
             <lightning:inputField fieldName="Name__c" />
             <lightning:inputField fieldName="Description__c" />
             <lightning:inputField fieldName="Type__c" />    
             <lightning:inputField fieldName="Related__c" />
             <lightning:inputField fieldName="Required__c" />
             <lightning:inputField fieldName="Necessary__c" /> 
             <lightning:inputField fieldName="Source__c" />
             <lightning:input aura:id="ProjDueDate" name="ProjDueDate" label="Project Due Date" type="date" dateStyle="short" />
             <lightning:inputField fieldName="Product_Group__c" />
             <lightning:inputField fieldName="Category__c" />
             <lightning:inputField fieldName="PLM_Member__c" />
             <lightning:inputField fieldName="Sourcing_Member__c" />
             <lightning:inputField fieldName="MFG_Member__c" />
             <lightning:inputField fieldName="Quality_Member__c" />
             <lightning:inputField fieldName="Engineering_Member__c" />
             <lightning:inputField fieldName="Sales_Member__c" />
             <lightning:inputField fieldName="Application_Member__c" />
                 
             <lightning:button class="slds-m-top_small" type="submit" label="Create Project" />
             <lightning:button class="slds-m-top_small" variant="neutral" label="Cancel" onclick="{!c.handleCancel}" />   
        
             </lightning:recordEditForm>
        
As you can see, I am using a lightning:input field for the date because the default way lightning:inputField handled my date field was "April 5, 2022" instead of "4/5/2022" and it needed to look consistent with the record page. 

After deploying this into a full sandbox for testing, we are noticing a delay in the display. The lightning:input field is displayed first and for a couple of brief seconds its the only field you see, then the remaining of the lightning:inputField fields show up. 

Is there a way to keep this delay or handle it more efficiently so that all fields are rendered together? 

Or is there a way to control the way the lightning:inputField date is handled to be "mm/dd/yyyy" like the standard record page?

Thanks in advance!
Hi, I would like to be able to create an Apex class that uses the Tooling API to see if a User (by ID or Email Address) is a recipient on email alerts or if their ID or Email Address is used in any metadata fields. I have written HTTP Callouts before, but having a bit of trouble figuring out how to access use the Tooling API to access my own org. I can't seem to figure out how to scan all email alerts for the main recipient. I can see the ccemails on the WorkFlowAlert object, but where is the main recipient? 
I am struggling to get a spinner to display during a table refresh and an imperative call. When the component is initially displayed, it loads data into a table and the spinner works perfectly:

 connectedCallback() {
        this.showLoading = true;
 }

@wire(fetchShipments, {inputId: '$inputId', inputFromDate: null, inputToDate: null})
wiredFetchShipments({ error, data }) {
        if (data) {
            this.shipments = data;
            this.allshipments = data;            
        } else if (error) {
            this.error = error;
            this.shipments = undefined;
            this.allshipments = undefined;
       }
        this.showLoading = false;
        this.isLoaded = true;
    }

However, if users want to filter the data, I have various search fields and a "Refresh List" button. The Refresh List works perfectly to reload the table, but does not display the spinner. I played around with it and added an await and a delay... is this the only way to get a spinner to show for something like this? If the user changes the dates to be outside of the defaults that were originall fetched from the server, then I must make another call to load new records... the spinner does not display there either. I am trying to work with async and await, but struggling to get it to work. There has to be a better way:

showLoadingDelay() {
        return new Promise(resolve => {
            setTimeout(function() {
                resolve(false)
            }, 4000)
        })
    }

 async handleRefresh( event ) {
        if (( dates selected are outside of the current default date range fetched from server) {
            const newdata = await this.handleDateUpdate(); // fetch new records from server
            this.showLoading = true;  // show spinner 
        } else {
            this.showLoading = true; // show spinner
        }
        this.shipments = this.allshipments;
        let recs = [];
        for (let rec of this.shipments) {
             let pushrec = true;
             //filter records based on user specified criteria
            if ( pushrec === true ) {
                 recs.push( rec );
            }
        }
        this.showLoading = await this.showLoadingDelay(); // trying to make it show spinner
        this.shipments = recs;
    }

async resetDates( event ) {
        fetchShipments({inputId: this.accountId, inputFromDate: null, inputToDate: null})
            .then(result => {
                this.shipments = result;
                this.allshipments = result;
            })
            .catch(error => {
                this.shipments = undefined;
                this.allshipments = undefined;
            })
    }

All the refreshes of the data work perfectly. From watching it in the debugger, it is retreiving the correct records when it should but I cannot get the darn spinner to show during the refresh because it happens so fast. That is why I was attempting the delay method. It retreives new records from the server fairly quickly too... so again I was trying the delay to get the spinner to show.

Any suggestions?
I have a fairly simply program that I am using to retreive some records via Apex and then allow the user to filter them in the JS controller. I also have an Export List button that is currently allowing them to download the list they have filtered as a CSV file. The problem is that leading zeroes do not show up in Excel. This is not an LWC or Salesforce issue, but an issue with how Excel handles the data. I would like to create a real XLSX file. Is there a way to do this natively? Or will I need to use a third-party library? What would be the recommended library to use? xlsx.js?

Thanks,
Rebekah

handleExport() {
        let rowEnd = '\n';
        let csvString = '';
        this.exportHeader.forEach(element => {
            csvString += element + ',';
        });
        csvString += rowEnd;
        this.orders.forEach(record => {
            csvString += Customer__c + ',';
            csvString += '"' + record.ShipToLocationID__c + '",';
            csvString += '"' + record.PONumber__c + '",';
            if (record.POLineNumber__c == undefined) {
                csvString += ' ,';
            } else {
                csvString += record.POLineNumber__c + ',';
            }
            if (record.CustomerItemNumber__c == undefined) {
                csvString += ' ,';
            } else {
               csvString += '"' + record.CustomerItemNumber__c + '",';
            }
            csvString += '"' + record.ItemNumber__c + '",';
            csvString += '"' + record.CONumber__c + '",';
            csvString += '"' + record.ERP_ProductItem__r.ItemDescription__c + '",';
            csvString += record.PromisedDeliveryDate__c + ',';
            csvString += record.COLineNumber__c + ',';
            csvString += record.ItemOrderedQuantity__c + ',';
            csvString += record.OpenQuantity__c + ',';
            csvString += record.UnitPrice__c + ',';
            csvString += record.ExtendedPrice__c + ',';
            csvString += rowEnd;
        });
       
        var element = 'data:text/csv;charset=utf-8,' + encodeURIComponent(csvString);
        let downloadElement = document.createElement('a');
        downloadElement.href = element;
        downloadElement.target = '_self';
        downloadElement.download = 'Sales Order Lines.csv';
        document.body.appendChild(downloadElement);
        downloadElement.click();
    }
I have a very simple lightning:recordEditForm:
<lightning:recordEditForm aura:id="recordEditForm" 
                                       objectApiName="CustomObject__c"
                                       onsubmit="{!c.handleCreate}"
                                       onsuccess="{!c.goToNewRecord}" >
    
             <lightning:inputField fieldName="Name__c" />
             <lightning:inputField fieldName="Description__c" />
             <lightning:inputField fieldName="Type__c" />    
             <lightning:inputField fieldName="Related__c" />
             <lightning:inputField fieldName="Required__c" />
             <lightning:inputField fieldName="Necessary__c" /> 
             <lightning:inputField fieldName="Source__c" />
             <lightning:input aura:id="ProjDueDate" name="ProjDueDate" label="Project Due Date" type="date" dateStyle="short" />
             <lightning:inputField fieldName="Product_Group__c" />
             <lightning:inputField fieldName="Category__c" />
             <lightning:inputField fieldName="PLM_Member__c" />
             <lightning:inputField fieldName="Sourcing_Member__c" />
             <lightning:inputField fieldName="MFG_Member__c" />
             <lightning:inputField fieldName="Quality_Member__c" />
             <lightning:inputField fieldName="Engineering_Member__c" />
             <lightning:inputField fieldName="Sales_Member__c" />
             <lightning:inputField fieldName="Application_Member__c" />
                 
             <lightning:button class="slds-m-top_small" type="submit" label="Create Project" />
             <lightning:button class="slds-m-top_small" variant="neutral" label="Cancel" onclick="{!c.handleCancel}" />   
        
             </lightning:recordEditForm>
        
As you can see, I am using a lightning:input field for the date because the default way lightning:inputField handled my date field was "April 5, 2022" instead of "4/5/2022" and it needed to look consistent with the record page. 

After deploying this into a full sandbox for testing, we are noticing a delay in the display. The lightning:input field is displayed first and for a couple of brief seconds its the only field you see, then the remaining of the lightning:inputField fields show up. 

Is there a way to keep this delay or handle it more efficiently so that all fields are rendered together? 

Or is there a way to control the way the lightning:inputField date is handled to be "mm/dd/yyyy" like the standard record page?

Thanks in advance!