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
John LayJohn Lay 

Handle Record Changes and Errors Not Setting v.recordSaveError message

I'm trying to complete the Handle Record Changes and Errors module but can't seem to get past the following challenge error:
Challenge Not yet complete... here's what's wrong: 
The 'accEdit' Lightning Component JS Controller does not appear to be setting 'v.recordSaveError' with an error message.

.I've tried many different combinations of sets and am not having much luck.

I've tried several different component.set methods such as this one:
component.set('v.recordSaveError','Error: ' + saveResult.state + ', message: ' + JSON.stringify(saveResult.error));

Any ideas what this module is looking for as a valid solution?

I do see recordSaveError display after being set due to an error.

Thanks.
 
Alain CabonAlain Cabon
Hi John,

I have just used the given pattern without changing it. Your solution should work but the challenge is waitting for something that is exactly that way:
 
if (saveResult.state === "ERROR") {
                var errMsg = "";
                // saveResult.error is an array of errors, 
                // so collect all errors into one message
                for (var i = 0; i < saveResult.error.length; i++) {
                    errMsg += saveResult.error[i].message + "\n";
                }
                cmp.set("v.recordSaveError", errMsg);
            } else {
                cmp.set("v.recordSaveError", "");
   }
<!-- Display Lightning Data Service errors, if any -->   
    <aura:if isTrue="{!not(empty(v.recordSaveError))}">
        <br />
        Error: <ui:outputText value="{!v.recordSaveError}"/>
    </aura:if>

https://trailhead.salesforce.com/fr/modules/lightning_data_service/units/lightning_data_service_handle_notifications

Regards
John Lay 9John Lay 9
Thanks Alain... you gave me just what I needed to compelete the module.

I had this pattern at one time but removed it when I got a different message.  I thought I had cycled back through all my tried patterns, but apparently did not.

Happy Trails.
John.
Alain CabonAlain Cabon
Good news

You have "some" badges I see:  https://trailhead-leaderboard-developer-edition.na35.force.com/

Happy Trails
Alain
Jess BurghJess Burgh
Hey all. I've been trying to figure out where I've gone wrong. I keep getting this error message. Challenge Not yet complete... here's what's wrong:
Could not find JS controller code for 'accEdit' Lightning Component. Any suggestions would be appreciated. Thanks!!
Patrick McClellanPatrick McClellan
This one had me stumped for too long, and for a reason that is totally lame! The validation check is looking in the js controller for "cmp.set" -- not "component.set" -- which is what is in the Developer Guide. Try this:
({
    handleSaveRecord: function(cmp, event, helper) {
        cmp.find("recordLoader").saveRecord($A.getCallback(function(saveResult) {
           
            if (saveResult.state === "ERROR") {
                var errMsg = "";
                // saveResult.error is an array of errors, 
                // so collect all errors into one message
                for (var i = 0; i < saveResult.error.length; i++) {
                    errMsg += saveResult.error[i].message + "\n";
                }
                cmp.set("v.recordSaveError", errMsg);
            } else {
                cmp.set("v.recordSaveError", "");
            }
        }));}
})

 
Jess BurghJess Burgh
Hey all. Patrick, I tried your coded and am still getting the same error message. Anyone have any other ideas? Thanks!!
Patrick McClellanPatrick McClellan
Hi Jess, this module is short on explanation, so my understanding of it is weak. The only other thing I can suggest is to make sure that the parameter you specify in the cmp.find() line ["recordLoader" in my code] matches the aura:id in the force:recordData in the component [force:recordData aura:id="recordLoader"].
Mo TrailheadMo Trailhead
Wow. I just spent about 90 minutes trying this every which way (same as above, it worked just fine in the UI but I kept getting the "controller does not appear to be setting" error. Changing the param to cmp in the function worked. Which is REALLY STUPID.

There is also what appears to be a typo in the instructions:
"If the edits in your editable component create an error, make sure the display component shows an error message."

Considering that we just built an edit component and a display component, this is very misleading -- I first thought the goal was to have an error in the edit component show the error message over in the other display component and built that. But then it became clear they just wanted everything done in the edit component.

This is a really poorly executed challenge -- unclear instructions and dependencies for passing that should not be there.
Marcin UfniarzMarcin Ufniarz
So it seems it requires that you use the 
Error: <ui:outputText value="{!v.recordSaveError}"/>

tag to display your error message.  I'm honestly just doing it in both in order to pass this.  I took everyone's suggestion from above.  
<aura:if isTrue="{!not(empty(v.recordSaveError))}">
        <div class="recordSaveError">
            <ui:message title="Error" severity="error" closable="true">
                {!v.recordSaveError}
            </ui:message>
            Error: <ui:outputText value="{!v.recordSaveError}"/>
        </div>
    </aura:if>
handleSaveRecord: function(cmp, event, helper) {
        cmp.find("recordEditor").saveRecord($A.getCallback(function(saveResult) {
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
                console.log("Save completed successfully.");
                cmp.set("v.recordSaveError", '');
            } else if (saveResult.state === "INCOMPLETE") {
                console.log("User is offline, device doesn't support drafts.");
                cmp.set("v.recordSaveError", '');
            } else if (saveResult.state === "ERROR") {
            	var errMsg = "";
                // console.log('Problem saving record, error: ' + JSON.stringify(saveResult.error));
                // saveResult.error is an array of errors,
				// so collect all errors into one message
                for(var i = 0; i < saveResult.error.length; i++) {
                    errMsg += saveResult.error[i].message + "\n";
                }
                cmp.set("v.recordSaveError", errMsg);

            } else {
                console.log('Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error));
                cmp.set("v.recordSaveError", "");
            }
        }));
    },

Good Luck on this headache. :)
Mark Tyler CrawfordMark Tyler Crawford
@Marcin Ufniarz

