• louisa barrett 7
  • NEWBIE
  • 205 Points
  • Member since 2016

  • Chatter
    Feed
  • 0
    Best Answers
  • 1
    Likes Received
  • 0
    Likes Given
  • 61
    Questions
  • 68
    Replies
Hi,

We use cases and service contracts and as SF prevent a contact being deleted that is associated to one of these records, when we want to delete a contact that is associated to a case or service contract each of these records needs to be individually updated to remove the contact.
I was hoping to remove the contact from these records on a before delete trigger on the contact. This is failing though as I think the SF code that is checking if the contact belongs to any cases or service contracts is rolling back my updates in my before trigger.
Does anyone know if this is possible thorugh a trigger?
I don't really want to launch a flow to delete the relationships on an individual contact record as I would like to be able to mass delete contacts.
This is the method that is called from the contact trigger on a beforeDelete
private static void removeContactFromRelatedObjects(Map<Id, Contact> oldContactsMap)
    {
        List<Contact> myContacts = new List<Contact>([SELECT ID, (SELECT Id, CaseNumber FROM Cases), (SELECT ID, ContractNumber FROM ServiceContracts) 
                                                            FROM Contact 
                                                            WHERE Id in : oldContactsMap.keyset()]);
        List<ServiceContract> mySCs = new List<ServiceContract>();
        List<Case> myCases = new List<Case>();
        for(Contact c : myContacts)
        {
            mySCs.addAll(c.ServiceContracts);
            myCases.addAll(c.Cases);
        }
        for(ServiceContract sc : mySCs)
        {
            sc.Contact = null;
        }
        for(Case c : myCases)
        {
            c.Contact = null;
        }
        database.update(mySCs, false);
        database.update(myCases, false);
    }
Many thanks for any help
Hi all,

I have decided to swap from the dev console to visual studio code.I read there was no built in support for formatting apex and it was suggested to install Prettier, which I have done.
When the code is formatted (Shift, Alt + F) parameters in methods are being dropped to the next line. This means that only 1/4 of the actual line space is being used. Below is a screen shot of what it looks like after formatting and what I would like it to look like. After some research it was suggested to change the Prettier:Print Width property from the default value or 80 to 120, which I've done. This made no difference, I've tried increasing it 250 and it the behaviour is still the same. It has also been mentioned that the print width property doesn't work if tsLint is enabled, but I don't have that installed, so I don't think that is the issue.
I've attached some screen shots and code snippets for clarity.

Code formatting example:
//Desired formatting
 public void OnAfterUpdate(Asset[] oldAssets, Map<ID, Asset> oldAssetsMap, Asset[] updatedAssets,Map<ID, Asset> assetsMap){
    fetchAssetCounts(updatedAssets, assetsMap);
  }



//After formatting in VS Code using Prettier
 public void OnAfterUpdate(
    Asset[] oldAssets,
    Map<ID, Asset> oldAssetsMap,
    Asset[] updatedAssets,
    Map<ID, Asset> assetsMap
  ) {
    fetchAssetCounts(updatedAssets, assetsMap);
  }
Screen shot of VS Code:
There is more than enough room on the same line without the parameters dropping to the next line
User-added image

Print width property
User-added image

.prettierrc file
{
  "trailingComma": "none",
  "overrides": [
    {
      "files": "**/lwc/**/*.html",
      "options": { "parser": "lwc"}
    },
    {
      "files": "*.{cmp,page,component}",
      "options": { "parser": "html" }
    }
  ]
}

settings.json file;
{
    "workbench.colorTheme": "Visual Studio Dark",
    "salesforcedx-vscode-apex.java.home": "C:\\Program Files\\Java\\jdk-11.0.12",
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "prettier.requireConfig": true,
    "prettier.arrowParens": "avoid",
    "prettier.useTabs": true,
    "prettier.printWidth": 120,
    "salesforcedx-vscode-core.retrieve-test-code-coverage": true,
    "prettier.proseWrap": "never",
    "prettier.tabWidth": 4,
    "eslint.runtime": ""
}
Does anyone have any suggestions?

Many thanks
Hi,
This is my first time using the @future annotation and was wondering if I could get some guidance.
I have a trigger on the contact, which is handled by a handler class. When a contact is deleted, I need to perfom a call out, so within the handler class I need to call a future method to perform that call out. As a future method only takes primitive data types, I have created another method which passes just the IDs to the future method. Is this the correct way to do this, or is there a better way?
I'm also a little concerned what happens if a mass delete is performed. How do you bulkify call outs?

Trigger:
trigger ContactTrigger on Contact (before delete, before insert, before update, after delete, after insert, after update) 
{
    ContactTriggerHandler handler = new ContactTriggerHandler(Trigger.isExecuting, Trigger.size);
    
    if (Trigger.isInsert && Trigger.isBefore)
    {
        handler.OnBeforeInsert(Trigger.new);       
    }
    else if (Trigger.isInsert && Trigger.isAfter)
    {
        handler.OnAfterInsert(Trigger.new, Trigger.newMap);
    }
    else if (Trigger.isUpdate && Trigger.isBefore)
    {
        handler.OnBeforeUpdate(Trigger.old, Trigger.oldmap, Trigger.new, Trigger.newmap);
    }
    else if (Trigger.isUpdate && Trigger.isAfter)
    {
        handler.OnAfterUpdate(Trigger.old, Trigger.oldmap, Trigger.new, Trigger.newmap);
    }
    else if(Trigger.isDelete && Trigger.isBefore)
    {
        handler.onBeforeDelete(trigger.old, trigger.oldMap);
    }
    else if(Trigger.isDelete && Trigger.isAfter)
    {
        handler.onAfterDelete(trigger.old, trigger.oldMap);
    }
}

Trigger handler class:
public class ContactTriggerHandler extends BaseTriggerHandler
{
    public ContactTriggerHandler(boolean isExecuting, integer size)
    {
        super(isExecuting, size);
    }
    
    public void OnBeforeInsert(Contact[] newContacts) 
    {}     
    
    public void OnAfterInsert(Contact[] newContacts, Map<ID, Contact> newContactsMap) 
    {}
    
    public void OnBeforeUpdate(Contact[] oldContacts, Map<ID, Contact> oldContactsMap, Contact[] updatedContacts, Map<ID, Contact> updatedContactsMap)
    {}
    
    public void OnAfterUpdate(Contact[] oldContacts, Map<ID, Contact> oldContactsMap, 
                              Contact[] updatedContacts, Map<ID, Contact> updatedContactsMap)
    {}
    
    public void OnBeforeDelete(Contact[] oldContacts, Map<ID, Contact> oldContactsMap)
    {}
    
    public void OnAfterDelete(Contact[] oldContacts, Map<ID, Contact> oldContactsMap)
    {
        passIDsToCallOut(oldContactsMap);
    }

    Private void passIDsToCallOut(Map<ID, Contact> contactsMap)
    {
        Set<Id> conIds = contactsMap.keySet();
        system.debug('con Ids for forget request');
        system.debug(conIds);
        sendForgetRequestGDPR(conIds);
    }
    
    @future(callout=true)
    Public static void sendForgetRequestGDPR(Set<id> contactIds)
    {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://****.com/api/auth/v1/login?email=myemail@email.co.uk&password=myPassword');
        request.setMethod('POST');
        request.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        request.setHeader('Accept', 'application/json');
        HttpResponse authResponse = http.send(request);
        if (authResponse.getStatusCode() == 200) {
            system.debug('got auth!');
            // Deserialize the JSON string into collections of primitive data types.
            Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(authResponse.getBody());
            List<Object> myresults = new List<Object>();
            for(Object obj : results.values())
            {
                myresults.add(obj);
            }
            string sessionId = string.ValueOf(myresults[0]);
            system.debug('session Id = ' +sessionId);
            request = new HttpRequest();
            request.setEndpoint('https://*****.com/api/v1/services/*****/gdpr/forget');
            request.setMethod('POST');
            request.setHeader('Content-Type','application/x-www-form-urlencoded');
            request.setHeader('Accept','application/json');
            request.setHeader('X-SESSION-ID',sessionId); 
            string comment = 'API Call';
            string contactId;
            for(Id conId : contactIds)
            {
                contactId = conId;
                request.setBody('record_id='+contactId+'&table_name=Contact&comment=' + EncodingUtil.urlEncode(comment, 'UTF-8'));
                system.debug(request);
                HttpResponse forgetResponse = http.send(request);
                if(forgetResponse.getStatusCode() == 200)
                {
                    system.debug('got GDPR!');
                }
                else
                {
                    system.debug('Forget Broken =' + forgetResponse.getStatusCode());
                }           
            }       
        }
        else
        {
            system.debug('Auth Broken =' + authResponse.getStatusCode());
        } 
    }
}

Many thanks
 
Hi,

I've never attempted an API link before so was wondering if someone could point me in the right direction of how this is best handled.
We currently use Own BackUp for all Salesforce data and metadata back ups. When a contact is deleted in Salesforce, at the moment I'm manually going into Own BackUp and creating a GDPR Forget request. Own BackUp have an API which allows you to send a forget request ( Forget Record (https://cdn2.hubspot.net/hubfs/2571574/api%20document-1.html#tag/GDPR/paths/~1api~1v1~1services~1{service_id}~1gdpr~1forget/post) ) and I would very much like to automate this when a contact is deleted in SF. I'm used to writing triggers, but have never done anything with APIs. If someone could give me base to start it would be very much appreciated. 

Many thanks
Hi All,

I have a recordEditForm on an Aura component which displays the core fields from the case object. 
My issue is I need the standard description field to automatically expand it's height to show all the content, like it does on the detail page.
Currently I get scoll bars and the ability to drag the box to expose the text.
Is it possible with a lightning:inputfield?
 
<div class="slds-grid slds-wrap">
                        <div class="slds-col slds-size_1-of-1">
                            <lightning:inputField fieldName="Description" onchange="{!c.enableButtons}"/>
                        </div>
                    </div>

 
Hi,

I have a aura component which uses a lightning:recordEditForm and a standard Lighting:button of type 'submit' to save the data. I want to implement the lightning:unsavedChanges component, which is halfway there, but when the user presses 'Save' on the unsaved changes dialog I cannot figure out how to either call the standard save function from submit button or to close the unsaved changes dialog so the user has to press save on the form.
Here is my code:

