• Etienne DK
  • NEWBIE
  • 40 Points
  • Member since 2017

  • Chatter
    Feed
  • 1
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 4
    Questions
  • 14
    Replies
Hi Experts,

I need Basic Search functionality where i need to search for Users information with the help of Email Id or User Number or Bid Number only one search box has to be there and also if there are related information i need to throw an error.

Please help me out.

Thanks in advance
A lightning:recordForm component is showing old data.
The SF database definitely has fresher data, a SELECT confirms the server has newer data.
Destroying & re-creating the lightning:recordForm doesn't have an affect, it still shows old data. Refreshing the entire browser page does refresh the component.

On a high level there are two components. 
A parent accountManager that creates a child accountForm
The child accountForm contains the Lightning:recordForm and comms with an external server.
The child will detect when it needs to refresh and will emit an event, the parent handles the event by destroying the child and creates a new child.
This new child is the problem child, it keeps showing stale data. 

Any way to switch off caching, or refresh a recordForm component?

Parent Component
<!-- AccountManager.cmp -->
<aura:component controller='CRAccountGetService' 
                implements='flexipage:availableForRecordHome,force:hasRecordId,force:hasSObjectName' 
                access='global'>

    <!-- Attributes-->
    <aura:attribute name='recordId' type='string' default='{! v.recordId }' access='global' />
    <aura:attribute name='sObjectName' type='string' access='global' />

    <!-- Handlers -->
    <aura:handler name='init' value='{! this }' action='{! c.handleInit }' />
    <aura:handler name="refreshAccountForm" event="c:CRRefreshAccountForm" action='{! c.handleRefreshAccountForm }' />

    <!-- Screen -->
    <div>
      <!-- AccountForm dynamically injected here  -->
        {! v.body }
    </div>
</aura:component>

// AccountManagerController.js
({
    handleInit: function(component, event, helper) {
        helper.newAccountForm(component);
    },

    // handler for child component refresh event. Destroy & recreate account form component
    handleRefreshAccountForm: function(component, event, helper) {
        var eventMsg = event.getParam('message');
        helper.showToast('Account', eventMsg, 'error', 5000, 'sticky' );
        
        // destroy existing Account form child component
        var body = component.get("v.body");
        var arrayLength = body.length;
        for (var i = 0; i < arrayLength; i++) {
            body[i].destroy;
        }
        component.set('v.body',[]);

        // create new Account form child component
        var recId = component.get('v.recordId');
        $A.createComponent("c:AccountForm", { 'recordId': recId }, 
                            function (newAccountForm, status, errorMsg) {
                                if (status === "SUCCESS") {
                                    component.set("v.body", newAccountForm);
                                } else {
                                   // show error
                                }
                            });
    },
})

CHILD COMPONENT
<!-- AccountForm.cmp -->
<aura:component controller='CRAccountGetService' 
                implements='flexipage:availableForAllPageTypes, flexipage:availableForRecordHome, force:hasRecordId, force:hasSObjectName' 
                access='global' >

    <aura:handler name='init' value='{! this }' action='{! c.handleInit }' />

    <!-- Event to let parent (manager) know we need to be refreshed -->
    <aura:registerEvent name="refreshAccountForm" type="c:CRRefreshAccountForm" />
    <aura:attribute name='recordId' type='string' default='{! v.recordId }' access='global' />
    <aura:attribute name='mode' type='string' default='view' access='global' />

    <!-- Screen -->
    <lightning:messages />
    
    <lightning:recordForm 
        aura:id='accountForm' 
        objectApiName='Account'
        recordId='{! v.recordId }'
        layoutType='Full'
        columns='2'
        mode='{! v.mode }'
        onsuccess='{! c.handleSuccess }' 
    />
</aura:component>

