function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Ananthanarayanan NemmaraAnanthanarayanan Nemmara 

Handle exceptions

Hi All,
Can someone please let me know how  i can change the error being displayed from Uncaught Action failed: c:salesOwnerChange$controller$submitSelected [Cannot read property 'length' of undefined] to some custom error message. I wanted to show an error when the submit for approval is clicked without any accounts being selected from the lightning component(which means slect list passed to update accounts would be null)
Below is my code:

CustomLookupcontroller.apxc:
public class customLookupController {
    @AuraEnabled
    public static List <sObject> fetchLookUpValues(String searchKeyWord, String ObjectName) 
    {
        system.debug('searchkeyword:::'+searchKeyWord);
        system.debug('ObjectName-->' + ObjectName);
        String searchKey = searchKeyWord + '%';
        
        List <sObject> returnList = new List <sObject> ();
      
        String sQuery =  'select id, Name from ' +ObjectName + ' where Name LIKE: searchKey order by createdDate DESC limit 5';
        List <sObject> lstOfRecords = Database.query(sQuery);
        system.debug('lstOfRecords:::'+ lstOfRecords);
        for (sObject obj: lstOfRecords) 
        {
            returnList.add(obj);
        }
        return returnList;
    }
    
    @AuraEnabled
    public static List<Account> ownerList(Id user)
    {
        List<Account> accList = [SELECT Name FROM Account WHERE OwnerId = :user ORDER BY Name asc];
        return accList;
    }
    
    @AuraEnabled
    public static void updateAccounts(List<Id> selectList, Id fromId, Id userId, String requestDate, String effectiveDate)
    {
        integer lstsize = selectList.size();
        if(lstsize!=0)
        {
         system.debug('its entering here'); 
        Change_Request__c req = new Change_Request__c();
        system.debug('fromId:::'+fromId);
        system.debug('userId:::'+userId);
        system.debug('selectList:::'+ selectList);
        system.debug('selectListSize:::'+selectList.size());
        List<Account> updateList = [SELECT Id, Name, To_Salesperson__c FROM Account WHERE Id in :selectList];
        List<User> fromUser = [select ManagerId from User where Id = :fromId];
        List<User> ToUser = [select ManagerId from User where Id = :userId];
        
        req.AccountForChange__c = '';
        for(Account acc : updateList)
        {
            system.debug('acc::' + updateList);
            req.AccountForChange__c = req.AccountForChange__c + acc.Name + '\n';
        }
        for(User acc1 : fromUser)
        {
            system.debug('acc1::' + fromUser);
            req.From_Salesperson_Manager__c = acc1.ManagerId ;
        }
        for(User acc2 : ToUser)
        {
            system.debug('acc2::' + ToUser);
            req.To_Salesperson_Manager__c = acc2.ManagerId  ;
        }
       
        Date reqt = Date.valueOf(requestDate);
        Date efft = Date.valueOf(effectiveDate);
        System.debug(reqt);
        System.debug(efft);
        
        req.RecordTypeId = '012f40000005PNY';
        req.To_Salesperson__c = userId;
        req.From_Salesperson__c = fromId;
        req.Status__c='Pending';
       
        req.Date_Requested__c = reqt;
        req.Effective_Date_of_Change__c = efft;
        insert req;
        }
}
    
    @AuraEnabled
    public static List<Account> ownerList2(Id account)
    {
        system.debug('account:::'+account);
        if(account==null)
        {
            List<Account> nullList = [SELECT Name FROM Account WHERE Broker__c = :null];
            return nullList;
        }
        else
        {
            List<Account> accList = [SELECT Name FROM Account WHERE Broker__c = :account ORDER BY NAME asc];
            return accList;
        }
    }
}