Component:
<aura:component controller="CaseController" implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:attribute name="reloadForm" type="boolean" default="true"/>
    <aura:attribute name="saveDisabled" type="boolean" default="true"/>
    <aura:attribute name="cancelDisabled" type="boolean" default="true"/>
    
    <lightning:unsavedChanges aura:id="unsaved"
                              onsave="{!c.handleSave}"
                              ondiscard="{!c.handleDiscard}"/>
    
    <!-- Notification library to show notifications-->
    <lightning:notificationsLibrary aura:id="notifLib"/>
    
    <lightning:card title="Case #">
        <div class="slds-p-left_large slds-p-right_medium">	
            <lightning:recordEditForm aura:id="recordEditForm" 
                                      objectApiName="Case"
                                      recordId="{!v.recordId}"
                                      onsuccess="{!c.handleSuccess}"
                                      density="comfy">
                <aura:if isTrue="{!v.reloadForm}">
                    <lightning:messages />             
                    <div class="slds-grid slds-wrap">
                        <div class="slds-col slds-size_1-of-2">
                            <lightning:inputField fieldName="Status" onchange="{!c.enableButtons}"/>
                            <lightning:inputField aura:id="asset" fieldName="AssetId" onchange="{!c.handleAssetChange}"/>
                            <lightning:inputField aura:id="assFaultCat" fieldName="Fault_Category__c" disabled="true" onchange="{!c.enableButtons}" />
                            <lightning:inputField aura:id="assFaultType" fieldName="Fault_Type__c" onchange="{!c.enableButtons}" />
                        </div>
                        <div class="slds-col slds-size_1-of-2">
                            <lightning:inputField fieldName="Priority" onchange="{!c.enableButtons}"/>
                            <lightning:inputField aura:id="assMakeModel" fieldName="Asset_Make_and_Model__c" />
                            <lightning:inputField fieldName="Interface_Type__c"/>    
                            <lightning:inputField fieldName="Connection_Method__c"/>
                        </div>
                    </div>
                    <div class="slds-grid slds-wrap">
                        <div class="slds-col slds-size_1-of-1">
                            <lightning:inputField fieldName="Description" onchange="{!c.enableButtons}"/>
                        </div>
                        <div class="slds-col slds-size_1-of-1">
                            <lightning:inputField fieldName="Help_Required__c" onchange="{!c.enableButtons}"/>
                        </div>
                    </div>
                    <div class="slds-grid slds-wrap">
                        <div class="slds-col slds-size_1-of-2">
                            <lightning:inputField fieldName="Solution__c"/>
                        </div>
                        <div class="slds-col slds-size_1-of-2">
                            <lightning:inputField fieldName="Solution_Details__c" onchange="{!c.enableButtons}" />
                        </div>
                    </div>
                    <aura:set attribute="else">
                        Saving...
                    </aura:set>
                </aura:if>
                <lightning:button class="slds-m-top_small"  name="cancel" label="Cancel" disabled = "{!v.cancelDisabled}" onclick="{!c.handleReset}"/>
                <lightning:button class="slds-m-top_small" variant="brand" type="submit" name="save" label="Save" disabled = "{!v.saveDisabled}" />
            </lightning:recordEditForm>
        </div>
    </lightning:card>	
</aura:component>
Controller:
({
    handleAssetChange: function(component, event, helper) {
        console.log('asset changed');
        var newID = event.getParam("value");
        if(newID.length >0)
        {
            if(newID.length > 0)
            {
                console.log('helper called');
                console.log(newID[0]);
                helper.updateAsset(component, newID[0]);  
            } 
        } 
    },
    
    enableButtons: function(component, event, helper) {
        console.log('field changed');
        var unSavedChange = component.find('unsaved');
        unSavedChange.setUnsavedChanges(true, { label: 'You have unsaved changes. Do you want to Continue?' }); 
        helper.toggleButtons(component, false, false);
    },
    
    handleSave : function(component, event, helper) {
        var unSavedChange = component.find('unsaved');
        unSavedChange.setUnsavedChanges(false);
    },
   
    handleSuccess : function(component, event, helper) {
        console.log('success handled');
        helper.handleSuccess(component, event, helper);
    },
    
    handleReset: function(component, event, helper) {
        console.log('Cancel clicked');
        helper.toggleButtons(component, true, true);
        helper.reshowForm(component);
    }
})

Helper:
({
    updateAsset : function(component, assetId){
        var action = component.get("c.fetchAsset");
        console.log('Helper - New asset Id = ' + assetId);
        action.setParams({
            "assetId": assetId
        });
        action.setCallback(this, function(result){
            var serverState = result.getState();
            console.log('Server state = ' + serverState);
            console.log('Asset Update');
            var res = result.getReturnValue();
            console.log('res result');
            console.log(res);
            //Ideally put a check in here to see if the new asset is covered under contract and if not, display an error. Will also have to check that the case doesn't already have a PO number assigned
            if (component.isValid() && serverState === "SUCCESS"){
                component.find('assFaultCat').set('v.value', res.Product_Category__c);
                component.find('assFaultType').set('v.value', null);
                var toastEvent = $A.get("e.force:showToast");
                console.log('the asset was changed');
                /*toastEvent.setParams({
                    "title": "Success",
                    "message": "The asset has been updated",
                    "type" : "success"
                });
                toastEvent.fire();*/
            }
            else if (serverState === "ERROR") {
                var errors = result.getError();
                console.log('There are errors');
                console.error(errors);
                if(errors){
                    if(errors[0] && errors[0].message){
                        var toastEvent = $A.get("e.force:showToast");
                        toastEvent.setParams({
                            "title": "Error!",
                            "message": errors[0].message,
                            "mode" : "sticky",
                            "type" : "error"
                        });
                        toastEvent.fire();
                    }
                }
            }
        });
        $A.enqueueAction(action);  
    },
    
    handleSuccess : function(component, event, helper){
        console.log('handle success helper called');
        component.find('notifLib').showToast({
            "variant": "success",
            "title": "Success!",
            "message": "The record has been successfully updated"
        });
        this.toggleButtons(component, true, true);
    },
    
    
    toggleButtons: function(component, saveDisabled, cancelDisabled)
    {
        console.log('toggle buttons -' + 'Save = ' + saveDisabled + 'Cancel = '+ cancelDisabled);
        component.set("v.saveDisabled", saveDisabled);
        component.set("v.cancelDisabled", cancelDisabled);
    },
    
    reshowForm: function(component)
    {
        console.log('reshow form');
        component.set("v.reloadForm", false);
        component.set("v.reloadForm", true);
    }
})

Many thanks​​​​​​​
 
Hi All,

On the opportunity record page I have an Aura component which has a Lightning:DataTable that displays all open tasks that meet a certain criteria. Also on the opportunity record page there is an Actions & Recommendations component which has access to 5 quick actions which create a task. What I want to be able to do is when a new task is created, the datatable to automatically refresh. I've tried using platform events(which this is the first time I've used them, so not really too sure what I'm doing). I've got an If statement in the callback to check if the task whatId matches the record Id, but this still means that every opportunity that is open on a tab is listening for the event. Not all opportunities have the data table component on the record page, and it doesn't seem that the subscription is destroyed when the tab is closed.
How do I unscribe to the event when the tab is closed? If the page is refreshed then it seems to be fine.
If there is another way to do this I'd be more than grateful for suggestions

Task Trigger Handler Code:
Private void psTaskCreated(Task[] tasks)
    {
        List<Task_Creation_Event__e> taeList = new List< Task_Creation_Event__e>();
        for(task tsk : tasks)
        {
            Task_Creation_Event__e taskEvent = new Task_Creation_Event__e();
            if(tsk.whatId != null && tsk.WhatId.getSObjectType() == Opportunity.sObjectType && tsk.Project_Task__c)
            {
                Task_Creation_Event__e tce = new Task_Creation_Event__e();
                tce.Opp_Id__c = tsk.WhatId;
                taeList.add(tce);  
            }
        }
        //Publish event
        try{
            if(taeList.size()>0)
                EventBus.publish(taeList);
        }catch(Exception e){
            throw new auraHandledException('Broken!');
        }
    }

Component:
<aura:component controller="OpportunityController" implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    <aura:attribute name="mydata" type="Object"/>
    <aura:attribute name="mycolumns" type="List"/>
    <aura:attribute name="listSize" type="integer"/>
    <aura:attribute name="draftValues" type="Object" default="[]"/>
    <aura:attribute name="Task" type="Task" default="{'sObjectType':'Task'}"/>
    <aura:attribute name="showSpinner" type="boolean" default="false"/>
    <lightning:empApi aura:id="empApi" />

    <div>
        <lightning:notificationsLibrary aura:id="notifLib"/>
            <aura:if isTrue="{!v.showSpinner }">
                <lightning:spinner alternativeText="Loading" />      
                <aura:set attribute="else">              
                    <!--To Do List Table--> 
                    <div class="slds-m-top--none slds-box slds-theme_default" >
                        <div class="slds-align_absolute--left">
                            <div class="slds-text-heading_small slds-text-color_default">       
                                Things I need to do ({!v.listSize})
                                <lightning:buttonicon iconName="utility:refresh" alternativeText="Refresh" 
                                                      variant = "brand" class=" slds-button_icon-x-small"
                                                      onclick="{!c.doInit}"/>
                            </div>
                        </div>
                        <div style="height: 175px;">
                            <lightning:datatable data="{! v.mydata }" 
                                                 columns="{! v.mycolumns }"
                                                 keyField="Id" 
                                                 draftValues="{!v.draftValues}"
                                                 onrowaction="{!c.handleRowAction}"
                                                 onsave="{!c.handleSaveEdition}"/> 
                        </div>
                    </div> 
                </aura:set>
            </aura:if>
    </div>
</aura:component>

Controller:
//get tasks from apex controller
    doInit : function(component, event, helper) { 
        console.log('do init called');
        var channel = '/event/Task_Creation_Event__e';
        const replayId = -1;
        const empApi = component.find("empApi");
        
        //A callback function that's invoked for every event received
        const callback = function (message) {
            var msg = message.data.payload;
            console.log('msg = '+JSON.stringify(msg));           
            console.log('Message returned : ' +msg.Opp_Id__c );  
if(msg.Opp_Id__c === component.get("v.recordId"))
            {
                console.log('Fetch tasks about to be called');
                helper.fetchTasks_Active(component);
            } 
        };
        // Subscribe to the channel and save the returned subscription object.
        empApi.subscribe(channel, replayId, callback).then(function(newSubscription) {
            console.log("Subscribed to channel 1" + channel);
        });
        const errorHandler = function (message) {
            console.error("Received error ", JSON.stringify(message));
        };
        empApi.onError(errorHandler);
        helper.fetchTasks_Active(component);
    },