Putting the error in the format that you suggested worked for me.  

Error: <ui:outputText value="{!v.recordSaveError}"/>


I am starting to distrust the final checks on coding projects.. It seems they want something so specific that it almost makes it impossible to get the right answer without looking it up.
Hanzsi DadonHanzsi Dadon
Has anyone a working solution? I get this error: The 'accEdit' Lightning Component does not appear to be checking if 'v.recordSaveError' is true.
This sounds strange because recordSaveError is a string, not a boolean...
Dustin Warner 5Dustin Warner 5
I just finished this Module. I was running into the same issue as @Hanzsi. I tried to follow the example in the walkthrough but it still gave me the error. I was able to update the .cmp and make it work with the following code.
 
<aura:if isTrue="{!v.recordSaveError}">
       <br />
       <div class="recordError">
           {!v.recordSaveError}
       </div>
    </aura:if>

It does not really make sense why it would be doing a check like this since it is a string attribute and in the example it has you check if it is not empty. This allowed me to proceed with the Module.
 
Hanzsi DadonHanzsi Dadon
Yeah, that worked for me, thank you so much!
Ducamp SebastienDucamp Sebastien
Thanks Dustin ! It worked for me ... although it does not make sense at all ....
Yves Asselin 3Yves Asselin 3
Thanks Dustin! 
BijaySBijayS
Thanks Dustin , it worked for me as well , Very Strange!!!
anjali gairolaanjali gairola
Just make sure to display the error in both the components .....edit as well as display cmp.
 
Prasanth SalamkayalaPrasanth Salamkayala
Thanks Dustin!!! Guys please use Dustin code to resolve it....
Dave HolfordDave Holford
Damn that was a curly one. The solution was so far removed from the previous units that it made it really difficult to work out the structure.

Finally, I'm through and now for the really scary part - the Superbadge.....
Lucas CalegariLucas Calegari

I guess for Dustin solution, the aura:if is probably checking if the error message is different than "" (As the default value on the attribute)
 

<aura:if isTrue="{!v.recordSaveError}">
       <br />
       <div class="recordError">
           {!v.recordSaveError}
       </div>
    </aura:if>