Lightning component:
<aura:component controller="customLookupController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global">
    <aura:attribute name="fromSalesperson" type="sObject" default="{}" />
    <aura:attribute name="toSalesperson" type="sObject" default="{}" />
    <aura:attribute name="searchResult" type="List" default="{}"/>
    <aura:attribute name="request" type="date" />
    <aura:attribute name="effective" type="date" />
 
    <table>
        <tr>
            <td style="padding:15px"><c:customLookup objectAPIName="user" IconName="standard:user" selectedRecord="{!v.fromSalesperson}" label="From Salesperson"/></td>
              <td style="padding:15px"><c:customLookup objectAPIName="user" IconName="standard:user" selectedRecord="{!v.toSalesperson}" label="To Salesperson"/></td> 
        </tr>
        <tr>
            <td style="padding:15px"><lightning:input aura:id="requestDate" value="{!v.request}" name="dateRequested" type="date" label="Date Requested"/></td>
            <td style="padding:15px"><lightning:input aura:id="effectiveDate" value="{!v.effective}" name="effectiveDateOfChange" type="date" label="Effective Date of Change"/></td>
        </tr>
    </table>
    
    <div style="padding:15px">
        <lightning:button name="submit" label="Search" onclick="{!c.submit}" />
    </div>
    
    <div style="padding-left:15px; padding-right:15px">
        <table class="slds-table slds-table--bordered slds-table--cell-buffer">
          <thead>
             <tr class="slds-text-title--caps">
                <th style="width:3.25rem;" class="slds-text-align--right">
                   <div class="slds-form-element">
                      <div class="slds-form-element__control">
                         <label class="slds-checkbox">
                            <!--header checkbox for select all-->
                            <ui:inputCheckbox aura:id="box3" change="{!c.selectAll}"/>
                            <span class="slds-checkbox--faux"></span>
                            <span class="slds-form-element__label text"></span>
                         </label>
                      </div>
                   </div>
                </th>
                <th>
                   <span class="slds-truncate" title="Name">Accounts</span>      
                </th>
             </tr>
          </thead>
          <!--table body start, 
             Iterate contact list as a <tr>
             -->
          <tbody>
             <aura:iteration items="{!v.searchResult}" var="acc">
                <tr>
                   <td scope="row" class="slds-text-align--right" style="width:3.25rem;">
                      <div class="slds-form-element">
                         <div class="slds-form-element__control">
                            <label class="slds-checkbox">
                               <ui:inputCheckbox text="{!acc.Id}" aura:id="boxPack" value=""/>
                               <span class="slds-checkbox--faux"></span>
                               <span class="slds-form-element__label text"></span>
                            </label>
                         </div>
                      </div>
                   </td>
                   <td scope="row">
                      <div class="slds-truncate" title="{!acc.Name}"><a>{!acc.Name}</a></div>
                   </td>
                </tr>
             </aura:iteration>
          </tbody>
       </table>
       </div>
       <div style="padding:15px">
           <lightning:button name="submitForApproval" label="Submit For Approval" onclick="{!c.submitSelected}"/>
       </div>
</aura:component>
Lightning component controller/salesownerchangecontroller.js:
({
    submit : function(component, event, helper) 
    {
        var userId = component.get("v.fromSalesperson");
        var action = component.get("c.ownerList");
        action.setParams({
            'user': userId.Id
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") 
            {
                var storeResponse = response.getReturnValue();
                component.set("v.searchResult", storeResponse);
            }
 });
        $A.enqueueAction(action);
    },
    
      selectAll: function(component, event, helper) 
    {
          var selectedHeaderCheck = event.getSource().get("v.value");
          var getAllId = component.find("boxPack");
        system.debug('boxPack:::'+ boxPack);
          if (selectedHeaderCheck == true) 
          {
               for (var i = 0; i < getAllId.length; i++) 
            {
                component.find("boxPack")[i].set("v.value", true);
                component.set("v.selectedCount", getAllId.length);
               }
          } 
         else 
        {
               for (var i = 0; i < getAllId.length; i++) 
            {
                component.find("boxPack")[i].set("v.value", false);
                component.set("v.selectedCount", 0);
               }
          }
     },
    
    submitSelected: function(component, event, helper) 
    {
        var selId = [];
          var getAllId = component.find("boxPack");
        var getRequest = component.get("v.request");
        var getEffective = component.get("v.effective");
        component.set("v.request", getRequest);
        component.set("v.effective", getEffective);
          for (var i = 0; i < getAllId.length; i++) 
        {
               if (getAllId[i].get("v.value") == true) 
            {
                selId.push(getAllId[i].get("v.text"));
               }
          }
          helper.submitSelectedHelper(component, event, selId, getRequest, getEffective);
    },
})