Helper:
fetchTasks_Active : function(component){
        var actions = [
            {label: 'Show comments', name:'show_comments'},
            {label: 'Complete task', name:'complete_task'},
            {label: 'View task', name:'view_task'}       
        ];
        component.set('v.mycolumns', [
            {label: 'Due Date', fieldName: 'ActivityDate', type: 'date', editable:'true'},
            {label: 'Task Type', fieldName: 'Task_Type__c', type: 'text'},
            {label: 'Subject', fieldName: 'Subject', type: 'text', editable:'true'},
            {label: 'Comments', fieldName: 'Description', type: 'text', wrapText: true, editable:'true'},
            {label: 'Contact', fieldName: 'WhoName', type: 'text'},
            {label: 'Status', fieldName: 'Status', type: 'text'},
            {type: 'action', typeAttributes: {rowActions: actions}}
        ]);
        
        var action = component.get("c.fetchOpenProjectTasks");
        action.setParams({
            "oppId": component.get("v.recordId")
        });
        action.setCallback(this, function(result){
            var serverState = result.getState();
            console.log('Server state = ' + serverState);
            console.log('Fetch active tasks');
            var res = result.getReturnValue();
            console.log('res result');
            console.log(res);
            if (component.isValid() && serverState === "SUCCESS"){
                component.set("v.listSize",res.length);
                var rows = res;
                for (var i = 0; i < rows.length; i++) 
                { var row = rows[i];
                 if(row.Who)
                 {
                     row.WhoName = row.Who.Name;
                     if(row.TaskRelations.length >1)
                     {
                         var relatedWho = row.TaskRelations.length -1;
                         row.WhoName = row.Who.Name + ' +' + relatedWho.toString();
                     }
                 }
                }
                component.set("v.mydata",res);
            }
            else if (serverState === "ERROR") {
                var errors = result.getError();
                console.log('There are errors');
                console.error(errors);
                if(errors){
                    if(errors[0] && errors[0].message){
                        self.fetchErrors(component, errors, self);
                    }
                }
            }
        });
        $A.enqueueAction(action);    
    },
Many thanks
 
Hi All,

I am fairly new to lightning components and am struggling to get a datatbale to show any server side errors. I have looked at the documentation (Salesforce Documention (https://developer.salesforce.com/docs/component-library/bundle/lightning:datatable/example#lightningcomponentdemo:exampleDatatableInlineEdit) )and tried to implement it to my scenario but cannot get it to work.
This is my code:

Component:
<aura:component controller="BuildUpChecklistController" implements="force:appHostable,flexipage:availableForRecordHome,force:hasRecordId">
	<aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    <aura:handler event="force:refreshView" action="{!c.doInit}"/>
    <aura:attribute name="mydata" type="Object"/>
    <aura:attribute name="mycolumns" type="List"/>
    <aura:attribute name="errors" type="Object" default="[]"/>
    <aura:attribute name="draftValues" type="Object" default="[]"/>
    <aura:attribute name="listSize" type="Integer" default="0"/>
    
    <!--User List Table-->
    <div class="slds-m-top--none slds-box slds-theme_default" >
        <div class="slds-align_absolute--left">
            <div class="slds-text-heading_small slds-text-color_default">       
                Update build notes and on site fields
                <lightning:helptext content="Help!"/>
            </div>
        </div>
        <lightning:datatable data="{! v.mydata }" 
                             columns="{! v.mycolumns }"
                             showRowNumberColumn= "true"
                             wrapTextMaxLines="3"
                             keyField="Id" 
                             errors="{!v.errors}"
                             draftValues="{!v.draftValues}"
                             onsave="{!c.handleSaveEdition}"/>
    </div>
</aura:component>

Controller:
handleSaveEdition: function (component, event, helper) {
        var draftValues = event.getParam('draftValues');
        var action = component.get("c.updateOLIs");
        action.setParams({"OLIs" : draftValues});
        action.setCallback(this, function(result){
            var state = result.getState();
            if(state === "SUCCESS"){
                    component.set("v.errors", []);
                    component.set("v.draftValues", []);
                    var toastEvent = $A.get("e.force:showToast");
                    toastEvent.setParams({
                        "title": "Success",
                        "message": "The opportunity line items have been updated",
                        "type" : "success"
                    });
                    toastEvent.fire();
                    $A.get('e.force:refreshView').fire();
                //}              
            } else if(state === "ERROR"){
               //I don't know what to use here to display any server side errors 
               //on the relevant rows of the datatable
               //
            } else if (status === "INCOMPLETE"){
                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                    "title": "Error!",
                    "message": "'No response from server or client'",
                    "type" : "error"
                });
                toastEvent.fire();
                $A.get('e.force:refreshView').fire();
            }
        });
        $A.enqueueAction(action);
    },

Apex Controller:
(I'm not doing any validation in this method at the moment, but I will)
 
@AuraEnabled
    public static void updateOLIs(List<OpportunityLineItem> OLIs)
    {
        update OLIs;
    }

Any help would be much appreciated,
Thank you​​​​​​​
I have a custom tab that displays a lighning component which on a click event allows a user to edit a record.
I am trying to listen for a save success on the e.force:editRecord and after much searching I found no solution as apparently there is no standard callback for the editRecord
https://trailblazer.salesforce.com/ideaView?id=0873A000000CQQiQAO
As per a few other suggestions I have added an handler for the force:showToast
This is working, albeit a hack, but the problem is as this is an application event it is constantly being listened for even if the custom tab isn't open.
Does anyone have any ideas how I can remedy this
<aura:handler event="force:showToast" action="{!c.handleToastEvent}"/>



handleToastEvent: function(component, event, helper){
        var toastMessageParams = event.getParams();
        var message = toastMessageParams.message;
        if(message.includes('Resource Placeholder') && message.includes('was saved')){
            var calendar = component.get('v._Calendar');
            var calendarEvent = event.getParam("calendarEvent")
            helper.fetchCalendarEvents(component, calendar, calendarEvent);
        }
    }

Many thanks,
Hi,

I have a scenario where I need to get the mouse position for nested aura components.
I have tried using getBoundingClientRect, clientX/Y, pageX/Y, offsetLeft/Top, but they are not taking into consideration the space that the other component could be taking up above or to the side of it.

So in the example below I need to get the mouse position from within the Calendar_Scheduling component, but that component is not aware of the CalendarFilters component that is sitting above it. So when using any of the getBoundingClientRect, clientY, pageY or offsetTop the position that is being returned is incorrect. 
Is there a property that I can use that will return the correct co-ordinates regardless of any other components that are on the page
 
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" access="global">
    
    <lightning:layout class="slds-theme_default" multipleRows = "true">    
        <lightning:layoutItem size="12" mediumDeviceSize="12" padding="around-small">
            <c:CalendarFilters Initialised="{!v.initialised}" 
                               Department="{!v.resourceDepartment}" 
                               Location="{!v.resourceLocation}"
                               ShowWorkOrders="{!v.showWorkOrders}"
                               ShowProfessionalServiceWork="{!v.showPSWork}"
                               ShowPlaceholders="{!v.showPlaceholders}"
                               IsSchedulingCalendar="{!v.isSchedulingCalendar}"
                               ProjectManager="{!v.projectManager}"/>
        </lightning:layoutItem>
        
        <lightning:layoutItem size="12">
            <c.Calendar_Scheduling Enabled="{!v.initialised}" 
                                   Department="{!v.resourceDepartment}" 
                                   Location="{!v.resourceLocation}"
                                   ProjectManager="{!v.projectManager}"
                                   IsSchedulingCalendar="{!v.isSchedulingCalendar}"/>
        </lightning:layoutItem>
    </lightning:layout>
</aura:component>

Many thanks
Hi,

I have a table with horizontal and vertical scroll bars and would like to lock the column headers when scrolling in either direction.
 
<lightning:layoutItem size="12" padding="around-small"><b>Work Orders</b>
        <div class="external-events slds-table--header-fixed_container" style="height:20rem;">
            <div class=" slds-scrollable " style="height:100%;">
                <table class="slds-table slds-table_bordered slds-table_cell-buffer slds-table--header-fixed">
                    <thead>
                        <tr>
                            <th scope="col">
                                <div class="slds-cell-fixed">WO#</div>
                            </th>
                            <th  scope="col">
                                <div class="slds-cell-fixed">Account</div>
                            </th>
                            <th scope="col">
                                <div class="slds-cell-fixed">Postcode</div>
                            </th>
                            <th scope="col">
                                <div class="slds-cell-fixed">Status</div>
                            </th>
                            <th scope="col">
                                <div class="slds-cell-fixed" >Subject</div>
                            </th>
                        </tr>
                    </thead>
                    <tbody>
                        <aura:iteration items="{!v.woList}" var="item">
                            <tr>
                                <td>
                                    <div class="{!'fc-event ' + item.className}" 
                                         data-id="{!item.id}"
                                         data-tag="{!item.tag}"
                                         onclick="{!c.handleClick}">{!item.WorkOrderNumber}   
                                    </div>
                                </td>
                                <td> 
                                    <div>{!item.accountName}</div>
                                </td>
                                <td> 
                                    <div>{!item.postcode}</div> 
                                </td>
                                <td> 
                                    <div>{!item.Status}</div>
                                </td>
                                <td>
                                    <div>{!item.Subject}</div>
                                </td>                            
                            </tr>
                        </aura:iteration>
                    </tbody>
                </table>
            </div>
        </div> 
    </lightning:layoutItem

At the moment it's scrolling ok, and when you scroll vertically the headers are fixed, but the column headers do not move when scrolling horizontally. I'm guessing it's because of the slds-cell-fixed, but I'm not sure what to change it to.
Any help would be much appreciated
Hi,

I am trying to show a tooltip within an aura:iteration. The tooltip is now displaying but the text is not wrapping onto the next line, it's continuing beyond the boundaries of the toolttip containiner.
I've changed the text colour to make it a little clearer what's happening
Tooltip

Component
<lightning:layoutItem size="12" padding="around-small"><b>Professional Services</b>
        <div class="psWork-events slds-scrollable">
            <table class="slds-table slds-table_bordered slds-table_cell-buffer">
                <thead>
                    <tr>
                        <th scope="col">
                            <div>Work</div>
                        </th>
                        <th scope="col">
                            <div>Account Name</div>
                        </th>
                        <th scope="col">
                            <div>Start</div>
                        </th>
                        <th scope="col">
                            <div># Days</div>
                        </th>
                        <th scope="col">
                            <div># Alloc</div>
                        </th>
                        <th scope="col">
                            <div># Req</div>
                        </th>
                        <th scope="col">
                            <div>Project Manager</div>
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <aura:iteration items="{!v.swList}" var="item" indexVar="index">
                        <tr data-selected-Index="{!index}">
                            <td>
                                <div class="{!'fc-event ' + item.className}" 
                                     data-id="{!item.id}" 
                                     data-title="{!item.title}"
                                     data-tag="{!item.tag}"
                                     data-starts="{!item.starts}"
                                     data-opp = "{!item.navigationId}"
                                     data-index="{!index}"
                                     onmouseover="{!c.handleMouseOver}"
                                     onmouseout="{!c.handleMouseOut}"
                                     onclick="{!c.handleClick}"> {!item.title}
                                    <div aura:id="ps-hover" 
                                         class="slds-hide slds-popover slds-popover_tooltip slds-nubbin_left" 
                                         style="position:absolute;top:-4px;left:35px">
                                        <div class="slds-popover__body" style="color:red;">
                                             Some really long text that should drop onto the next line, but what's actually happening is the text is continuing outside of the tooltip boundaries
                                        </div>               
                                    </div> 
                                </div>
                            </td>
                            <td>
                                <div>{!item.accountName}</div>
                            </td>
                            <td> 
                                <div><lightning:formattedDateTime value ="{!item.starts}"  month="short" day="2-digit" /> </div>
                            </td>
                            <td> 
                                <div>{!item.numberOfDays}</div>
                            </td>
                            <td> 
                                <div>{!item.alcTechCount}</div>
                            </td>
                            <td> 
                                <div>{!item.reqTechCount}</div>
                            </td>
                            <td> 
                                <div>{!item.ProjectManager}</div>
                            </td>
                        </tr>
                    </aura:iteration>
                </tbody>
            </table>
        </div> 
    </lightning:layoutItem>


Controller:
 
handleMouseOver : function(component,event,helper){
        console.log('Mouse entered');
        var items = component.find("ps-hover");
        if(!items.length) items = [items];
        console.log('Removing class for =', parseInt(event.target.dataset.index ));
        $A.util.removeClass(items[parseInt(event.target.dataset.index)],'slds-hide');
    },
    handleMouseOut : function(component,event,helper){ 
        console.log('Mouse left');
        var items = component.find("ps-hover");
        if(!items.length) items = [items];
        console.log('Adding class for =', parseInt(event.target.dataset.index ));
        $A.util.addClass(items[parseInt(event.target.dataset.index)],'slds-hide');      
    }

Any help would be much appreciated
Thanks
 
Hi,

Has anyone had any joy in using tooltips (popper and tooltip.js) with the Full Calendar Scheduler V4 resource timeline view?
I have created a very simple cut down version to demonstrate the issue I'm having. The tooltip is being created but it isn't being displayed. If I create the project in codepen using the exact same files as are in my static resources it works as intended.
 
Component
<aura:component implements="force:appHostable" access="global">
   <ltng:require scripts="{!join(',',
                           $Resource.FullCalendarCoreMainV4_3_1JS,
                           $Resource.FullCalendarInteractionV4_3_1JS,
                           $Resource.FullCalendarDayGridMainV4_3_1JS,
                           $Resource.FullCalendarTimelineMainV4_3_1JS,
                           $Resource.FullCalendarTimegridMainV4_3_1JS,
                           $Resource.FullCalendarResourceCommonMainV4_3_1JS,
                           $Resource.FullCalendarResourceTimelineMainV4_3_1JS,
                           $Resource.FullCalendarResourceDayGridMainV4_3_1JS,
                           $Resource.FullCalendarResourceTimegridMainV4_3_1JS,
                           $Resource.PopperMin, 
                           $Resource.TooltipMin
                           )}"
                 styles="{!join(',',
                          $Resource.FullCalendarCoreMainV4_3_1CSS,
                          $Resource.FullCalendarDayGridMainV4_3_1CSS,
                          $Resource.FullCalendarTimelineMainV4_3_1CSS,
                          $Resource.FullCalendarResourceTimelineMainV4_3_1CSS)}"  
                  afterScriptsLoaded="{!c.scriptsLoaded}"
                  />    
    <!-- COMPONENT UI -->  
        <div id="calendar"/> 