accEdit.cmp
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId">

    <aura:attribute name="recordId" type="String" />
    <aura:attribute name="recordError" type="String" />
    <aura:attribute name="record" type="Object" />
    <aura:attribute name="accountRecord" type="Object" />
    <aura:attribute name="recordSaveError" type="String" default=""/>

	<force:recordData aura:id="recordEditor"
                  layoutType="FULL"
                  recordId="{!v.recordId}"
                  targetError="{!v.recordError}"
                  targetRecord="{!v.record}"
                  targetFields ="{!v.accountRecord}"
                  fields="Name"
                  mode="EDIT" />

	<!-- Display an editing form -->
  <lightning:input label="Account Name" value="{!v.accountRecord.Name}"/>
	<lightning:button   label="Save Account"  value="{!c.handleSaveRecord}" />

  <aura:if isTrue="{!v.recordSaveError}">
       <br />
       <div class="recordError">
           {!v.recordSaveError}
       </div>
    </aura:if>

</aura:component>
accEditController
({
    handleSaveRecord: function(cmp, event, helper) {
        cmp.find("recordEditor").saveRecord($A.getCallback(function(saveResult) {
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
                console.log("Save completed successfully.");
                cmp.set("v.recordSaveError", '');
            } else if (saveResult.state === "INCOMPLETE") {
                console.log("User is offline, device doesn't support drafts.");
                cmp.set("v.recordSaveError", '');
            } else if (saveResult.state === "ERROR") {
                var errMsg = "";
                // console.log('Problem saving record, error: ' + JSON.stringify(saveResult.error));
                // saveResult.error is an array of errors,
                // so collect all errors into one message
                for(var i = 0; i < saveResult.error.length; i++) {
                    errMsg += saveResult.error[i].message + "\n";
                }
                cmp.set("v.recordSaveError", errMsg);

            } else {
                console.log('Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error));
                cmp.set("v.recordSaveError", "");
            }
        }));
})



This worked for me! Thanks Dustin
Faiza Naz 10Faiza Naz 10
Hi,
you can find solution here.
http://faizanaz90.blogspot.com/2017/11/lightning-data-service-basics-handle.html
sfdc learner 21sfdc learner 21
Thanks, Faiza

Note mentioned in the post was very helpful. It's worked for me.

Note:
​If you keep getting this error "The 'accEdit' Lightning Component JS Controller does not appear to be setting 'v.recordSaveError' with an error message" then make sure in handleSaveRecord function you are using "cmp" not any other name.
amahmamahm
I dont like that !!! I was able to accomplish with the following code:
 
<aura:if isTrue="{!v.recordSaveError}">
        <div class="recordError">{!v.recordSaveError}</div>
    </aura:if>
He wanted the error message in a div with a "recordError" class !!!!!!!!!! This is nowhere mentioned
 
Rahul Gawale 26Rahul Gawale 26
I have used following code, and it worked for me.
 
//in component at the end,
<!-- Display error message -->
    <aura:if isTrue="{!not(empty(v.recordSaveError))}">
        <div class="recordError">
            {!v.recordSaveError}</div>
    </aura:if>

/// in handleSaveRecord
if (saveResult.state === "ERROR") {
                var errMsg = "";
                // saveResult.error is an array of errors, 
                // so collect all errors into one message
                for (var i = 0; i < saveResult.error.length; i++) {
                    errMsg += saveResult.error[i].message + "\n";
                }
                cmp.set("v.recordSaveError", errMsg);
            } else {
                cmp.set("v.recordSaveError", "");
   			}

 
ArturArtur

Accordnig Rahul Gawale 22
Display error message have to be placed after div edit section. It pass the chalange only in this order :|

shashi kumar 58shashi kumar 58
Lightning Data Service Basics
Handle Record Changes and Errors 
1. accEdit.cmp
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId">

    <aura:attribute name="recordId" type="String" />
    <aura:attribute name="recordError" type="String" />
    <aura:attribute name="record" type="Object" />
    <aura:attribute name="accountRecord" type="Object" />
    <aura:attribute name="recordSaveError" type="String" default=""/>

	<force:recordData aura:id="recordEditor"
                  layoutType="FULL"
                  recordId="{!v.recordId}"
                  targetError="{!v.recordError}"
                  targetRecord="{!v.record}"
                  targetFields="{!v.accountRecord}"
                  fields="Name"
                  mode="EDIT" />

	<!-- Display an editing form -->
  <lightning:input label="Account Name" value="{!v.accountRecord.Name}"/>
	<lightning:button label="Save Account"  value="{!c.handleSaveRecord}" />

 <aura:if isTrue="{!v.recordSaveError}">
       <br />
       <div class="recordError">
           {!v.recordSaveError}
       </div>
    </aura:if>
    
    <aura:if isTrue="{!not(empty(v.recordSaveError))}">
        <div class="recordError">
            {!v.recordSaveError}</div>
</aura:if>
    
    

</aura:component>
2. accDisplay.cmp
<aura:component description="accDisplay" implements="flexipage:availableForRecordHome,force:hasRecordId">
<aura:attribute name="recordId" type="String" />
<aura:attribute name="record" type="Object" />
<aura:attribute name="accountRecord" type="Object" />

<force:recordData recordId="{!v.recordId}"
                  targetRecord="{!v.record}"
                  targetFields="{!v.accountRecord}"
                  fields="Id, Name"/>

<label class="slds-form-element__label">Name: </label>

    <lightning:card title="{!v.accountRecord.Name}" />

<label class="slds-form-element__label">Industry: </label>
<lightning:formattedText title="Industry" value="{!v.accountRecord.Industry}"/>

<label class="slds-form-element__label">Description: </label>
<!--<lightning:card title="{!v.accountRecord.Description}"/>-->
    <lightning:formattedText title="Description" value="{!v.accountRecord.Description}" />

<label class="slds-form-element__label">Phone: </label>
<lightning:formattedPhone title="Phone" value="{!v.accountRecord.Phone}"/>

</aura:component>

3. Controller accEditController.js
({
    handleSaveRecord: function(cmp, event, helper) {
        cmp.find("recordEditor").saveRecord($A.getCallback(function(saveResult) {
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
                console.log("Save completed successfully.");
                cmp.set("v.recordSaveError", '');
            } else if (saveResult.state === "INCOMPLETE") {
                console.log("User is offline, device doesn't support drafts.");
                cmp.set("v.recordSaveError", '');
            } else if (saveResult.state === "ERROR") {
                var errMsg = "";
                // console.log('Problem saving record, error: ' + JSON.stringify(saveResult.error));
                // saveResult.error is an array of errors,
                // so collect all errors into one message
                for(var i = 0; i < saveResult.error.length; i++) {
                    errMsg += saveResult.error[i].message + "\n";
                }
                cmp.set("v.recordSaveError", errMsg);

            } else {
                console.log('Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error));
                cmp.set("v.recordSaveError", "");
            }
        }));
    }})

​Check your challenge... Please mark it as best answer and like.....

 
Joe Bauer 4Joe Bauer 4
So I got it to pass but it doesn't work in the UI when I tested it. I keep getting a null error whenever I type anything in the input box. Anyone know why that is?
Rajani PolampalliRajani Polampalli
@Shashi Kumar,

Thanks. It works for me fine..
Frederick H LaneFrederick H Lane
This is what worked for me;
I edited the accEdit component from the previous challenge 'Manipulate Records with force:recordData'
Challenge; "Use force:recordData to create two Lightning components that display and edit the details of an account"

accEdit.cmp

<aura:component implements="force:hasRecordId,flexipage:availableForRecordHome">
 <aura:attribute name="record"
                   type="Object"
                   description="The record object to be displayed"/>
    <aura:attribute name="accountRecord"
                    type="Object"
                    description="A simplified view record object to be displayed"/>
    <aura:attribute name="recordSaveError"
                    type="String"
                    description="An error message bound to force:recordData"/>
    
    <force:recordData aura:id="accountRecordId"
                      recordId="{!v.recordId}"
                      fields="Name"
                      mode="EDIT"
                      targetRecord="{!v.record}"
                      targetFields="{!v.simpleRecord}"
                      targetError="{!v.recordSaveError}"/>
    
    
    <!-- Display an editing form -->
    <div class="Record Details">
        <lightning:card iconName="action:edit" title="Edit Account">
            <div class="slds-p-horizontal--small">
                <lightning:input label="Account Name" value="{!v.accountRecord.Name}"/>
                <br/>
                <lightning:button label="Save Account" variant="brand" onclick="{!c.handleSaveRecord}" />
            </div>
        </lightning:card>
    </div>
    
    <!-- Display Lightning Data Service errors, if any -->
    <aura:if isTrue="{!not(empty(v.recordSaveError))}">
        <div class="recordError">
            {!v.recordSaveError}
        </div>
    </aura:if>
</aura:component>

accEditController.js

({
 handleSaveRecord : function(component, event, helper) {
  component.find("accountRecordId").saveRecord($A.getCallback(function(saveResult) {
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
                console.log("Save completed successfully.");
            } else if (saveResult.state === "INCOMPLETE") {
                console.log("User is offline, device doesn't support drafts.");
            } else if (saveResult.state === "ERROR") {
                console.log('Problem saving record, error: ' + 
                           JSON.stringify(saveResult.error));
                var errMsg = "";
                for (var i = 0; i < saveResult.error.length; i++) {
                    errMsg += saveResult.error[i].message + "\n";
                }
                component.set("v.recordSaveError", errMsg);
            } else {
                console.log('Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error));
            }
        }));
 }
})
Thomas HThomas H
Sashi K  ) ---    You Code Worked  !!  THANKS    --- I tried this countless times.over a day or two with many different approaches of Code (above) .