Helper :
({
     submitSelectedHelper: function(component, event, selectRecordsIds, getRequest, getEffective) 
    {
         var userId = component.get("v.toSalesperson");
        var fromId = component.get("v.fromSalesperson");
          var action = component.get("c.updateAccounts");
        var requestDate = ""+getRequest+"";
        var effectiveDate = ""+getEffective+"";
          action.setParams({
               "selectList": selectRecordsIds,
               "userId": userId.Id,
            "fromId": fromId.Id,
            "requestDate": requestDate,
            "effectiveDate": effectiveDate
          });
          action.setCallback(this, function(response) {
           var state = response.getState();
            system.debug("state:::"+state);
           if (state === "SUCCESS") 
        {
            console.log(state);
           }
    });
          $A.enqueueAction(action);
        
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
        "title": "Success!",
        "message": "Submitted For Approval"
        });
        toastEvent.fire();
        
        var urlEvent = $A.get("e.force:navigateToURL");
        urlEvent.setParams({
          "url": "/one/one.app#/n/Sales_Owner_Change_Request"
        });
        urlEvent.fire();
    },
})


As of now in the component page if nothing is selected and we click on submit for approval i clicked: an error is thrown with following message--> Uncaught Action failed: c:salesOwnerChange$controller$submitSelected [Cannot read property 'length' of undefined]
 
Best Answer chosen by Ananthanarayanan Nemmara
Ashif KhanAshif Khan
Hi Ananthanarayanan ,
you can find the number of selected account and can show the error as you want here am showing in alert
submitSelected: function(component, event, helper) 
    {
        var selId = [];
          var getAllId = component.find("boxPack");
        var getRequest = component.get("v.request");
        var getEffective = component.get("v.effective");
       
       //=====change It as=====


     getAllId=(getAllId==null)?[]:getAllId;


          for (var i = 0; i < getAllId.length; i++) 
        {
               if (getAllId[i].get("v.value") == true) 
            {
                selId.push(getAllId[i].get("v.text"));
               }
          }

         //==finding number of selected account

      if(selId.length==0){ 
        alert('please select account');
            return ;}
          
         component.set("v.request", getRequest); 
         component.set("v.effective", getEffective);

          helper.submitSelectedHelper(component, event, selId, getRequest, getEffective);
    },

​​regards 
Ashif

All Answers

Raj VakatiRaj Vakati
You can do it in two ways 
  • Server side code. You can throw an error from the apex code as shown below 
throw new AuraHandledException('NSFW name detected.');
  • Client-side 
let errors = response.getError();
let message = 'Unknown error'; // Default error message
// Retrieve the error message sent by the server
if (errors && Array.isArray(errors) && errors.length > 0) {
    message = errors[0].message;
}
// Display the message
console.error(message);



Refer this link 

https://developer.salesforce.com/blogs/2017/09/error-handling-best-practices-lightning-apex.html
Ananthanarayanan NemmaraAnanthanarayanan Nemmara
Hi Raj,

Thanks for your reply. But could you please let me know where do I need to write in the code pasted above. I have already referred to the article you have posted before posting this question here, but I was unable to implement it in my code.