// AccountFormController.js
({
    // After a successful save to SF database, call external service
    handleSuccess: function(component, event, helper) {
        helper.callExternalService(component, event, helper).then (
            // promise resolved: external server accepted data. SF database unchanged
            $A.getCallback(function () {
                helper.showToast('Account Save', 'All good', 'success', 1000);
            }),

            // promise rejected: external server rejected data and overwrote values in SF database, 
            // fire event so the Manager (the parent component) refreshes the form view
            $A.getCallback(function (message) { 
                var refreshMeEvent = component.getEvent("refreshAccountForm");
                refreshMeEvent.setParam("message", message);
                refreshMeEvent.fire();
            })
        );
    },
})
 
// AccountFormHelper.js
({
    callExternalService: function(component,event, helper) {
        return new Promise($A.getCallback(function(resolve, reject) {

            var externalService = component.get('c.callExternalService');
            externalService.setParams({
                'accountId': component.get('v.recordId')
            });

            externalService.setCallback(this, function(response) {
                if (response.getState() === "SUCCESS") {
                    var rspMsg = JSON.parse(response.getReturnValue());
                    if (rspMsg.success) {
                        resolve();
                    } else {
                        reject(rspMsg.message);
                    }
                } else {
                    reject('Controller failure:' + response.getState()); 
                }
            });
            $A.enqueueAction(externalService);
        }));
    },
})

 
Hi, I've spent a few hours trying to make this work so hopefully it's possible and it's my Google fu that is off.

I'm trying to navigate to a Lightning App Builder record page from a custom lightning component, the custom component errors saying it cannot find the component  c:My_App_Builder_Page​   (I've tried a few variations but no luck)
 
// helper
({
    navigateToAppBuilderPage : function(component, event, helper) {
        var recordId = component.get("v.recordId")

        var evt = $A.get("e.force:navigateToComponent");
        evt.setParams({
            componentDef: "c:My_App_Builder_Page",     //developer name in app builder
            recordId : recordId
            //componentAttributes :{ }
        });
        evt.fire();
    }
})

As background the custom component is used as a record view override, it does a callout and then tries to load the app builder page to show the record and related lists.

I would skip using the app builder page and use a custom component but I can't see how to programatically create a record page with related lists 


 
I'm trying to intercept a record save, grab the new values and do stuff (eg validation or a callout) before saving the record. 

As with most orgs we utilise on page layouts heavily, so they have to be leveraged in this solution.

Using force:recordData one can intercept the save but it does not support rendering, which means you can get the data before save but have to manually specify page layout fields (and security). Clearly not an option for orgs with multiple page layouts.

Using lightning:recordForm the page layouts (and security) are handled by the component (yay) but there is no way to access the field data, as per Page Layout, before save.  Unless I'm missing something?

I did a StackExchange writeup with code examples but no luck so am trying here...

Any ideas?

lightning:recordForm force:recordData lds lightning data service
Verify fails with "An update to a Battle Station record with Weapon Status of 'Fully Operational' failed to update the Project Status field with the value of 'Complete'."

I have stepped thru carefully numerous times now. I have deleted, re-created, re-logged etc and the error persists.  The Process works when I manually edit records.

I'm at a loss as to what to try?
Hello,
Hello, I'm working on the lightning version. I have lightning component opened by quick action.
The component displays the form for creating an object (X) from an opportunity.
The idea is to select the opportunity and the account linked to this opportunity and pass them directly into the object creation form (X). Do you have an idea?
A lightning:recordForm component is showing old data.
The SF database definitely has fresher data, a SELECT confirms the server has newer data.
Destroying & re-creating the lightning:recordForm doesn't have an affect, it still shows old data. Refreshing the entire browser page does refresh the component.

On a high level there are two components. 
A parent accountManager that creates a child accountForm
The child accountForm contains the Lightning:recordForm and comms with an external server.
The child will detect when it needs to refresh and will emit an event, the parent handles the event by destroying the child and creates a new child.
This new child is the problem child, it keeps showing stale data. 

Any way to switch off caching, or refresh a recordForm component?

