• MarkHB
  • NEWBIE
  • 10 Points
  • Member since 2012

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 1
    Likes Given
  • 4
    Questions
  • 0
    Replies
We have a Lightning Case record console that includes the Email Quick Action, and the Quick Action does specify the default To and From addresses, with the To: being either the Contact Email or a custom field that's populated during Email-to-Case processing.  I am finding that, in some cases, for follow-up emails the To: address is getting populated with another value, such as the default From: address. I turned on Lightning Debug and when I open the composer I see this:
 
address set to /email/htmlbody/htmlbody.jsp?id=6599%3A0&layout=CaseLightningEmail&useCkEditorPanels=false&isNarrow=false&customCssClasses=&isQuickTextEnabled=true&isPardotOrg=false&isCmsOnly=false&_CONFIRMATIONTOKEN=...

Does anyone know how that addressee gets chosen?  Thanks for any help!

 
  • April 29, 2021
  • Like
  • 0
Hi,
I am working on a new Visualforce page as part of our Lightning conversion.  As part of that, I've written code to showMessages if we're still on Classic, and showToasts if we're on Lightning.  If the operation succeeds, I would like to show a Success message and then redirect back to the record page, but the redirect happens instead of the rerender (for failure, I return null as the new pageReference so no redirect happens and the messages display properly).  How can I force the VF page to wait for the showToast operation(s) to complete before reloading the record?

VF page:
<apex:page id="Xx_CancelQuote"
           standardController="xx__Quote__c"
           extensions="XxQuoteButtonController"
           title="Cancel Quote"
           lightningStylesheets="{!lightning}">
    <apex:slds />
    <apex:form >
        <apex:actionFunction name="cancelQ" action="{!cancelQuote}" id="cancelFunction" reRender="messageBox" />
        <apex:actionFunction name="return2Q" action="{!returnToRecord}" id="returnFunction" />
    </apex:form>
    <apex:outputPanel id="scriptPanel">
        <script>if (confirm("Cancel quote {!quoteNumber}?"))
                cancelQ();
            else
                return2Q();
        </script>
    </apex:outputPanel>
    <apex:outputPanel id="messageBox">
        <apex:pageMessages showDetail="true"/>
        <script>
            <apex:repeat value="{!toastMessages}" var="dirKey">
            sforce.one.showToast({
                "title":  "{!toastMessages[dirKey].title}",
                "message":  "{!toastMessages[dirKey].message}",
                "type":  "{!toastMessages[dirKey].typeName}",
                "mode":  "{!toastMessages[dirKey].mode}"
            });
            </apex:repeat>
        </script>
    </apex:outputPanel>
    <br/>
    <apex:form>
        <apex:commandButton id="returnBtn" value="Return to Quote" onClick="return2Q(); return false;" />
    </apex:form>
</apex:page>

Controller:
/**
 * 
 * Controller for Convert-Xx_-to-Lightning buttons
 */

