You need to sign in to do that
Don't have an account?
Lightning Components error "Unable to find action 'getCaseComments' on the controller of c:CaseCommentList"
Hello All,
Taking a shot at my first Lighting Component App and cannot resolve my #^&!# error. The purpose of my app is to display CaseComments related to a Case. When I attempt to Preview my app get the following error:
*** Can Someone please help me find my error? ***
Thanks in advance.
Robert
Here's my code:
CaseCommentListController.cls
// Apex Controller for CaseComment List Lightning Component public class CaseCommentListController { @AuraEnabled public static List<CaseComment> getCaseCommentsList(List<Id> parentIds) { // Getting the list of casecomments from where Id is in parentIds List<CaseComment> casecommentList = [SELECT Id, CommentBody, ParentId FROM CaseComment WHERE ParentId in :parentIds]; // Returning the casecomment list return casecommentList; } @AuraEnabled public static Map<String,String> saveCaseCommentList(List<CaseComment> casecommentList) { // Forming a string map to return response Map<String,String> resultMap = new Map<String,String>(); // Adding try catch for exception handling try { // Updating the CaseComment List update casecommentList; // Setting the success status and message in resultMap resultMap.put('status', 'success'); resultMap.put('message', 'CaseComments Updated Successfully'); } catch(Exception e) { // Setting the error status and message in resultMap resultMap.put('status', 'error'); resultMap.put('message',e.getMessage()); } // Returning the result string map return resultMap; } @AuraEnabled public static Map<String,String> deleteCaseCommentList(List<Id> casecommentIds) { //Fetching CaseComments List<CaseComment> casecommentsToDelete = [SELECT Id FROM CaseComment WHERE Id in :casecommentIds]; // Forming a string map to return response Map<String,String> resultMap = new Map<String,String>(); // Adding try catch for exception handling try { // Deleting the CaseComments delete casecommentsToDelete; // Setting the success status and message in resultMap resultMap.put('status', 'success'); resultMap.put('message', 'CaseComments Deleted Successfully'); } catch(Exception e) { // Setting the error status and message in resultMap resultMap.put('status', 'error'); resultMap.put('message',e.getMessage()); } // Returning the result string map return resultMap; } @AuraEnabled public static Map<String, String> createCaseCommentRecord(CaseComment newCaseComment) { // Forming a string map to return response Map<String,String> resultMap = new Map<String,String>(); // Adding try catch for exception handling try { // Inserting the CaseComment insert newCaseComment; // Setting the success status and message in resultMap resultMap.put('status', 'success'); resultMap.put('message', 'CaseComment Inserted Successfully'); } catch(Exception e) { // Setting the error status and message in resultMap resultMap.put('status', 'error'); resultMap.put('message',e.getMessage()); } // Returning the result string map return resultMap; } }
CaseCommentListApp.app
<!-- Application to call CaseCommentList component --> <aura:application extends="force:slds" > <!-- force:slds extended to apply lightning design system styling and passed in the record Id --> <c:CaseCommentList recordId="5000y00001dWMmQAAW" /> </aura:application>
CaseCommentListAppController.js
({ // Function called on initial page loading to get casecomment list from server getCaseCommentsList : function(component, event, helper) { // Helper function - fetchCaseComments called for interaction with server helper.fetchCaseComments(component, event, helper); }, // Function used to create a new CaseComment newCaseComment: function(component, event, helper) { // Global event force:createRecord is used var createCaseComment = $A.get("e.force:createRecord"); // Parameters like apiName and defaultValues are set createCaseComment.setParams({ "entityApiName": "CaseComment", "defaultFieldValues": { "ParentId": component.get("v.recordId") } }); // Event fired and new casecomment dialog open createCaseComment.fire(); }, // Function used to update the casecomments editCaseComments: function(component, event, helper) { // Getting the button element var btn = event.getSource(); // Getting the value in the name attribute var name = btn.get('v.name'); // Getting the record view form and the record edit form elements var recordViewForm = component.find('recordViewForm'); var recordEditForm = component.find('recordEditForm'); // If button is edit if(name=='edit') { // Hiding the recordView Form and making the recordEdit form visible $A.util.addClass(recordViewForm,'formHide'); $A.util.removeClass(recordEditForm,'formHide'); // Changing the button name and label btn.set('v.name','save'); btn.set('v.label','Save'); } else if(name=='save') { // Calling saveCaseCommentList if the button is save helper.saveCaseCommentList(component, event, helper); } } })
CaseCommentListAppHelper.js
({ helperMethod : function() { } })
CaseCommentListApp.css
.THIS { } .THIS .formHide { display: none; }
CaseCommentListCmp.cmp
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes" controller="CaseCommentListController" access="global"> <!-- Handler to call function when page is loaded initially --> <aura:handler name="init" action="{!c.getCaseComments}" value="{!this}" /> <!-- List of casecomments stored in attribute --> <aura:attribute name="casecommentList" type="List" /> <!-- New CaseComment Object --> <aura:attribute name="casecomment" type="CaseComment" default="{ 'SObjectType': 'CaseComment', 'CommentBody': '' }"> </aura:attribute> <!-- Method to validate new casecomment --> <aura:method name="validateCaseComment" action="{!c.validateCaseComment}" /> <!-- Lightning card to show casecomments --> <lightning:card title="CaseComments"> <!-- Body of lightning card starts here --> <p class="slds-p-horizontal_small"> <!-- Aura iteration to iterate list, similar to apex:repeat --> <div aura:id="recordViewForm"> <aura:iteration items="{!v.casecommentList}" var="casecomment"> <!-- recordViewForm to view the record --> <lightning:recordViewForm recordId="{!casecomment.Id}" objectApiName="CaseComment"> <div class="slds-box slds-theme_default"> <!-- inputfield checkbox used to check wether to delete the casecomment or not --> <lightning:input type="checkbox" value="{!casecomment.Id}" label="Mark for Deletion" aura:id="deleteCaseComment" /> <br /> <!-- outputfield used to output the record field data inside recordViewForm --> <lightning:outputField fieldName="CommentBody" /> </div> </lightning:recordViewForm> <!-- Line break between two records --> <br /> </aura:iteration> </div> <div aura:id="recordEditForm" class="formHide"> <aura:iteration items="{!v.casecommentList}" var="casecomment"> <div class="slds-box slds-theme_default"> <!-- inputfield used to update the record field data --> <!-- Validation added --> <lightning:input aura:id="fieldToValidate" value="{!casecomment.CommentBody}" messageWhenValueMissing="Comment is Mandatory" required="true"/> </div> <br /> <!-- Line break between two records --> </aura:iteration> </div> </p> <!-- Lightning card actions --> <aura:set attribute="actions"> <!-- New casecomment modal button added --> <lightning:button name="casecommentModal" label="New CaseComment" onclick="{!c.openModal}" /> <!-- Delete button added --> <lightning:button variant="destructive" label="Delete" onclick="{!c.deleteCaseComments}" /> <!-- New button added --> <lightning:button label="New" onclick="{!c.newCaseComment}" /> <!-- Edit/Save button added --> <lightning:button variant="brand" label="Edit" name="edit" onclick="{!c.editCaseComments}" /> </aura:set> </lightning:card> <!-- CaseComments Modal Section --> <div> <section aura:id="casecommentModal" role="dialog" tabindex="-1" aria-labelledby="casecommentModalHeading" aria-modal="true" aria-describedby="casecommentModalBody" class="slds-modal"> <!-- Modal Container --> <div class="slds-modal__container"> <!-- Modal Header ( consists of close button and heading of modal ) --> <header class="slds-modal__header"> <lightning:buttonIcon class="slds-modal__close" alternativeText="Close" iconName="utility:close" onclick="{!c.closeModal}" variant="bare-inverse" size="large"></lightning:buttonIcon> <h2 id="casecommentModalHeading" class="slds-text-heading_medium slds-hyphenate">New CaseComment</h2> </header> <!-- Modal Body ( consists of form ) --> <div class="slds-modal__content slds-p-around_medium" id="casecommentModalBody"> <!-- Validation added --> <lightning:input aura:id="formFieldToValidate" label="Comment" messageWhenValueMissing="Comment is Mandatory" required="true" value="{!v.casecomment.CommentBody}" /> </div> <!-- Modal Footer ( consists of cancel and save buttons ) --> <footer class="slds-modal__footer"> <lightning:button onclick="{!c.closeModal}" variant="neutral">Cancel</lightning:button> <lightning:button onclick="{!c.createCaseComment}" variant="brand" >Save</lightning:button> </footer> </div> </section> <!-- Modal Backdrop --> <div aura:id="casecommentModalBackdrop" class="slds-backdrop"></div> </div> </aura:component>
CaseCommentListCmpController.js
({ // Function called on initial page loading to get casecomment list from server getCaseCommentsList : function(component, event, helper) { // Helper function - fetchCaseComments called for interaction with server helper.fetchCaseComments(component, event, helper); }, // Function used to create a new casecomment newcasecomment: function(component, event, helper) { // Global event force:createRecord is used var createcasecomment = $A.get("e.force:createRecord"); // Parameters like apiName and defaultValues are set createcasecomment.setParams({ "entityApiName": "casecomment", "defaultFieldValues": { "ParentId": component.get("v.recordId") } }); // Event fired and new casecomment dialog open createcasecomment.fire(); }, // Function used to update the casecomments editCaseComments: function(component, event, helper) { // Getting the button element var btn = event.getSource(); // Getting the value in the name attribute var name = btn.get('v.name'); // Getting the record view form and the record edit form elements var recordViewForm = component.find('recordViewForm'); var recordEditForm = component.find('recordEditForm'); // If button is edit if(name=='edit') { // Hiding the recordView Form and making the recordEdit form visible $A.util.addClass(recordViewForm,'formHide'); $A.util.removeClass(recordEditForm,'formHide'); // Changing the button name and label btn.set('v.name','save'); btn.set('v.label','Save'); } else if(name=='save') { // Getting the edit form fields to validate var casecommentFields = component.find("fieldToValidate"); // Initialize the counter to zero - used to check validity of fields var blank=0; // If there are more than 1 fields if(casecommentFields.length!=undefined) { // Iterating all the fields var allValid = casecommentFields.reduce(function (validSoFar, inputCmp) { // Show help message if single field is invalid inputCmp.showHelpMessageIfInvalid(); // return whether all fields are valid or not return validSoFar && inputCmp.get('v.validity').valid; }, true); // If all fields are not valid increment the counter if (!allValid) { blank++; } } else { // If there is only one field, get that field and check for validity (true/false) var allValid = casecommentFields; // If field is not valid, increment the counter if (!allValid.get('v.validity').valid) { blank++; } } // Call the helper method only when counter is 0 if(blank==0) { // Calling saveCaseComments if the button is save helper.saveCaseComments(component, event, helper); } } }, // Function used to delete the casecomments deleteCaseComments: function(component, event, helper) { // Calling removeCaseComments Helper Function helper.removeCaseComments(component, event, helper); }, // Function used to open the casecomment modal openModal: function(component, event, helper) { var modal = component.find("casecommentModal"); var modalBackdrop = component.find("casecommentModalBackdrop"); $A.util.addClass(modal,"slds-fade-in-open"); $A.util.addClass(modalBackdrop,"slds-backdrop_open"); }, // Function used to close the casecomment modal closeModal: function(component, event, helper) { var modal = component.find("casecommentModal"); var modalBackdrop = component.find("casecommentModalBackdrop"); $A.util.removeClass(modal,"slds-fade-in-open"); $A.util.removeClass(modalBackdrop,"slds-backdrop_open"); }, // Function used to create new casecomment createcasecomment: function(component, event, helper) { var iscasecommentValid = component.validatecasecomment(component, event, helper); if(iscasecommentValid) { helper.insertcasecomment(component, event, helper); } }, // Function to validate new casecomment - Aura method used for the same validatecasecomment: function(component, event, helper) { // Getting all fields and iterate them to check for validity var allValid = component.find('formFieldToValidate').reduce(function (validSoFar, inputCmp) { // Show help message if single field is invalid inputCmp.showHelpMessageIfInvalid(); // Get the name of each field var name = inputCmp.get('v.name'); // Check if name is emailField if(name=='emailField') { // Getting the value of that field var value = inputCmp.get('v.value'); // If value is not equal to robert.wambold@almacgroup.com, add custom validation if(value != 'robert.wambold@almacgroup.com') { // Focus on that field to make custom validation work inputCmp.focus(); // Setting the custom validation inputCmp.set('v.validity', {valid:false, badInput :true}); } } // Returning the final result of validations return validSoFar && inputCmp.get('v.validity').valid; }, true); // Returning Validate casecomment result in boolen return allValid; } })
CaseCommentListCmpHelper.js
({ // Function to fetch data from server called in initial loading of page fetchCaseComments : function(component, event, helper) { // Assign server method to action variable var action = component.get("c.getCaseCommentList"); // Getting the parent id from page var parentId = component.get("v.recordId"); // Setting parameters for server method action.setParams({ parentIds: parentId }); // Callback function to get the response action.setCallback(this, function(response) { // Getting the response state var state = response.getState(); // Check if response state is success if(state === 'SUCCESS') { // Getting the list of casecomments from response and storing in js variable var casecommentList = response.getReturnValue(); // Set the list attribute in component with the value returned by function component.set("v.casecommentList",casecommentList); } else { // Show an alert if the state is incomplete or error alert('Error in getting data'); } }); // Adding the action variable to the global action queue $A.enqueueAction(action); }, // Function to update the casecomments on server saveCaseComments: function(component, event, helper) { // Getting the casecomment list from lightning component var casecommentList = component.get("v.casecommentList"); // Getting the recordViewForm and recordEditForm component var recordViewForm = component.find('recordViewForm'); var recordEditForm = component.find('recordEditForm'); // Initializing the toast event to show toast var toastEvent = $A.get('e.force:showToast'); // Defining the action to save casecomment List ( will call the saveCaseCommentList apex controller ) var saveAction = component.get("c.saveCaseCommentList"); // setting the params to be passed to apex controller saveAction.setParams({ casecommentList: casecommentList }); // callback action on getting the response from server saveAction.setCallback(this, function(response) { // Getting the state from response var state = response.getState(); if(state === 'SUCCESS') { // Getting the response from server var dataMap = response.getReturnValue(); // Checking if the status is success if(dataMap.status=='success') { // Remove the formHide class $A.util.removeClass(recordViewForm,'formHide'); // Add the formHide class $A.util.addClass(recordEditForm,'formHide'); // Getting the button element var btn = event.getSource(); // Setting the label and name of button back to edit btn.set('v.name','edit'); btn.set('v.label','Edit'); // Setting the success toast which is dismissable ( vanish on timeout or on clicking X button ) toastEvent.setParams({ 'title': 'Success!', 'type': 'success', 'mode': 'dismissable', 'message': dataMap.message }); // Fire success toast event ( Show toast ) toastEvent.fire(); } // Checking if the status is error else if(dataMap.status=='error') { // Setting the error toast which is dismissable ( vanish on timeout or on clicking X button ) toastEvent.setParams({ 'title': 'Error!', 'type': 'error', 'mode': 'dismissable', 'message': dataMap.message }); // Fire error toast event ( Show toast ) toastEvent.fire(); } } else { // Show an alert if the state is incomplete or error alert('Error in getting data'); } }); $A.enqueueAction(saveAction); } })
CaseCommentListCmp.css
.THIS { } .THIS .formHide { display: none; }
*** Thanks again for helping !!! ***
You are using wrong method name .In the CaseCommentListCmp.cmp init handler the action is getCaseComments.But there is no getCaseComments methods in
CaseCommentListCmpController.js.You have to call getCaseCommentsList in init handler of CaseCommentListCmp.cmp
Try this one
CaseCommentListCmp.cmp
Hope this helps you
If this helps kindly mark it as solved so that it may help others in future.
Thanks and Regards