Parent Component
<!-- AccountManager.cmp -->
<aura:component controller='CRAccountGetService' 
                implements='flexipage:availableForRecordHome,force:hasRecordId,force:hasSObjectName' 
                access='global'>

    <!-- Attributes-->
    <aura:attribute name='recordId' type='string' default='{! v.recordId }' access='global' />
    <aura:attribute name='sObjectName' type='string' access='global' />

    <!-- Handlers -->
    <aura:handler name='init' value='{! this }' action='{! c.handleInit }' />
    <aura:handler name="refreshAccountForm" event="c:CRRefreshAccountForm" action='{! c.handleRefreshAccountForm }' />

    <!-- Screen -->
    <div>
      <!-- AccountForm dynamically injected here  -->
        {! v.body }
    </div>
</aura:component>

// AccountManagerController.js
({
    handleInit: function(component, event, helper) {
        helper.newAccountForm(component);
    },

    // handler for child component refresh event. Destroy & recreate account form component
    handleRefreshAccountForm: function(component, event, helper) {
        var eventMsg = event.getParam('message');
        helper.showToast('Account', eventMsg, 'error', 5000, 'sticky' );
        
        // destroy existing Account form child component
        var body = component.get("v.body");
        var arrayLength = body.length;
        for (var i = 0; i < arrayLength; i++) {
            body[i].destroy;
        }
        component.set('v.body',[]);

        // create new Account form child component
        var recId = component.get('v.recordId');
        $A.createComponent("c:AccountForm", { 'recordId': recId }, 
                            function (newAccountForm, status, errorMsg) {
                                if (status === "SUCCESS") {
                                    component.set("v.body", newAccountForm);
                                } else {
                                   // show error
                                }
                            });
    },
})

CHILD COMPONENT
<!-- AccountForm.cmp -->
<aura:component controller='CRAccountGetService' 
                implements='flexipage:availableForAllPageTypes, flexipage:availableForRecordHome, force:hasRecordId, force:hasSObjectName' 
                access='global' >

    <aura:handler name='init' value='{! this }' action='{! c.handleInit }' />

    <!-- Event to let parent (manager) know we need to be refreshed -->
    <aura:registerEvent name="refreshAccountForm" type="c:CRRefreshAccountForm" />
    <aura:attribute name='recordId' type='string' default='{! v.recordId }' access='global' />
    <aura:attribute name='mode' type='string' default='view' access='global' />

    <!-- Screen -->
    <lightning:messages />
    
    <lightning:recordForm 
        aura:id='accountForm' 
        objectApiName='Account'
        recordId='{! v.recordId }'
        layoutType='Full'
        columns='2'
        mode='{! v.mode }'
        onsuccess='{! c.handleSuccess }' 
    />
</aura:component>

// AccountFormController.js
({
    // After a successful save to SF database, call external service
    handleSuccess: function(component, event, helper) {
        helper.callExternalService(component, event, helper).then (
            // promise resolved: external server accepted data. SF database unchanged
            $A.getCallback(function () {
                helper.showToast('Account Save', 'All good', 'success', 1000);
            }),

            // promise rejected: external server rejected data and overwrote values in SF database, 
            // fire event so the Manager (the parent component) refreshes the form view
            $A.getCallback(function (message) { 
                var refreshMeEvent = component.getEvent("refreshAccountForm");
                refreshMeEvent.setParam("message", message);
                refreshMeEvent.fire();
            })
        );
    },
})
 
// AccountFormHelper.js
({
    callExternalService: function(component,event, helper) {
        return new Promise($A.getCallback(function(resolve, reject) {

            var externalService = component.get('c.callExternalService');
            externalService.setParams({
                'accountId': component.get('v.recordId')
            });

            externalService.setCallback(this, function(response) {
                if (response.getState() === "SUCCESS") {
                    var rspMsg = JSON.parse(response.getReturnValue());
                    if (rspMsg.success) {
                        resolve();
                    } else {
                        reject(rspMsg.message);
                    }
                } else {
                    reject('Controller failure:' + response.getState()); 
                }
            });
            $A.enqueueAction(externalService);
        }));
    },
})

 
Hi Salesforce Community,