</aura:component>

Controller:
 
({ 
    scriptsLoaded : function(component, event, helper) {
        console.log('Calendar scripts loaded'); 
        var calendarElement = document.getElementById('calendar');
        var calendar = new FullCalendar.Calendar(calendarElement,{
            plugins:['resourceTimeline', 'dayGrid'],
            header: {
                left: 'prev,next today',
                center: 'title',
                right: 'timelineFiveDays, resourceTimelineDay, dayGridMonth'
            },
            defaultView: 'timelineFiveDays',
            views: {            
                timelineFiveDays:{
                    type: 'resourceTimeline',
                    duration: { weeks: 1 },
                    slotDuration: {days: 1},
                    weekends: false,
                    buttonText: '5 Days'
                },
            },
            resources:[
                {
                    id:'a',
                    title:'Person A'
                },
                {
                    id:'b',
                    title:'Person B'
                }
            ],
            events: [
                {
                    title: 'Event 1',
                    description: 'Description for Event 1',
                    start: '2020-04-27',
                    resourceId: 'a'
                },
                {
                    title: 'Event 2',
                    description: 'Description for Event 2',
                    start: '2020-04-28',
                    resourceId: 'a'
                },
                {
                    title: 'Event 3',
                    description: 'Description for Event 3',
                    start: '2020-04-29',
                    resourceId: 'a'
                }
            ],
            eventRender: function(info) {
                var tooltip = new Tooltip(info.el, {
                    title: info.event.extendedProps.description,
                    placement: 'top',
                    trigger: 'hover',
                    container: 'body'
                });
                console.log(tooltip);
            },
        });
        calendar.render();
    },
})

Style:
I have also tried removing everything from the style class with the same result
.THIS .popper .tooltip {
  position: absolute;
  z-index: 9999;
  background: #FFC107;
  color: black;
  width: 150px;
  border-radius: 3px;
  box-shadow: 0 0 2px rgba(0,0,0,0.5);
  padding: 10px;
  text-align: center;
}
.THIS .style5 .tooltip {
  background: #1E252B;
  color: #FFFFFF;
  max-width: 200px;
  width: auto;
  font-size: .8rem;
  padding: .5em 1em;
}
.THIS .popper .popper__arrow .tooltip .tooltip-arrow {
  width: 0;
  height: 0;
  border-style: solid;
  position: absolute;
  margin: 5px;
}

.THIS .tooltip .tooltip-arrow .popper .popper__arrow {
  border-color: #FFC107;
}
.THIS .style5 .tooltip .tooltip-arrow {
  border-color: #1E252B;
}
.THIS .popper[x-placement^="top"] .tooltip[x-placement^="top"] {
  margin-bottom: 5px;
}
.THIS .popper[x-placement^="top"] .popper__arrow .tooltip[x-placement^="top"] .tooltip-arrow {
  border-width: 5px 5px 0 5px;
  border-left-color: transparent;
  border-right-color: transparent;
  border-bottom-color: transparent;
  bottom: -5px;
  left: calc(50% - 5px);
  margin-top: 0;
  margin-bottom: 0;
}
.THIS .popper[x-placement^="bottom"] .tooltip[x-placement^="bottom"] {
  margin-top: 5px;
}
.THIS .tooltip[x-placement^="bottom"] .tooltip-arrow .popper[x-placement^="bottom"] .popper__arrow {
  border-width: 0 5px 5px 5px;
  border-left-color: transparent;
  border-right-color: transparent;
  border-top-color: transparent;
  top: -5px;
  left: calc(50% - 5px);
  margin-top: 0;
  margin-bottom: 0;
}
.THIS .tooltip[x-placement^="right"] .popper[x-placement^="right"] {
  margin-left: 5px;
}
.THIS .popper[x-placement^="right"] .popper__arrow .tooltip[x-placement^="right"] .tooltip-arrow {
  border-width: 5px 5px 5px 0;
  border-left-color: transparent;
  border-top-color: transparent;
  border-bottom-color: transparent;
  left: -5px;
  top: calc(50% - 5px);
  margin-left: 0;
  margin-right: 0;
}
.THIS .popper[x-placement^="left"] .tooltip[x-placement^="left"] {
  margin-right: 5px;
}
.THIS .popper[x-placement^="left"] .popper__arrow .tooltip[x-placement^="left"] .tooltip-arrow {
  border-width: 5px 0 5px 5px;
  border-top-color: transparent;
  border-right-color: transparent;
  border-bottom-color: transparent;
  right: -5px;
  top: calc(50% - 5px);
  margin-left: 0;
  margin-right: 0;
}
Browser Console
Browser Console Debugging​​​​​​​From the browser console you can see the tooltip is being created, but it isn't being displayed. As this is working in codepen I'm assuming Salesforce is blocking something, but I'm not really too sure where to start

Any help would be much appreciated
I was wondering if anyone knew of a way to get the values of the field within a page layout section. Within a trigger I want to grab the fields and values assigned, that are within a particular section, and then calculate an average based on the field values.
I've got the field names and was hoping there was a way I could get the value.
 