Regards,
Anand
Ashif KhanAshif Khan
Hi Ananthanarayanan 
make some changes of getAllId variable as 
submitSelected: function(component, event, helper) 
    {
        var selId = [];
          var getAllId = component.find("boxPack");
        var getRequest = component.get("v.request");
        var getEffective = component.get("v.effective");
        component.set("v.request", getRequest);
        component.set("v.effective", getEffective);
       //=====change It as=====


     getAllId=(getAllId==null)?[]:getAllId;


          for (var i = 0; i < getAllId.length; i++) 
        {
               if (getAllId[i].get("v.value") == true) 
            {
                selId.push(getAllId[i].get("v.text"));
               }
          }
          helper.submitSelectedHelper(component, event, selId, getRequest, getEffective);
    },

Let me know is it work for you.
Regards 
Ashif
Ananthanarayanan NemmaraAnanthanarayanan Nemmara
Hey Ashif,
Thanks for your reply. But just by adding this one line didn't change anything. It gives me success message but the request ius not inserted. I want a error message when people click submit for approval without selecting the account first. Could you please let me know how this can be done.
Regards,
Anand
Ananthanarayanan NemmaraAnanthanarayanan Nemmara
Hi All,
Just to clarify, nothing is required in the object. I am just trying to make it required from the front end.As of now when someone tries to submit for approval, they get a message that its successful but a request is not created. I want to show them them before clicking on submit for approval they need to enter the data above.
Regards,
Anand
Ashif KhanAshif Khan
Hi Ananthanarayanan ,
you can find the number of selected account and can show the error as you want here am showing in alert
submitSelected: function(component, event, helper) 
    {
        var selId = [];
          var getAllId = component.find("boxPack");
        var getRequest = component.get("v.request");
        var getEffective = component.get("v.effective");
       
       //=====change It as=====


     getAllId=(getAllId==null)?[]:getAllId;


          for (var i = 0; i < getAllId.length; i++) 
        {
               if (getAllId[i].get("v.value") == true) 
            {
                selId.push(getAllId[i].get("v.text"));
               }
          }

         //==finding number of selected account

      if(selId.length==0){ 
        alert('please select account');
            return ;}
          
         component.set("v.request", getRequest); 
         component.set("v.effective", getEffective);

          helper.submitSelectedHelper(component, event, selId, getRequest, getEffective);
    },

​​regards 
Ashif
This was selected as the best answer
Ananthanarayanan NemmaraAnanthanarayanan Nemmara
Hey Asif, 
Thanks a lot for your solution. This did work. Infact I had found the solution before checking here but forgot to respond here. But thanks for your efforts. One thing that i would like to know is, in my lightning component there are 2 search boxes "From Salesperson" and "To Salesperson". I have done all the validations but the only 2 of them which I am not able to do are:

1> Once a rep is selected, and then removed and if i click submitted it does call the controller inspite of my validation as below:
 
if(selId.length>0 )
        {
            if(getRequest!=null)
            {
                if(getEffective!=null)
                {
                    if(userId!=null)
                    {
                        if(userId!==fromId){
                            helper.submitSelectedHelper(component, event, selId, getRequest, getEffective);
                        }else{
                            var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
        title: "Please re-check your Salesperson To and From Salesperson",
        message: "To and from Salespersons are same",
        type:'error'
        });
        toastEvent.fire();
                        }
2> As you can see above even when the to and from salesperson are same i do not want to trigger the submitSelectedHelper function but this is not working.

Any inputs on how i can make this work.

Regards,
Anand
Ashif KhanAshif Khan
Hi Ananthanarayanan,
There is a little mistake in this condition userId!==fromId you need to use userId!=fromId.

Regards
Ashif
Ananthanarayanan NemmaraAnanthanarayanan Nemmara
Hi Asif,

Thanks for the reply. I could solve those 2 issues. It was cacutally UserId.Id!=fromId.Id which i had to use.
Thanks for your response.
Regards,
Anand