I created a test class that I believe should cover the trigger I created 100% but I'm only getting 64% coverage. I know I don't need 100% coverage to bring this trigger and class into my production but I'd like to figure this out.

Here is my code for my trigger:
trigger Renewal_PSM on Opportunity (after insert, after update) {

    Set<Id> oppIds = new Set<Id>();
    Map<Id,Id> oppIds2 = new Map<Id,Id>();
    List<Opportunity> opptoUpdate = new List<Opportunity>();
    
    for(Opportunity o : Trigger.new){
         if(o.Previous_Renewal_Opportunity__c != null)
              oppIds.add(o.Id);
              oppIds2.put(o.Previous_Renewal_Opportunity__c,o.Id);
    }
    
    for(Opportunity opp2: [Select Amount from Opportunity where Id in: oppIds2.keySet()])
    {
        if(opp2.Amount !=null && !checkRecursive.SetOfIDs.contains(opp2.Id))
        {
          Opportunity o1= new Opportunity();
          o1.id=oppIds2.get(opp2.Id);
          checkRecursive.SetofIDs.add(opp2.Id);
          o1.Previous_Renewal_Product_Sum_Amount__c =opp2.Amount;
          opptoUpdate.add(o1);
        }
    
    }

if(opptoUpdate.size()>0)
update opptoUpdate;
}

Here is the code for my test class:
@isTest
private class Test_Renewal_Product_Sum_Amount{
  
         
  static testMethod void test_OpportunityTrigger2(){
  
   Account account_Obj = new Account(Name = 'Name123');
    Insert account_Obj; 

   
    Opportunity opp = new opportunity(Name = 'Name321',Description='Testing', StageName = 'Prospecting',AccountId=account_Obj.Id, CloseDate = Date.today());
  Insert opp;
      
   
   
    Opportunity opportunity_Obj = new Opportunity(IsPrivate = false, Description='Testing', Name = 'Name198',AccountId=account_Obj.Id,StageName = 'Proposal', previous_Renewal_Opportunity__c=opp.id, CloseDate = Date.today());
    Insert opportunity_Obj;
      
      Opportunity opportunity_Obj2 = new Opportunity(IsPrivate = false, Description='Testing', Name = 'Name196',AccountId=account_Obj.Id,Amount=123456, StageName = 'Discovery', CloseDate = Date.today());
      
      Insert opportunity_Obj2;
      
      opp.previous_Renewal_Opportunity__c= opportunity_Obj2.Id;
      update opp;
  
  }
}

Thanks,
Liz
Hi Experts,

I need Basic Search functionality where i need to search for Users information with the help of Email Id or User Number or Bid Number only one search box has to be there and also if there are related information i need to throw an error.

Please help me out.

Thanks in advance
Hi, I've spent a few hours trying to make this work so hopefully it's possible and it's my Google fu that is off.

I'm trying to navigate to a Lightning App Builder record page from a custom lightning component, the custom component errors saying it cannot find the component  c:My_App_Builder_Page​   (I've tried a few variations but no luck)
 
// helper
({
    navigateToAppBuilderPage : function(component, event, helper) {
        var recordId = component.get("v.recordId")

        var evt = $A.get("e.force:navigateToComponent");
        evt.setParams({
            componentDef: "c:My_App_Builder_Page",     //developer name in app builder
            recordId : recordId
            //componentAttributes :{ }
        });
        evt.fire();
    }
})

As background the custom component is used as a record view override, it does a callout and then tries to load the app builder page to show the record and related lists.

I would skip using the app builder page and use a custom component but I can't see how to programatically create a record page with related lists 


 
Hello - I am looking for an approach to create a List View button in LEX where once it is clicked it will create a record in the bacground with few fields auto-populated and open up the detail page of this record.
Ex., In the below screenshot - currently the 'New' button on the 'Case' page opens up a popup to select the record type and then in the next page displays fields to manually enter the value and once it is saved it opens up the detail page. We would like to automate this process by displaying another button something called 'Quick New' then in the background creates a record with recordtype and few other fields like Origin, description etc., and then opens up the detail record of it. 
Any suggestions on this please.