private void setFusionScore(Training_Self_Assessment__c[] newSAs)
    {
        for(Training_Self_Assessment__c tsa : newSAs)
        {
            system.debug('TSA trigger');
            List<Metadata.Metadata> layouts = 
                Metadata.Operations.retrieve(Metadata.MetadataType.Layout, 
                                             new List<String> {'Training_Self_Assessment__c-Training Record Layout'});
            system.assertEquals(1, layouts.size());
            Metadata.Layout layoutMd = (Metadata.Layout)layouts.get(0);
            for (Metadata.LayoutSection section : layoutMd.layoutSections) 
            {
                if(section.label == 'Fusion')
                {  
                    for (Metadata.LayoutColumn column : section.layoutColumns) 
                    {
                        if (column.layoutItems != null) 
                        {
                            for (Metadata.LayoutItem item : column.layoutItems) 
                            {
                                system.debug('Field Name = ' + item.field);
                                system.debug('Field Value = ' + item.??);
                            }
                        }
                    }
                }
            }
        }         
    }

Many thanks
Does anyone know how to close a workspace(primary) tab and it's sub tabs?
The below only returns the subtab. I need to close the primary and any subtabs.
var workspaceAPI = component.find("workspace");
workspaceAPI.getEnclosingTabId().then(function(tabId) {
                    var enclosingTabId = tabId;
                    workspaceAPI.closeTab({tabId: enclosingTabId});
                })
Many thanks
 
I have a lightning component that closes a case. Depending on the button that is pressed it either closes the case and leaves the workspace tab open or closes the case and the workspace tab.
All is working great until I set the visibility on the component. I don't want it to show if the case status is closed.
When the above criteria is set on the component, the onSuccess method is not called, only the onLoad and handleSumbit function that is called from the click event of the 2 save buttons. 
Is there a way I can set a visibility criteria on the component and still have the onSuccess method being called?

Component
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId">
    <lightning:workspaceAPI aura:id="workspace"/>
    <aura:attribute name="showSpinner" type="Boolean" default="true"/>
    <aura:attribute name="closeTab" type="Boolean" default="true"/>
    <aura:if isTrue="{!v.showSpinner}">
        <lightning:spinner />
    </aura:if>
    <div class="slds-box slds-theme_default">
        <div class="slds-text-title_bold">Close the Case</div>
        <lightning:recordEditForm aura:id="recordEditor"
                                  onload="{!c.handleLoad}"                                 
                                  onsuccess="{!c.handleSuccess}"
                                  recordId = "{!v.recordId}"
                                  objectApiName="Case">
            <lightning:messages />
            <div class="slds-grid">
                <div class="slds-col slds-size_1-of-2">
                    <lightning:inputField aura:id="fieldStatus" fieldName="Status" disabled="true" />
                    <lightning:inputField aura:id="field" fieldName="Fault_Type__c" />
                    <lightning:inputField aura:id="field" fieldName="Solution_Details__c" />                    
                </div>
                <div class="slds-col slds-size_1-of-2">
                    <lightning:inputField aura:id="field" fieldName="Fault_Category__c" disabled="true" />                    
                    <lightning:inputField aura:id="field" fieldName="Solution__c" />
                </div>                      
            </div>
            <div class="slds-m-top_medium">
                <lightning:button aura:id="button3" variant="neutral" name="Cancel" label="Cancel" onclick="{!c.handleCancel}" />
                <lightning:button aura:id="button2" variant="brand" type="button" name="save2" label="Close Case" onclick="{!c.handleSubmit}" />
                <lightning:button aura:id="button1" variant="brand" type="button" name="save" label="Close Case and Tab" onclick="{!c.handleSubmit}"/>                                
            </div>
        </lightning:recordEditForm>
    </div> 
</aura:component>
Controller
({
    handleLoad : function(component, event, helper) {
        console.log('handle handleLoad');
        component.find("fieldStatus").set("v.value", "Closed");
        component.set("v.showSpinner", false);
    },
    
    handleSubmit : function(component, event, helper) {
        event.preventDefault(); // Prevent default submit      
        component.find('recordEditor').submit(); // Submit form
        console.log('handle handleSubmit');
        if(event.getSource().getLocalId() == 'button2'){
            component.set("v.closeTab", false);
        }        
    },
    
    handleSuccess : function(component, event, helper) {
        console.log('record updated successfully'); 
        component.set("v.showSpinner", false);
        // Success! Prepare a toast UI message
        var resultsToast = $A.get("e.force:showToast");
        resultsToast.setParams({
            "title": "Case Saved",
            "message": "The case has been closed"
        });
        resultsToast.fire();
        var closeTab2 = component.get("v.closeTab");
        console.log(closeTab2);
       //Below should only fire if a specific lighting button was pressed
        if(closeTab2){           
            var workspaceAPI = component.find("workspace");
            console.log('closing tab');
            workspaceAPI.getFocusedTabInfo().then(function(response) {
                var focusedTabId = response.tabId;
                workspaceAPI.closeTab({tabId: focusedTabId});
            })
            .catch(function(error) {
                console.log(error);
            }); 
        }       
    },
    
    handleCancel: function(component, event, helper) {
        console.log('updated cancelled');
        component.find('field').forEach(function(f) {
            f.reset();
        });
    }
})

Thanks
Hi,

I was wondering if there was a way to get the ID of the button that was clicked on a recordEditForm within the onsuccess method.
I have tried 
console.log(event.getSource().getLocalId());
but that just returns the ID of the recordEditForm, not the button that was clicked.
The reason I need this is I want to display two buttons, one that simply updates the case and the other which updates the case and closes the workspace tab

This is my component
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId">
    <lightning:workspaceAPI aura:id="workspace"/>
    <aura:attribute name="showSpinner" type="Boolean" default="true"/>
    <aura:if isTrue="{!v.showSpinner}">
        <lightning:spinner />
    </aura:if>
    <div class="slds-box slds-theme_default">
        <div class="slds-text-title_bold">Updates the status to closed and closes the primary tab</div>
        <lightning:recordEditForm aura:id="recordEditor"
                                  onload="{!c.handleLoad}"
                                  onsubmit="{!c.handleSubmit}"
                                  onsuccess="{!c.handleSuccess}"
                                  recordId = "{!v.recordId}"
                                  objectApiName="Case">
            <lightning:messages />
            <lightning:inputField fieldName="Fault_Category__c" disabled="true" />
            <lightning:inputField fieldName="Fault_Type__c" />
            <lightning:inputField fieldName="Solution__c" />
            <lightning:inputField fieldName="Solution_Details__c" />
            <div class="slds-m-top_medium">
                <lightning:button aura:id="button1" value="value1" variant="brand" type="submit" name="save" label="Close Case and Tab" />
                <lightning:button aura:id="button2" value="value2" variant="brand" type="submit" name="save2" label="Close Case" />
            </div>
        </lightning:recordEditForm>
    </div> 
</aura:component>
This is the controller
({
    handleLoad : function(component, event, helper) {
        console.log('handle handleLoad');
        component.set("v.showSpinner", false);
    },
    
    handleSubmit : function(component, event, helper) {
        event.preventDefault(); // Prevent default submit
        var fields = event.getParam("fields");
        fields["Status"] = 'Hold';        
        component.find('recordEditor').submit(fields); // Submit form
        console.log('handle handleSubmit');
    },
    
    handleSuccess : function(component, event, helper) {
        console.log('record updated successfully');
        //The below is returning the id of the Lighting:recordEditForm 
        console.log(event.getSource().getLocalId());
        component.set("v.showSpinner", false);
        // Success! Prepare a toast UI message
        var resultsToast = $A.get("e.force:showToast");
        resultsToast.setParams({
            "title": "Case Saved",
            "message": "The case has been closed"
        });
        resultsToast.fire();
        
        //Below should only fire if a specific lighting button was pressed
        var workspaceAPI = component.find("workspace");
        console.log('closing tab');
        workspaceAPI.getFocusedTabInfo().then(function(response) {
            var focusedTabId = response.tabId;
            workspaceAPI.closeTab({tabId: focusedTabId});
        })
        .catch(function(error) {
            console.log(error);
        });
    }
})
I have highlighted the commented code in bold in the controller where I need to reference the button that was clicked

Any help would be much appreciated

 
I was hoping someone could explain to me why the below trigger is working.
My test class for the below trigger is failing, which I understand why. Roll Up summaries are calculated once the after trigger has run, so in my before tiggers the values have not yet been updated.
What I don't understand though is why the trigger is working though.
The field 'Hardware_Maintenance_Total__c' is a formula field based on a roll up summary and 2 standard currency field.
The trigger simply increments the 'Change_Revision__c'  value by 1 if the hardware total is changed

Method called by before trigger
private void updateChangeRevision(Map<ID, Opportunity> oldOppsMap, Opportunity[] opps)
    {
        for(Opportunity opp : opps)
        {
            Opportunity oldOpp = oldOppsMap != null ? oldOppsMap.get(opp.Id) : null;
            system.debug('New Hardware maintenance total = ' + opp.Hardware_Maintenance_Total__c + 
                             ' Old Hardware maintenance total = ' + oldOpp.Hardware_Maintenance_Total__c);
            if(oldOpp != null &&
               opp.Hardware_Maintenance_Total__c != oldOpp.Hardware_Maintenance_Total__c)
            {
                opp.Change_Revision__c = opp.Change_Revision__c != null ? opp.Change_Revision__c +1 : 1;
            }     
        } 
    }

Debug when ran changing values in the record page itself
11:12:40.3 (61046491)|USER_DEBUG|[90]|DEBUG|New Hardware maintenance total = 43.72 Old Hardware maintenance total = 21.33

Debug when running test class
11:44:29.779 (7880532817)|USER_DEBUG|[78]|DEBUG|New Hardware maintenance total = 21.33 Old Hardware maintenance total = 21.33

As I say, I understand why the test class is failing, the roll up summaries will not have been calculated as yet, so the formula field I am checking 'Hardware_Maintenance_Total__c' will not have been updated at that point.
So why is the trigger actually working?

Many thanks
I have a VF page which uses a lightning component to call a flow(checks and decisions are made in the flow to determine if the asset should be deleted) to delete an asset. Depending on whether the user is in Classic or a console view the behaviour should be different. I use an identical page to delete a case rather than an asset and it works perfectly.
However when the asset is deleted. the flow appears to be called again. I'm getting the following error via email
Flow Details
Flow API Name: Delete_Asset
Type: Screen Flow
Version: 1
Status: Active
Org: CRB Cunninghams (00Db0000000eIN5)
Flow Interview Details
Interview Label: Delete Asset 18/03/2019 10:27
Current User: Louisa Barrett (005b0000003IbLU)
Start time: 18/03/2019 10:27
Duration: 0 seconds
How the Interview Started
Louisa Barrett (005b0000003IbLU) started the flow interview.
Some of this flow's variables were set when the interview started.
AssetID = 02i0J00000XVygLQAT
FAST LOOKUP: GetAsset
Find all Asset records where:
Id Equals {!AssetID} (02i0J00000XVygLQAT)
Assign those records to {!Asset}.
Save these field values in the variable: Id, Name, Added_to_Service_Contract__c, Service_Contract__c, Service_Contract_Status__c, Service_Contract_Start_Date__c, Service_Contract_End_Date__c, AccountId
Result
Failed to find records.
________________________________________
Salesforce Error ID: 624516304-414064 (-1789764336)