public with sharing class Xx_QuoteButtonController {
    ApexPages.StandardController stdCon;

    public class ToastMessage {
        public String typeName {get; set;}
        public String title {get; set;}
        public String message {get; set;}
        public String mode {get; set;}

        ToastMessage(String typeName, String title, String message, String mode) {
            this.typeName = typeName;
            this.title = title;
            this.message = message;
            this.mode = mode;
        }
    }

    public Map<Integer, ToastMessage> toastMessages {get;set;}

    public Boolean lightning;

    public Integer getMessageSize() {
        return this.toastMessages.size();
    }

    public Xx_QuoteButtonController(ApexPages.StandardController controller) {
        stdCon = controller;
        toastMessages = new Map<Integer, ToastMessage>();
    }

    //There is probably a much better way to do this
    public String getQuoteNumber() {
        String quoteNumber = '(Name not available)';
        xx__Quote__c quote = (xx__Quote__c) stdCon.getRecord();
        quote = [SELECT Id, QuoteNumber__c FROM xx__Quote__c WHERE Id = :quote.Id];
        if (quote != null && quote.QuoteNumber__c != null && !(quote.QuoteNumber__c.equals('') || quote.QuoteNumber__c.isWhitespace())) {
            quoteNumber = quote.QuoteNumber__c;
        }
        return quoteNumber;
    }

    public PageReference returnToRecord() {
        return stdCon.view();
    }

    public PageReference cancelQuote() {
        PageReference result;
        Id cancelledRecordTypeId = Schema.SObjectType.xx__Quote__c.getRecordTypeInfosByName().get('Cancelled').getRecordTypeId();
        try {
            xx__Quote__c quote = (xx__Quote__c) stdCon.getRecord();
            if (Test.isRunningTest()) {
                xx__Quote__c quote2 = [SELECT Id, Name FROM xx__Quote__c WHERE Id = :quote.Id];
                if (quote2.Name.equals('BAD')) {
                    Exception e = new NoDataFoundException();
                    e.setMessage('Bad record found!');
                    throw e;
                }
            }
            if (quote != null) {
                quote.xx__Status__c = 'Cancelled';
                quote.RecordTypeId = cancelledRecordTypeId;
            }
            result = stdCon.save();
            addPageMessage(ApexPages.Severity.CONFIRM, 'Success!', 'Record was cancelled');
        } catch (Exception e) {
            String errorName = logError(e, 'Cancel Xx_ Quote');
            addPageMessage(ApexPages.Severity.ERROR, 'Cancellation Failed!', e.getMessage());
            result = null;
        }
        return result;
    }

    public Boolean getLightning() {
        return UserInfo.getUiThemeDisplayed().toLowerCase().startsWith('theme4');
    }

    private void addPageMessage(ApexPages.Severity severity, String message, String detail) {
        if (getLightning()) {
            String severityName;
            String mode = 'sticky';
            switch on severity {
                when CONFIRM {
                    severityName = 'success';
                    mode = 'dismissable';
                }
                when WARNING {
                    severityName = 'warning';
                }
                when ERROR,FATAL {
                    severityName = 'error';
                }
                when INFO {
                    severityName = 'info';
                }
                when else {
                    severityName = 'other'; //should never get here
                }
            }
            toastMessages.put(toastMessages.size(), new ToastMessage(severityName, message, detail, mode));
            System.debug('Adding toast '+toastMessages.size()+': '+severityName+', '+message+', '+detail+', '+mode);
        } else { //classic
            ApexPages.addMessage(new ApexPages.Message(severity, message, detail));
        }
    }

    private static String logError(Exception e, String applicationFunction) {

        //Omitted, writes the exception to a tracking object and returns the Name of the record created.
}
}
Thanks for any advice you can give!
 
  • March 25, 2020
  • Like
  • 0