User-added image

 
I'm trying to intercept a record save, grab the new values and do stuff (eg validation or a callout) before saving the record. 

As with most orgs we utilise on page layouts heavily, so they have to be leveraged in this solution.

Using force:recordData one can intercept the save but it does not support rendering, which means you can get the data before save but have to manually specify page layout fields (and security). Clearly not an option for orgs with multiple page layouts.

Using lightning:recordForm the page layouts (and security) are handled by the component (yay) but there is no way to access the field data, as per Page Layout, before save.  Unless I'm missing something?

I did a StackExchange writeup with code examples but no luck so am trying here...

Any ideas?

lightning:recordForm force:recordData lds lightning data service
I’m running into an issue with the new lightning:recordForm component available in Summer ’18 when more than one separately-rendered component uses the same method to retrieve a different list of fields.

Basic example: Let’s say you have one component
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId,force:hasSObjectName" access="global" >
    <aura:attribute name="recordId" type="String" />
   <aura:attribute name="fields" type="List" default="HomePhone,DoNotCall,Fax,HasOptedOutOfFax"/>
                    <lightning:recordForm 
                                      recordId="{!v.recordId}" 
                                      objectApiName="Contact" 
                                      fields="{!v.fields}"
                                      columns="2"/>
</aura:component>
Then there is an identical component with different fields:
<aura:attribute name="fields" type="List" default="Name,Phone,Email,HasOptedOutOfEmail"/>
You then put these on a lightning record page for your contacts and put them within your Tabs (or Accordion) component. If both components are placed in the same tab, they both render fine when that tab becomes active.

Here’s the issue. If I put them into different tabs, only the one in the first of the tabs that is opened renders properly. When you open the second tab, the recordForm component returns an error: “This record could not be loaded because it includes too many formula fields with complex formulas….”

Has anyone else tried this? Is this expected functionality? Is there a workaround?
Hello,

So i am trying to implement the "Infinite Scrolling to Load More Rows" in a datatable.  I am trying to implement the example found at https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/aura_compref_lightning_datatable.htm.  However there is a helper method called in the JS Controller called "fetchData" that is not there and i cant for the life of me make it myself.  I have tried everything.  Any help would be greatly appreciated.

Please see code below.

Component:
<aura:component controller="ContactController" implements="force:appHostable,flexipage:availableForAllPageTypes" access="global">
    <aura:attribute name="mydata" type="Object" />
    <aura:attribute name="mycolumns" type="List"/>
    <aura:attribute name="isLoading" type="Boolean" default="true"/>
    <aura:attribute name="contactId" type="Id" />
    <aura:attribute name="sortedBy" type="String" />
    <aura:attribute name="sortedDirection" type="String" /> 
    <aura:attribute name="enableInfiniteLoading" type="Boolean" default="true"/>
    <aura:attribute name="initialRows" type="Integer" default="10"/>
    <aura:attribute name="rowsToLoad" type="Integer" default="50"/>
    <aura:attribute name="totalNumberOfRows" type="Integer" default="300"/>
    <aura:attribute name="loadMoreStatus" type="String" default=""/>
    <aura:handler name="init" value="{! this }" action="{! c.init }"/>
    <div style="height: 500px">
        <lightning:datatable data="{! v.mydata}" 
                             columns="{! v.mycolumns }" 
                             keyField="id"
                             onsort="{!c.updateColumnSorting}"
                             sortedBy="{!v.sortedBy}"
                             sortedDirection="{!v.sortedDirection}"
                             enableInfiniteLoading="true"
                             onloadmore="{! c.loadMoreData }"/>
        
    </div>
    {! v.loadMoreStatus}
</aura:component>

JS Controller:

({
    init: function (cmp, event, helper) {

        var actions = [
            { label: 'Show details', name: 'show_details' },
            { label: 'Delete', name: 'delete' }
        ];
        cmp.set('v.mycolumns', [
            // Other column data here
            { type: 'action', typeAttributes: { rowActions: actions } }
        ]);
        cmp.set('v.mycolumns', [
            {label: 'Contact Name', fieldName: 'Name', type: 'string', sortable: 'true'},
            {label: 'Phone', fieldName: 'Phone', type: 'phone', sortable: 'true'},
            {label: 'Email', fieldName: 'Email', type: 'email', sortable: 'true'}
        ]);
        helper.getData(cmp);
    },
    
    getSelectedName: function (cmp, event) {
        var selectedRows = event.getParam('selectedRows');
        // Display that fieldName of the selected rows
        for (var i = 0; i < selectedRows.length; i++){
            alert("You selected: " + selectedRows[i].Name);
        }
    },
    
    handleRowAction: function (cmp, event, helper) {
        var action = event.getParam('action');
        var row = event.getParam('row');
        switch (action.name) {
            case 'show_details':
                alert('Showing Details: ' + JSON.stringify(row));
                cmp.set('v.contactId', row.Id);
                alert(cmp.get('v.contactId'));
                $A.util.removeClass(cmp.find("childDiv"),'toggle');
                $A.util.addClass(cmp.find("listDiv"),'toggle');
                var attribute1 = cmp.get('v.contactId');
                var childComponent = cmp.find('child');
                childComponent.reInit(attribute1);
                break;
            case 'delete':
                var rows = cmp.get('v.mydata');
                var rowIndex = rows.indexOf(row);
                rows.splice(rowIndex, 1);
                cmp.set('v.mydata', rows);
                break;
        }
    },
    
    //Client-side controller called by the onsort event handler
    updateColumnSorting: function (cmp, event, helper) {
        var fieldName = event.getParam('fieldName');
        var sortDirection = event.getParam('sortDirection');
        // assign the latest attribute with the sorted column fieldName and sorted direction
        cmp.set("v.sortedBy", fieldName);
        cmp.set("v.sortedDirection", sortDirection);
        helper.sortData(cmp, fieldName, sortDirection);     
        
        
    },
    
    loadMoreData: function (cmp, event, helper) {
        //Display a spinner to signal that data is being loaded
        event.getSource().set("v.isLoading", true);
        //Display "Loading" when more data is being loaded
        cmp.set('v.loadMoreStatus', 'Loading');
        helper.fetchData(cmp, cmp.get('v.rowsToLoad'))
            .then($A.getCallback(function (data) {
                if (cmp.get('v.mydata').length >= cmp.get('v.totalNumberOfRows')) {
                    cmp.set('v.enableInfiniteLoading', false);
                    cmp.set('v.loadMoreStatus', 'No more data to load');
                } else {
                    var currentData = cmp.get('v.mydata');
                    //Appends new data to the end of the table
                    var newData = currentData.concat(data);
                    cmp.set('v.mydata', newData);
                    cmp.set('v.loadMoreStatus', '');
                }
               event.getSource().set("v.isLoading", false);
            }));
    }
    
})

HELPER

This is where i need the help to come up with a helper method that is referenced in the JS controller.  THANK YOU!

 
Verify fails with "An update to a Battle Station record with Weapon Status of 'Fully Operational' failed to update the Project Status field with the value of 'Complete'."

I have stepped thru carefully numerous times now. I have deleted, re-created, re-logged etc and the error persists.  The Process works when I manually edit records.

I'm at a loss as to what to try?
I have completed the Lightning Process builder step and i have verified that it is working correctly ( the battle Station record has been changed to complete and it has post a message to chatter, but when I click the Verify Step button I get this error message:

"Step Not yet complete... here's what's wrong:
An update to a Battle Station record with Weapon Status of 'Fully Operational' failed to post a Chatter message to the record. Make sure that the process is configured correctly and that it is activated.
Note: you may run into errors if you've skipped previous steps."