This is my VF page that calls the flow
<apex:page standardController="Asset" lightningStylesheets="true" >
<!-- Orignal method to call flow -->
<!--<flow:interview name="Delete_Asset"

finishLocation="/{!Asset.AccountID}">

<apex:param name="AssetID" value="{!Asset.Id}"/>

</flow:interview>-->
    
  <apex:includeScript value="/support/console/40.0/integration.js"/>
    <html>
        <head>
            <apex:includeLightning />
        </head>
        <body class="slds-scope">
            <div id="flowContainer" />
            <script type="text/javascript">
            var returnID = "{!Asset.Account.Id}";
            var statusChange = function (event) 
            {
                console.log('Status change = ' + event.getParam("status"));
                if(event.getParam("status") === "FINISHED") 
                {
                    // Use my return Id to open a tab
                    if (sforce.console.isInConsole())
                    {
                        sforce.console.getEnclosingTabId(closeSubtab);
                        sforce.console.getFocusedPrimaryTabId(refreshPrimaryTab);
                    }
                    else
                    { 
                        window.parent.location = '/' + returnID; 
                    }
                }
            };
            $Lightning.use
            ("c:TestLightningApp2", function()
             {
                 // Create the flow component 
                 console.log('function called');
                 $Lightning.createComponent("lightning:flow", 
                                            {"onstatuschange":statusChange},
                                            "flowContainer",
                                            function (component) 
                                            {
                                                // Set my input variables
                                                var inputVariables =
                                                    [
                                                        {
                                                            name : 'AssetID',
                                                            type : 'String',
                                                            value : '{!Asset.Id}'
                                                        }
                                                    ];
                                                // Start the flow and pass in the input variables
                                                component.startFlow("Delete_Asset", inputVariables);
                                            }
                                           );
             }
            );                       
            var closeSubtab = function closeSubtab(result)
            {
                var tabId = result.id;
                sforce.console.closeTab(tabId);
            }
            var refreshPrimaryTab = function getTabId(result)
            {
                var tabId = result.id;
                sforce.console.refreshPrimaryTabById(tabId, true);
            }
            </script>
        </body>
    </html>
</apex:page>