I did log out of SF for 45 minutes  before I tested your Code however. Maybe that helped too )

Best,
th

User-added image
Saket Ranjan 3Saket Ranjan 3
here is the code, like and help other if it works for you too :

accDisplay.cmp 
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId">
 <aura:attribute name="accountRecord" type="Object" />
<force:recordData aura:id="AccountRecordCreator"
    recordId="{!v.recordId}"
    layoutType="FULL"
    targetRecord="{!v.accountRecord}"
    targetFields="{!v.simpleNewAccount}"
    targetError="{!v.newContactError}"
                  mode="VIEW"
    />
   



      
    <!-- Display a lightning card with details about the record -->
<div class="Record Details"> 
    <lightning:card iconName="standard:account" title="{!v.accountRecord.Name}" >
        <div class="slds-p-horizontal--small">
            <p class="slds-text-heading--small">
                <lightning:formattedText title="Industry" value="{!v.accountRecord.Industry}" /></p>
            <p class="slds-text-heading--small">
                <lightning:formattedText title="Description" value="{!v.accountRecord.Description}" /></p>
            <p class="slds-text-heading--small">
                <lightning:formattedPhone title="Phone" value="{!v.accountRecord.Phone}" /></p>
        </div>
    </lightning:card>
</div>

<!-- Display Lightning Data Service errors, if any -->
<aura:if isTrue="{!not(empty(v.recordError))}">
    <div class="recordError">
        {!v.recordError}</div>