I have a Lightning Datatable with a URL field whose target value has been a forward slash concatenated with a case object ID (so it resolved to https://mydomain.lightning.force.com/objectId).  Prior to Summer '19, this produced the intended result: the link opened a new tab in the Lightning service console.  As of this week, though, it's opening in a new browser tab instead (so effectively a target="_blank").  I have two questions:
  1. Does anyone know if this change was documented anywhere?
  2. Is there anything I can do with the typeAttributes that will produce the same result that calling workspaceAPI.openTab() does (regardless of focus)?
Current column definition (wrapped for ease of reading) in the Controller:
 
{label: "Case Number",
    fieldName: "Anchor",
    type: "url",
    typeAttributes: {
        label:{
            fieldName: "CaseNumber"
        }
    },
    sortable: true},
Thanks for any help!
Mark

#Summer19
Hi,
I'm trying to create a List Action Visualforce page (Lightning environment) which will not only include two user-set fields, but also push in the user's ID and current timestamp into two additional fields which the user has no control over.  Updating the selected records with the exposed fields (a dropdown and a textbox) works fine, but I have been unable to set the other two fields.  I have tried two different tactics:
  1. Using inputHidden for the two fields (see code below), but I haven't found the magic Javascript incantation to properly set them before the form submits.  In ordinary HTML I would just set the value attribute, but that's bound to the object field and using html-value is not allowed.
  2. Using controller.getRecord() in the controller extension, also as shown below, but that doesn't work, either; I can tell in the logs that updateRecords is called but the fields aren't updated.
Does anyone have a working solution for this?  (Note: I haven't tried both methods at the same time, I just wanted to show them both in the example).

Page:
<apex:page standardController="MyObject__c"
        recordSetVar="adjustments"
        extensions="ExtensionsClass"
        showHeader="false"
        id="MyObject_BulkChange">
    <apex:slds />
    <apex:form id="muform">        
        <apex:pageBlock title="Refunds / Adjustments Mass-Update" mode="edit" id="mub1">
            <apex:pageMessages />
            <apex:pageBlockSection id="mus1">
                <apex:inputField value="{!MyObject__c.Status__c}" id="status">
                    <apex:actionSupport event="onchange" rerender="muselectedlist"/>
                </apex:inputField>
                <apex:inputField value="{!MyObject__c.Comment__c}" id="comment">
                    <apex:actionSupport event="onchange" rerender="muselectedlist"/>
                </apex:inputField>
                <apex:inputHidden value="{!MyObject__c.User_Name__c}" rendered="true" id="userName"/>
                <apex:inputHidden value="{!MyObject__c.Action_Date__c}" rendered="false" id="actionDate"/>
            </apex:pageBlockSection>
            <apex:pageBlockButtons location="bottom" id="mubut">
                <apex:commandButton value="Save" action="{!updateRecords}" id="butsav"/>
                <apex:commandButton value="Cancel" action="{!cancel}" id="butcan"/>
            </apex:pageBlockButtons>
        </apex:pageBlock>
        <apex:pageBlock title="Selected Items" id="muselectedlist">
            <apex:pageBlockTable value="{!selected}" var="ref" id="mutab">
                <apex:column value="{!ref.Account_Number__c}" id="refAcctNbr"/>
                <apex:column value="{!ref.Name}" id="refName"/>
                <apex:column value="{!ref.Status__c}" id="refStatus"/>
                <apex:column value="{!ref.Comment__c}" id="refComment"/>
                <apex:column value="{!ref.User_Name__c}" id="refUserName"/>
                <apex:column value="{!ref.Action_Date__c}" id="refActionDate"/>
            </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Controller:
public with sharing class ExtensionsClass {
    ApexPages.StandardSetController setCon;

    public selectedSizeWorkaround(ApexPages.StandardSetController controller) {
        setCon = controller;
    }

    public integer getMySelectedSize() {
        return setCon.getSelected().size();
    }
    public integer getMyRecordsSize() {
        return setCon.getRecords().size();
    }

    public PageReference updateRecords() {
        ((MyObject__c)(setCon.getRecord())).User_Name__c = UserInfo.getUserId();
        ((MyObject__c)(setCon.getRecord())).Action_Date__c = System.now();
        return setCon.save();
    }
}

Thanks in advance for any help.
I am attempting to use force:navigateToComponent but running into an odd issue. The internet sites that I'm using as reference seams to point me that I'm following the right path but I'm unclear on the error. Its preventing me from saving the page: 

    <aura:component>
    <lightning:button variant="brand" label="Button Text" onclick="{!c.Navigate}" />
    </aura:component>

Controller JS:

    Navigate : function(component, event, helper) {
    var evt = $A.get("e.force:navigateToComponent");
    evt.setParams({
    componentDef : "c:component2",
    });
    evt.fire();
}

Error Reported on Save: Failed to save undefined: markup://aura:component cannot be instantiated directly. Component will not save in developer console. 

Source Materials: 
https://developerprob.blogspot.com/2016/06/navigate-from-one-component-to-another.html

https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/ref_force_navigateToComponent.htm