If I use the original method to call the flow(commented text at the top of the page' it works fine.

Any help would be much appreciated
I need to get a collection variable from a flow and then pass it to another vf page.
The problem is the constructor is being called again and causing the flow variable to be null. I have set the redirect to be false, but this doesn't seem to be making any difference.
If I remove the flow aspect from the page, it works fine.
I've copied in the extension class and the two visual force pages.
Does anyone know if this is possible when calling a flow from the first page?

Extention class:
public class DeliveryNoteFlowController 
{
    private final Opportunity myOpp;
    
    public DeliveryNoteFlowController(ApexPages.StandardController stdController) {
        this.myOpp = (Opportunity)stdController.getRecord();
        system.debug('Opp ID = ' + myOpp.Id);
    }
    
    public Flow.Interview.DeliveryNote myflow { get; set; }
      
    public List<OpportunityLineItem> getMyOLIs() 
    {
        if (myflow == null) 
        { 
            system.debug('Flow is null');
            return null; 
        }
        else 
        {
            system.debug('OLI count = ' + myFlow.SelectedOLIs.Size());
            return (List<OpportunityLineItem>)myflow.SelectedOLIs;       
        }
    }
    
    public PageReference getFinishLocation()
    {
        PageReference pgr = Page.DeliveryNote3;      
        pgr.setRedirect(true);
        return pgr;
    }  
}
VF page that launches flow:
<apex:page standardController="Opportunity" extensions="DeliveryNoteFlowController">    
    <flow:interview name="DeliveryNote" interview="{!myFlow}" finishLocation="{!FinishLocation}">
        <apex:param name="OppId" value="{!Opportunity.id}"/>
    </flow:interview>
</apex:page>

 VF page(DeliveryNote3) that is called for the finish location. This page renders as a pdf:
<apex:page standardController="Opportunity" extensions="DeliveryNoteFlowController" standardStylesheets="false" applyHtmlTag="false" sidebar="false" readOnly="true" showHeader="false" renderAs="pdf">
    <head>
        <style type="text/CSS">
            body{
            font-family:"Verdana",Helvetica,Arial,sans-serif;         
            }
            
            .table-bordered {
            border: 1px solid #A9A9A9;
            border-collapse : collapse;
            font-size : .7em;
            border-width: thin;
            }
            
            .table-noborder {
            border: 0;
            font-size : .7em;
            }
            
            thead>tr>th {
            vertical-align: bottom;
            border: 1px solid #202d79;
            border-spacing: 0;
            text-align:left;
            border-collapse: collapse;
            background : #202d79;
            color:white;
            }
            
            .td-noborder {
            vertical-align: bottom;
            border:0 ;
            border-spacing: 0;
            border-collapse: collapse;
            text-align:left;
            width:50%;
            }
            
            td {
            vertical-align: center;
            border: 1px solid #A9A9A9;
            border-spacing: 0;
            border-collapse: collapse;
            text-align:left;
            }
            
            .header>td{
            font-weight:bold;
            background : #c4c4c4;               
            }
            
            .echoArea>td{
            padding:10px;
            }
        </style>
    </head>
    <body>
        <img src="{!$Resource.Logo}" alt="Our Logo" align="right" width="250" height="50"/>
        <header>
            <h2>Delivery note for <br/> {!Opportunity.Account.Name}</h2>
            {!myOppName}
            {!myOpp}
        </header>
        <p>Details</p>
        <table width="100%" class="table-noborder">               
                <tr>
                    <td class="td-noborder">Delivery Note No: {!Opportunity.Opportunity_External_ID__c}</td>                
                    <td class="td-noborder" width="15%" align="left">
                           Install Date: <apex:outputField value="{!Opportunity.Install_Date__c}"/>
                    </td>
                </tr>
                <tr>
                <td class="td-noborder">Project Manager: {!Opportunity.Project_Manager__c}</td>
                <td class="td-noborder" width="15%" align="left"></td>
                </tr>
                <tr>
                    <td class="td-noborder">Address:<br/>{!Opportunity.Account.BillingStreet}<br/>{!Opportunity.Account.BillingCity}<br/>{!Opportunity.Account.BillingState}<br/>{!Opportunity.Account.BillingPostalCode}</td> 
                    <td class="td-noborder"></td>
                </tr>                          
        </table>       
        <p>Products</p>
        <table width="100%" class="table-bordered">
            <thead>               
                <tr>
                    <th>Product</th><th>Quantity</th>
                </tr>
                <apex:repeat var="oli" value="{!MyOLIs}" >
                     <tr>
                        <td align="left">{!oli.Name}</td>
                        <td align="left">{!FLOOR(oli.Quantity)}</td>
                    </tr>                  
                </apex:repeat>
            </thead>
        </table>
        <br/>
        <table width="100%" class="table-noborder">
            <tr>
                <td class="td-noborder">Placeholder text

                </td>
            </tr>
        </table>
		 <br/>
        <p>Received by</p>
        <p>
            <i>Signature__________________________________________________</i><br/> 
            <br/>
            <i>Print name_________________________________________________</i>
        </p>
        <p>
            Date______________________________________________________        
        </p> 
          
    </body>
</apex:page>

Many thanks for any assistance
 
I have a custom tab that displays a lighning component which on a click event allows a user to edit a record.
I am trying to listen for a save success on the e.force:editRecord and after much searching I found no solution as apparently there is no standard callback for the editRecord
https://trailblazer.salesforce.com/ideaView?id=0873A000000CQQiQAO
As per a few other suggestions I have added an handler for the force:showToast
This is working, albeit a hack, but the problem is as this is an application event it is constantly being listened for even if the custom tab isn't open.
Does anyone have any ideas how I can remedy this
<aura:handler event="force:showToast" action="{!c.handleToastEvent}"/>



handleToastEvent: function(component, event, helper){
        var toastMessageParams = event.getParams();
        var message = toastMessageParams.message;
        if(message.includes('Resource Placeholder') && message.includes('was saved')){
            var calendar = component.get('v._Calendar');
            var calendarEvent = event.getParam("calendarEvent")
            helper.fetchCalendarEvents(component, calendar, calendarEvent);
        }
    }

Many thanks,
Hi,
This is my first time using the @future annotation and was wondering if I could get some guidance.
I have a trigger on the contact, which is handled by a handler class. When a contact is deleted, I need to perfom a call out, so within the handler class I need to call a future method to perform that call out. As a future method only takes primitive data types, I have created another method which passes just the IDs to the future method. Is this the correct way to do this, or is there a better way?
I'm also a little concerned what happens if a mass delete is performed. How do you bulkify call outs?

Trigger:
trigger ContactTrigger on Contact (before delete, before insert, before update, after delete, after insert, after update) 
{
    ContactTriggerHandler handler = new ContactTriggerHandler(Trigger.isExecuting, Trigger.size);
    
    if (Trigger.isInsert && Trigger.isBefore)
    {
        handler.OnBeforeInsert(Trigger.new);       
    }
    else if (Trigger.isInsert && Trigger.isAfter)
    {
        handler.OnAfterInsert(Trigger.new, Trigger.newMap);
    }
    else if (Trigger.isUpdate && Trigger.isBefore)
    {
        handler.OnBeforeUpdate(Trigger.old, Trigger.oldmap, Trigger.new, Trigger.newmap);
    }
    else if (Trigger.isUpdate && Trigger.isAfter)
    {
        handler.OnAfterUpdate(Trigger.old, Trigger.oldmap, Trigger.new, Trigger.newmap);
    }
    else if(Trigger.isDelete && Trigger.isBefore)
    {
        handler.onBeforeDelete(trigger.old, trigger.oldMap);
    }
    else if(Trigger.isDelete && Trigger.isAfter)
    {
        handler.onAfterDelete(trigger.old, trigger.oldMap);
    }
}

Trigger handler class:
public class ContactTriggerHandler extends BaseTriggerHandler
{
    public ContactTriggerHandler(boolean isExecuting, integer size)
    {
        super(isExecuting, size);
    }
    
    public void OnBeforeInsert(Contact[] newContacts) 
    {}     
    
    public void OnAfterInsert(Contact[] newContacts, Map<ID, Contact> newContactsMap) 
    {}
    
    public void OnBeforeUpdate(Contact[] oldContacts, Map<ID, Contact> oldContactsMap, Contact[] updatedContacts, Map<ID, Contact> updatedContactsMap)
    {}
    
    public void OnAfterUpdate(Contact[] oldContacts, Map<ID, Contact> oldContactsMap, 
                              Contact[] updatedContacts, Map<ID, Contact> updatedContactsMap)
    {}
    
    public void OnBeforeDelete(Contact[] oldContacts, Map<ID, Contact> oldContactsMap)
    {}
    
    public void OnAfterDelete(Contact[] oldContacts, Map<ID, Contact> oldContactsMap)
    {
        passIDsToCallOut(oldContactsMap);
    }

    Private void passIDsToCallOut(Map<ID, Contact> contactsMap)
    {
        Set<Id> conIds = contactsMap.keySet();
        system.debug('con Ids for forget request');
        system.debug(conIds);
        sendForgetRequestGDPR(conIds);
    }
    
    @future(callout=true)
    Public static void sendForgetRequestGDPR(Set<id> contactIds)
    {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://****.com/api/auth/v1/login?email=myemail@email.co.uk&password=myPassword');
        request.setMethod('POST');
        request.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        request.setHeader('Accept', 'application/json');
        HttpResponse authResponse = http.send(request);
        if (authResponse.getStatusCode() == 200) {
            system.debug('got auth!');
            // Deserialize the JSON string into collections of primitive data types.
            Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(authResponse.getBody());
            List<Object> myresults = new List<Object>();
            for(Object obj : results.values())
            {
                myresults.add(obj);
            }
            string sessionId = string.ValueOf(myresults[0]);
            system.debug('session Id = ' +sessionId);
            request = new HttpRequest();
            request.setEndpoint('https://*****.com/api/v1/services/*****/gdpr/forget');
            request.setMethod('POST');
            request.setHeader('Content-Type','application/x-www-form-urlencoded');
            request.setHeader('Accept','application/json');
            request.setHeader('X-SESSION-ID',sessionId); 
            string comment = 'API Call';
            string contactId;
            for(Id conId : contactIds)
            {
                contactId = conId;
                request.setBody('record_id='+contactId+'&table_name=Contact&comment=' + EncodingUtil.urlEncode(comment, 'UTF-8'));
                system.debug(request);
                HttpResponse forgetResponse = http.send(request);
                if(forgetResponse.getStatusCode() == 200)
                {
                    system.debug('got GDPR!');
                }
                else
                {
                    system.debug('Forget Broken =' + forgetResponse.getStatusCode());
                }           
            }       
        }
        else
        {
            system.debug('Auth Broken =' + authResponse.getStatusCode());
        } 
    }
}

Many thanks
 
Hi All,

I have a recordEditForm on an Aura component which displays the core fields from the case object. 
My issue is I need the standard description field to automatically expand it's height to show all the content, like it does on the detail page.
Currently I get scoll bars and the ability to drag the box to expose the text.
Is it possible with a lightning:inputfield?
 
<div class="slds-grid slds-wrap">
                        <div class="slds-col slds-size_1-of-1">
                            <lightning:inputField fieldName="Description" onchange="{!c.enableButtons}"/>
                        </div>
                    </div>

 
Hi All,
Currently I see the following sub tabs in Chatter feed.
 'All Updates', 'Emails','Call Logs', 'Text Posts', 'Status Change'

User-added image
Is there a way to supress some of the tabs .e.g supress 'Call Logs' tab ?

Regards,
Avinash
Hi All,

I am fairly new to lightning components and am struggling to get a datatbale to show any server side errors. I have looked at the documentation (Salesforce Documention (https://developer.salesforce.com/docs/component-library/bundle/lightning:datatable/example#lightningcomponentdemo:exampleDatatableInlineEdit) )and tried to implement it to my scenario but cannot get it to work.
This is my code:

Component:
<aura:component controller="BuildUpChecklistController" implements="force:appHostable,flexipage:availableForRecordHome,force:hasRecordId">
	<aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    <aura:handler event="force:refreshView" action="{!c.doInit}"/>
    <aura:attribute name="mydata" type="Object"/>
    <aura:attribute name="mycolumns" type="List"/>
    <aura:attribute name="errors" type="Object" default="[]"/>
    <aura:attribute name="draftValues" type="Object" default="[]"/>
    <aura:attribute name="listSize" type="Integer" default="0"/>
    
    <!--User List Table-->
    <div class="slds-m-top--none slds-box slds-theme_default" >
        <div class="slds-align_absolute--left">
            <div class="slds-text-heading_small slds-text-color_default">       
                Update build notes and on site fields
                <lightning:helptext content="Help!"/>
            </div>
        </div>
        <lightning:datatable data="{! v.mydata }" 
                             columns="{! v.mycolumns }"
                             showRowNumberColumn= "true"
                             wrapTextMaxLines="3"
                             keyField="Id" 
                             errors="{!v.errors}"
                             draftValues="{!v.draftValues}"
                             onsave="{!c.handleSaveEdition}"/>
    </div>
</aura:component>

Controller:
handleSaveEdition: function (component, event, helper) {
        var draftValues = event.getParam('draftValues');
        var action = component.get("c.updateOLIs");
        action.setParams({"OLIs" : draftValues});
        action.setCallback(this, function(result){
            var state = result.getState();
            if(state === "SUCCESS"){
                    component.set("v.errors", []);
                    component.set("v.draftValues", []);
                    var toastEvent = $A.get("e.force:showToast");
                    toastEvent.setParams({
                        "title": "Success",
                        "message": "The opportunity line items have been updated",
                        "type" : "success"
                    });
                    toastEvent.fire();
                    $A.get('e.force:refreshView').fire();
                //}              
            } else if(state === "ERROR"){
               //I don't know what to use here to display any server side errors 
               //on the relevant rows of the datatable
               //
            } else if (status === "INCOMPLETE"){
                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                    "title": "Error!",
                    "message": "'No response from server or client'",
                    "type" : "error"
                });
                toastEvent.fire();
                $A.get('e.force:refreshView').fire();
            }
        });
        $A.enqueueAction(action);
    },

Apex Controller:
(I'm not doing any validation in this method at the moment, but I will)
 
@AuraEnabled
    public static void updateOLIs(List<OpportunityLineItem> OLIs)
    {
        update OLIs;
    }

Any help would be much appreciated,
Thank you​​​​​​​
I have a custom tab that displays a lighning component which on a click event allows a user to edit a record.
I am trying to listen for a save success on the e.force:editRecord and after much searching I found no solution as apparently there is no standard callback for the editRecord
https://trailblazer.salesforce.com/ideaView?id=0873A000000CQQiQAO
As per a few other suggestions I have added an handler for the force:showToast
This is working, albeit a hack, but the problem is as this is an application event it is constantly being listened for even if the custom tab isn't open.
Does anyone have any ideas how I can remedy this
<aura:handler event="force:showToast" action="{!c.handleToastEvent}"/>



handleToastEvent: function(component, event, helper){
        var toastMessageParams = event.getParams();
        var message = toastMessageParams.message;
        if(message.includes('Resource Placeholder') && message.includes('was saved')){
            var calendar = component.get('v._Calendar');
            var calendarEvent = event.getParam("calendarEvent")
            helper.fetchCalendarEvents(component, calendar, calendarEvent);
        }
    }

Many thanks,
Hello,

I have created a trigger on the Order object that works fine. But I am not able to get any coverage of my trigger with my test class.
Even though I wrote a test class; the coverage of my trigger remains at 0%
Could someone tell me what am I doing wrong?
Thanks

Trigger:
 
trigger UpdateAccountCA on Order (after update) {
	
    Map<Id, Decimal> mAccAmount = new Map<Id, Decimal>();
    
    //Iterate through each Order 
    for(Order o : Trigger.new) {
        if(mAccAmount.containskey(o.accountid)) {
          Decimal d = mAccAmount.get( o.AccountId );
          System.debug('Decimal value ' +d);
          d += o.TotalAmount;

          mAccAmount.put( o.AccountId, d );  
            
        } else {
            mAccAmount.put( o.AccountId, o.TotalAmount );

        }
        
    }
    List<Account> lAccs = [SELECT Id, Chiffre_d_affaire__c FROM Account WHERE Id = :mAccAmount.keySet()];
	System.debug('Account Keyset: ' +mAccAmount.keySet());
    
    //Iterate through each List of Accounts 
    if(lAccs.size()>0) {
        for(Account acc : lAccs){
            acc.Chiffre_d_affaire__c = acc.Chiffre_d_affaire__c + mAccAmount.get(acc.Id);  
        }
    }
    update lAccs;  
}

Test class:
 
@isTest
public class UpdateAccountCATest {
    
    @isTest static void test() {
        Account acc1 = new Account(Name = 'Test Account 1');
        insert acc1;
      
        Id pricebookId = Test.getStandardPricebookId();
        
        Product2 pd1 = new Product2(Name = 'Chemise Verte longue XYX', Family = 'Chemise');
        Insert pd1;
 
        //Create the PricebookEntry
        PricebookEntry standardPrice = new PricebookEntry();
            standardPrice.Pricebook2Id = pricebookId;
            standardPrice.Product2Id = pd1.Id;
            standardPrice.UnitPrice = 1020;
            standardPrice.IsActive = true;
        	standardPrice.UseStandardPrice = false;
        
        Insert standardPrice;

        Order o1 = new Order(AccountId = acc1.Id, EffectiveDate=date.today(), Status='Draft', Pricebook2Id = pricebookId);
        insert o1;

        OrderItem oi1 = new OrderItem (OrderId = o1.Id, PricebookEntryId = standardPrice.Id, Quantity=10, UnitPrice = 150);
        insert oi1;
        OrderItem oi2 = new OrderItem (OrderId = o1.Id, PricebookEntryId = standardPrice.Id, Quantity=20, UnitPrice = 1000);
        insert oi2;        
    }
 
}

 
Hi,

I have a table with horizontal and vertical scroll bars and would like to lock the column headers when scrolling in either direction.
 
<lightning:layoutItem size="12" padding="around-small"><b>Work Orders</b>
        <div class="external-events slds-table--header-fixed_container" style="height:20rem;">
            <div class=" slds-scrollable " style="height:100%;">
                <table class="slds-table slds-table_bordered slds-table_cell-buffer slds-table--header-fixed">
                    <thead>
                        <tr>
                            <th scope="col">
                                <div class="slds-cell-fixed">WO#</div>
                            </th>
                            <th  scope="col">
                                <div class="slds-cell-fixed">Account</div>
                            </th>
                            <th scope="col">
                                <div class="slds-cell-fixed">Postcode</div>
                            </th>
                            <th scope="col">
                                <div class="slds-cell-fixed">Status</div>
                            </th>
                            <th scope="col">
                                <div class="slds-cell-fixed" >Subject</div>
                            </th>
                        </tr>
                    </thead>
                    <tbody>
                        <aura:iteration items="{!v.woList}" var="item">
                            <tr>
                                <td>
                                    <div class="{!'fc-event ' + item.className}" 
                                         data-id="{!item.id}"
                                         data-tag="{!item.tag}"
                                         onclick="{!c.handleClick}">{!item.WorkOrderNumber}   
                                    </div>
                                </td>
                                <td> 
                                    <div>{!item.accountName}</div>
                                </td>
                                <td> 
                                    <div>{!item.postcode}</div> 
                                </td>
                                <td> 
                                    <div>{!item.Status}</div>
                                </td>
                                <td>
                                    <div>{!item.Subject}</div>
                                </td>                            
                            </tr>
                        </aura:iteration>
                    </tbody>
                </table>
            </div>
        </div> 
    </lightning:layoutItem

At the moment it's scrolling ok, and when you scroll vertically the headers are fixed, but the column headers do not move when scrolling horizontally. I'm guessing it's because of the slds-cell-fixed, but I'm not sure what to change it to.
Any help would be much appreciated
Does anyone know how to close a workspace(primary) tab and it's sub tabs?
The below only returns the subtab. I need to close the primary and any subtabs.
var workspaceAPI = component.find("workspace");
workspaceAPI.getEnclosingTabId().then(function(tabId) {
                    var enclosingTabId = tabId;
                    workspaceAPI.closeTab({tabId: enclosingTabId});
                })
Many thanks
 
I wanted to check if this is a known issue. On saturday our instance was upgraded to Summer 19, and on monday we started seeing Apex CPU time Limit Exceeded error on one of our objects.

Could someone let me know if they are aware of the issue.

Thanks
Ravi
Hi,
I have a vf page which has several page block tables on all with inline edit support enabled. Within the tables there are controlling(Product_Category__c) and dependent(Make__c) picklists. My issue is that the the controlling picklist has a FLS of read only as it is set via a trigger, when I put this field onto the vf page, I get the error of 'The inline edit-enabled dependent picklist 'Make' requires its controlling field 'Product Category' to be present on the page.' when a profile other than system admin views the page. If I remove the read only flags from the FLS and set it at a page layout level, the user can then view the vf page, but the controlling field becomes editable.
Does anyone have any suggestions how I can get around this?

This is my vf page.  I have several pageblocktables within the page, but I've removed all but one for ease of reading.

Many thanks for any help
<apex:page standardController="Account" extensions="SiteSurvey"> 
    <apex:form >        
        <apex:pageBlock id="Block1" title="Active assets for {!Account.Name}" >
            <apex:panelGrid columns="2">
                <apex:commandButton value="View as PDF" action="{!printAsPDF}"/>
                <apex:commandButton value="View as xls" action="{!printAsXLS}"/>
            </apex:panelGrid>
            <apex:pageBlockButtons >
                <apex:commandbutton value="Save" action="{!updateAssets}" id="saveButton" style="display:none"/>
                <apex:commandButton value="Cancel" action="{!cancelAssets}" id="cancelButton" style="display:none"/>
            </apex:pageBlockButtons>
            
            <apex:pageBlockSection id="tsSection" collapsible="true" title="Touchscreens [{!TouchscreenAssets.size}]" columns="1" rendered="{!TouchscreenAssets.size >0}" >
                <apex:pageBlockTable value="{!TouchscreenAssets}" var="a" style="table-layout:fixed">
                    <apex:column headerValue="Asset Name:">
                        <apex:outputLink value="/{!a.ID}" target="_blank">
                            {!a.Name}
                        </apex:outputLink>
                    </apex:column>
                    <apex:column headerValue="Contract Status">
                        <apex:outputField value="{!a.Service_Contract_Status__c}"/>
                    </apex:column>                 
                    <apex:column headerValue="Category">
                        <apex:outputField value="{!a.Product_Category__c}" />
                    </apex:column>
                    <apex:column headerValue="Make" >
                        <apex:outputField value="{!a.Make__c}"/>
                    </apex:column>
                    <apex:column headerValue="Model" >
                        <apex:outputField value="{!a.Model__c}"/>
                    </apex:column>
                    <apex:column headerValue="OS" >
                        <apex:outputField value="{!a.Operating_System__c}"/>
                    </apex:column>
                    <apex:column headerValue="Location #" >
                        <apex:outputField value="{!a.Location_Number__c}"/>
                    </apex:column>
                    <apex:column headerValue="IP" >
                        <apex:outputField value="{!a.IP_Address__c}"/>
                    </apex:column>
                    <apex:column headerValue="User Name" >
                        <apex:outputField value="{!a.User_Name__c}"/>
                    </apex:column>
                    <apex:column headerValue="Password" >
                        <apex:outputField value="{!a.Password__c}"/>
                    </apex:column>
                    <apex:column headerValue="Drawer" >
                        <apex:outputField value="{!a.Drawer_Type__c}"/>
                    </apex:column>
                    <apex:column headerValue="Network" >
                        <apex:outputField value="{!a.Network_Communication__c}"/>
                    </apex:column>
                    <apex:column headerValue="Comms" >
                        <apex:outputField value="{!a.Communication_Method__c}"/>
                    </apex:column>
                    <apex:column headerValue="Prox" >
                        <apex:outputField value="{!a.Prox_Type__c}"/>
                    </apex:column>
                    <apex:column headerValue="Desc" >
                        <apex:outputField value="{!a.Description}" style="white-space:normal"/>
                    </apex:column>
                    <apex:inlineEditSupport event="onClick" showOnEdit="saveButton, cancelButton"/>
                </apex:pageBlockTable>
            </apex:pageBlockSection>
            <script> 
            twistSection(document.getElementById('{!$Component.Block1.tsSection}').getElementsByTagName('img')[0])
            </script>
      </apex:pageBlock>
    </apex:form>
</apex:page>

 
Hi,

I would like to return a user ID and a list of custom objects that the user is the owner of using an inner select, but I don't know where to find the child relationship name for the custom object.

example:
List<User> owners = [SELECT ID, Name, 
                             (SELECT ID, Name, OwnerID, Month_Number__c
                              FROM Custom_Object__c)
                             FROM User
                             WHERE OwnerID IN : ownerIDs];

I basically want to end up with a map of <ID, List<Custom_Object__c>>(), where the ID is the user ID and the list is all the custom object records that the user is the owner of.
Normally I would just look on the object and get the child relationship name from there, but the user object does not show it's related objects.
Is this query possible from the user table?

Thanks
Hi,
I would like to add a select all option to a column(On_Site__c) that is bound to an outputfield on my VF page which is currently using inline editing
This is the page code:

<apex:page standardController="Build_Up_Checklist__c" extensions="BuildUpChecklist" showHeader="false" sidebar="false">
    <style type="text/css">
        .pbTitle {
        white-space: nowrap;
        }
    </style>
    <table width="98%" border="0" cellpadding="0" cellspacing="0">
        <tr><td align ="right"><a href="javascript:window.print();">Print</a></td></tr>
    </table>
    <apex:form>
        <apex:pageBlock title="Product list for: {!Build_Up_Checklist__c.Build_Up_Checklist_Opportunity__r.Name} - ({!Build_Up_Checklist__c.Opportunity_EDU__c})">
            <apex:outputPanel >
                <apex:commandbutton value="Save" action="{!updateOLIs}" id="saveButton" style="display:none"/>
                <apex:commandButton value="Cancel" action="{!cancelUpdateOLIs}" id="cancelButton" style="display:none"/>
            </apex:outputPanel>
            <apex:pageblocktable value="{!OppProducts}" var="oli">
                <apex:column value="{!oli.PriceBookEntry.Name}" />
                <apex:column value="{!oli.Product_Notes__c}" />
                <apex:column value="{!oli.Quantity}"/>
                <apex:column headerValue="On Site"> 
                    <apex:outputField value="{!oli.On_Site__c}">
                        <apex:inlineEditSupport showOnEdit="saveButton, cancelButton" event="ondblclick" />
                    </apex:outputField>
                </apex:column>
                <apex:column value="{!oli.Replacement__c}"/>             
            </apex:pageblocktable>
        </apex:pageBlock>
    </apex:form>
</apex:page>


The editing and saving is working as intended, but it would be nice if the user didn't have to check the 'On_Site__c' checkbox on each row.

Many thanks
 
Hello all,

I try to call a flow via a visualforce page. The flow is started from an Account (button and action), submitting the AccountID and simply creates a new object linked to this Accout. 
My goal is to go back to the Account page after the flow completed. It works in Salesforce classic, but not in Lighning and SF1. As soon as I click finish here, I am not redirected to the Account page, but the page just freezes. Only possibility is to click cancel then. 

Any suggestions from you?
Stefan

This is how my code looks like:

<apex:page standardController="Account">
<apex:variable var="getAccountId" value="{!Account.Id}"></apex:variable>
    <flow:interview name="Assessment" finishLocation="{!URLFOR('/'+getAccountId)}">
         <apex:param name="AccountID" value="{!Account.Id}"/>
    </flow:interview>
</apex:page>
I need to have lists refresh when a new record is added. I would think that the Choose How Lists Refresh option and Push Notifications handle this, but that does not seem to work. Please help!