</aura:if>

   

   
</aura:component>


accEdit.cmp

<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId"> <!--inherit recordId attribute-->

<aura:attribute name="accountRecord" type="Object" />
<aura:attribute name="recordSaveError" type="String" />

<force:recordData aura:id="recordEditor"
    recordId="{!v.recordId}"
    targetError="{!v.recordSaveError}"
    targetFields="{!v.accountRecord}"
    mode="EDIT" 
    fields="Name" />

    <!-- Display an editing form -->
    <div calss="Edit Account">
        <lightning:card iconName="action:edit" title="Edit Account">
            <div class="slds-p-horizontal--small">
                <lightning:input label="Account Name" value="{!v.accountRecord.Name}" /> <br/>
                <lightning:button label="Save Account" onclick="{!c.handleSaveRecord}" variant="brand"/>
            </div>    
        </lightning:card> 
    </div>
         <!-- Display Lightning Data Service errors, if any -->
        
   <aura:if isTrue="{!not(empty(v.recordSaveError))}">
        <div class="recordError">
             {!v.recordSaveError}</div>
        
    </aura:if>
     
    
   
</aura:component>


accEditController


({
   handleSaveRecord: function(cmp, event, helper) {
        cmp.find("recordEditor").saveRecord($A.getCallback(function(saveResult) {
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
                console.log("Save completed successfully.");
                cmp.set("v.recordSaveError", '');
            } else if (saveResult.state === "INCOMPLETE") {
                console.log("User is offline, device doesn't support drafts.");
                cmp.set("v.recordSaveError", '');
            } else if (saveResult.state === "ERROR") {
                var errMsg = "";
                                for(var i = 0; i < saveResult.error.length; i++) {
                    errMsg += saveResult.error[i].message + "\n";
                }
                cmp.set("v.recordSaveError", errMsg);

            } else {
                console.log('Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error));
                cmp.set("v.recordSaveError", "");
            }
        }));
    },
})
Shivprakash SoniShivprakash Soni

Please try below code, hope this will work .

accEdit.cmp:
-------------------
<aura:component implements="force:hasRecordId,flexipage:availableForRecordHome">
    <aura:attribute name="accountRecord" type="Object"/>
    <aura:attribute name="recordSaveError" type="String" default=""/>
    <!-- Load record in EDIT mode -->
    <force:recordData aura:id="recordLoader"
        recordId="{!v.recordId}"
        fields="Name,Description,Phone"
        targetFields="{!v.accountRecord}"
        targetError="{!v.recordSaveError}"
        mode="EDIT"
        recordUpdated="{!c.handleRecordUpdated}" />
    <!-- Account edit form -->
    <lightning:card iconName="action:edit" title="Edit Accountg">
        <div class="slds-p-horizontal--small">
            <lightning:input label="Account Name" value="{!v.accountRecord.Name}"/>
            <br/>
            <lightning:button label="Save Account" variant="brand" onclick="{!c.saveAccount}" />
        </div>
    </lightning:card>
    <!-- Display error message -->
    <aura:if isTrue="{!not(empty(v.recordSaveError))}">
        <div class="recordSaveError">
            {!v.recordSaveError}</div>
    </aura:if>
</aura:component>
---------------------------------------------------------------------------------------------------------------------------------------------
accEditController.js:
-----------------------------


({
    saveAccount : function(cmp, event, helper) {
        var recordLoader = cmp.find("recordLoader");
        recordLoader.saveRecord($A.getCallback(function(saveResult) {
            if (saveResult.state === "ERROR") {
                var errMsg = "";
                // saveResult.error is an array of errors,
                // so collect all errors into one message
                for (var i = 0; i < saveResult.error.length; i++) {
                    errMsg += saveResult.error[i].message + "\n";
                }
                cmp.set("v.recordSaveError", errMsg);
            } else {
                cmp.set("v.recordSaveError", "");
            }
        }));
    },
    // Control the component behavior here when record is changed (via any component)
    handleRecordUpdated: function(component, event, helper) {
        var eventParams = event.getParams();
        if(eventParams.changeType === "CHANGED") {
            // get the fields that are changed for this record
            var changedFields = eventParams.changedFields;
            console.log('Fields that are changed: ' + JSON.stringify(changedFields));
            // record is changed so refresh the component (or other component logic)
            var resultsToast = $A.get("e.force:showToast");
            resultsToast.setParams({
                "title": "Saved",
                "message": "The record was updated."
            });
            resultsToast.fire();
        } else if(eventParams.changeType === "LOADED") {
            // record is loaded in the cache
        } else if(eventParams.changeType === "REMOVED") {
            // record is deleted and removed from the cache
        } else if(eventParams.changeType === "ERROR") {
            console.log('Error: ' + component.get("v.error"));
        }
    }
})
__________________________________________       GoodLuck       ______________________________________________________