+ Start a Discussion
Drew Meyers 3Drew Meyers 3 

Create a SimilarProperties Lightning Component not verifiying

I have no idea what is hanging up this trailhead unit, I have gone through the unit 3 times now following every single step the unit spells out for you to do. The error I am getting is "Challenge Not yet complete... here's what's wrong: 
The markup for the 'SimilarProperties' component is incorrect."
Here are the files created by following every excrutiating step.

SimilarProperties.cmp
<aura:component controller="MyPropertyController" implements="flexipage:availableForRecordHome">
<aura:attribute name="recordId" type="Id" />
<aura:attribute name="similarProperties" type="Object[]" />
<aura:attribute name="property" type="Property__c" />
<aura:attribute name="remoteRecordId" type="Id" />
<aura:attribute name="showDialog" type="String" default="false" />
<aura:attribute name="searchCriteria" type="String" default="Price" />
<aura:attribute name="priceRange" type="String" default="100000" />

    <aura:handler event="c:recordUpdated" action="{!c.doInit}" />

<force:recordData aura:id="propertyService"
                  recordId="{!v.recordId}"
                  targetRecord="{!v.property}"
                  recordUpdated="{!c.doInit}"
                  layoutType="FULL" />

<lightning:card iconName="custom:custom85" title="{! 'Similar Properties by ' + v.searchCriteria}" class="slds-is-relative">
    <div class="slds-p-left--medium slds-p-right--medium">
        <ul class="slds-list--vertical slds-has-dividers--top-space">
            <aura:iteration items="{!v.similarProperties}" var="item" indexVar="i">
                <li class="slds-list__item">                   
                    <c:SimilarProperty propertyId="{!item.Id}" remoteRecordId="{!v.remoteRecordId}" showDialog="{!v.showDialog}" />
                </li>
            </aura:iteration>
        </ul>
    </div>
    <lightning:spinner aura:id="spinner" variant="brand" size="large"/>
    <c:SimilarPropertyEdit showDialog="{!v.showDialog}" remoteRecordId="{!v.remoteRecordId}" />
</lightning:card>

</aura:component>
SimilarPropertiesController.js
({
    doInit : function(component, event, helper) {
        var spinner = component.find("spinner");
        $A.util.removeClass(spinner, "slds-hide");
        var action = component.get("c.getSimilarProperties");
        action.setParams({
        recordId: component.get("v.recordId"),
        beds: component.get("v.property.fields.Beds__c.value"),
        price: component.get("v.property.fields.Price__c.value"),
        searchCriteria: component.get("v.searchCriteria"),
        priceRange: parseInt(component.get("v.priceRange"), 10)
    });

        action.setCallback(this, function(response){
            var similarProperties = response.getReturnValue();
            component.set("v.similarProperties", similarProperties);
            $A.util.addClass(spinner, "slds-hide");
        });
        $A.enqueueAction(action);
    }
})
SimilarProperties.css
.THIS {
    min-height: 153px;
}

SimilarProperties.design
<design:component label="Similar Properties">
    <sfdc:objects>
        <sfdc:object>Property__c</sfdc:object>
    </sfdc:objects>
    <design:attribute name="searchCriteria" label="Search By" datasource="Bedrooms, Price" default="Price" description="Search for similar houses based on what criteria?" />
    <design:attribute name="priceRange" label="Price Range" default="100000" description="When searching by Price, search using the price plus or minus this amount" />   
</design:component>

SimilarProperties.svg
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="100px" height="100px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <path d="M120,108 C120,114.6 114.6,120 108,120 L12,120 C5.4,120 0,114.6 0,108 L0,12 C0,5.4 5.4,0 12,0 L108,0 C114.6,0 120,5.4 120,12 L120,108 L120,108 Z" id="Shape" fill="#2A739E"/>
        <path fill="#FFF" d="m78 24h-50v-2c0-1.1-0.9-2-2-2h-4c-1.1 0-2 0.9-2 2v56c0 1.1 0.9 2 2 2h4c1.1 0 2-0.9 2-2v-46h50c1.1 0 2-0.9 2-2v-4c0-1.1-0.9-2-2-2z m-4 14h-34c-3.3 0-6 2.7-6 6v22c0 3.3 2.7 6 6 6h34c3.3 0 6-2.7 6-6v-22c0-3.3-2.7-6-6-6z m-5.5 17h-2.5v10c0 0.6-0.4 1-1 1h-4c-0.6 0-1-0.4-1-1v-6c0-0.6-0.4-1-1-1h-4c-0.6 0-1 0.4-1 1v6c0 0.6-0.4 1-1 1h-4c-0.6 0-1-0.4-1-1v-10h-2.5c-0.5 0-0.7-0.6-0.3-0.9l11.2-10.9c0.4-0.3 0.9-0.3 1.3 0l11.2 10.9c0.3 0.3 0.1 0.9-0.4 0.9z"></path>
    </g>
</svg>

SimilarProperty.cmp
<aura:component implements="force:hasRecordId" access="global">
    <aura:attribute name="propertyId" type="Id" />
    <aura:attribute name="targetFields" type="Property__c" />
    <aura:attribute name="showDialog" type="String" />
    <aura:attribute name="remoteRecordId" type="Id" />

    <force:recordData aura:id="propertyRecord"
                      recordId="{!v.propertyId}"
                      targetFields="{!v.targetFields}"
                      fields="Name, Beds__c, Baths__c, Price__c, Status__c, Thumbnail__c"
                      />

    <div class="slds-media">
        <div class="slds-media__figure">
            <img src="{!v.targetFields.Thumbnail__c}" class="slds-avatar--large slds-avatar--circle" alt="{!v.targetFields.Title_c}" />
        </div>
        <div class="slds-media__body">
            <div class="slds-grid">
                <a onclick="{!c.navToRecord}">
                    <h3 class="slds-text-heading--small slds-m-bottom--xx-small">{!v.targetFields.Name}</h3>
                </a>
                <lightning:buttonIcon iconName="utility:edit" class="slds-col--bump-left" variant="bare" alternativeText="Edit Record" onclick="{!c.editRecord}" />
            </div>
            <div aura:id="propertyDetails" class="slds-m-top--small">
                <ul class="slds-grid slds-wrap">
                    <li class="slds-list__item slds-size--1-of-2"><span class="slds-text-color--weak slds-m-right--small">Beds:</span> {!v.targetFields.Beds__c}</li>
                    <li class="slds-list__item slds-size--1-of-2"><span class="slds-text-color--weak slds-m-right--small">Baths:</span> {!v.targetFields.Baths__c}</li>
                    <li class="slds-list__item slds-size--1-of-2"><span class="slds-text-color--weak slds-m-right--small">Price:</span> {!v.targetFields.Price__c}</li>
                    <li class="slds-list__item slds-size--1-of-2"><span class="slds-text-color--weak slds-m-right--small">Status:</span> {!v.targetFields.Status__c}</li>
                </ul>
            </div>
        </div>
    </div>
</aura:component>

SimilarPropertyController.js
({
    navToRecord : function (component, event, helper) {
        var navEvt = $A.get("e.force:navigateToSObject");
        navEvt.setParams({
            "recordId": component.get("v.propertyId")
        });
        navEvt.fire();
    },
    
        editRecord : function(component, event, helper) {
    var recId = component.get("v.propertyId");
    component.set("v.remoteRecordId", recId);
    component.set("v.showDialog", "true");
}
})

SimilarPropertyEdit.cmp
<aura:component>
    <aura:attribute name="showDialog" type="String" default="false" />
    <aura:attribute name="remoteRecordId" type="Id" />
    <aura:attribute name="selectedProperty" type="Property__c" />
    <aura:handler name="change" value="{!v.showDialog}" action="{!c.toggleDialog}" />
    <aura:handler name="change" value="{!v.remoteRecordId}" action="{!c.getRecord}" />

    <force:recordData aura:id="editRecord"
                         targetRecord="{!v.selectedProperty}"
                         fields="Id,Name,Beds__c,Baths__c,Price__c,Status__c"
                         mode="EDIT" />

    <div aura:id="editDialog" role="dialog" tabindex="-1" aria-labelledby="header43" class="slds-modal">
        <div class="slds-modal__container">
            <div class="slds-modal__header">
                <button class="slds-button slds-modal__close " title="Close" onclick="{!c.toggleDialog}">
                    <lightning:icon iconName="utility:close" variant="bare" ></lightning:icon>
                    <span class="slds-assistive-text">Close</span>
                </button>
                <h2 class="slds-text-heading--medium">Edit Record</h2>
            </div>
            <div class="slds-modal__content slds-p-around--medium slds-grid slds-wrap slds-grid--align-spread">
                <lightning:input aura:id="propName" name="propName" label="Property Name" required="true" value="{!v.selectedProperty.fields.Name.value}" class="slds-size--1-of-1 slds-p-horizontal--x-small" />
                <lightning:input aura:id="propBeds" name="propBeds" type="number" label="Beds" value="{!v.selectedProperty.fields.Beds__c.value}" class="slds-size--1-of-2 slds-p-horizontal--x-small" />
                <lightning:input aura:id="propBaths" name="propBaths" type="number" label="Baths" value="{!v.selectedProperty.fields.Baths__c.value}" class="slds-size--1-of-2 slds-p-horizontal--x-small" />
                <lightning:input aura:id="propPrice" name="propPrice" type="number" label="Price" value="{!v.selectedProperty.fields.Price__c.value}" class="slds-size--1-of-2 slds-p-horizontal--x-small" />
                <lightning:input aura:id="propStatus" name="propStatus" label="Status" value="{!v.selectedProperty.fields.Status__c.value}" class="slds-size--1-of-2 slds-p-horizontal--x-small" />
            </div>
            <div class="slds-modal__footer">
                <button class="slds-button slds-button--neutral" onclick="{!c.toggleDialog}">Cancel</button>
                <button class="slds-button slds-button--brand" onclick="{!c.saveRecord}">Save</button>
            </div>
        </div>
    </div>
    <div aura:id="overlay" class="slds-backdrop"></div>
</aura:component>
SimilarPropertyEditController.js
({
    getRecord : function(component) {
        var tempRec = component.find("editRecord");
        tempRec.set("v.recordId", component.get("v.remoteRecordId"));
        tempRec.reloadRecord();
    },
    toggleDialog : function(component, event, helper) {
        helper.showHideModal(component);
    },
    saveRecord : function(component,event,helper) {
        var propBeds = parseInt(component.find('propBeds').get("v.value"), 10);
        var propBaths = parseInt(component.find('propBaths').get("v.value"), 10);
        var propPrice = parseInt(component.find('propPrice').get("v.value"), 10);

        component.set("v.selectedProperty.fields.Beds__c.value", propBeds);
        component.set("v.selectedProperty.fields.Baths__c.value", propBaths);
        component.set("v.selectedProperty.fields.Price__c.value", propPrice);

        var tempRec = component.find("editRecord");
        tempRec.saveRecord($A.getCallback(function(result){
            console.log(result.state);
            if (result.state === "SUCCESS" || result.state === "DRAFT") {
                var event = $A.get("e.c:recordUpdated");
                event.fire();
            } else if (result.state === "ERROR") {
                console.log('Error: ' + JSON.stringify(result.error));
            } else {
                console.log('Unknown problem, state: ' + result.state + ', error: ' + JSON.stringify(result.error));
            }
        }));       
        helper.showHideModal(component);
    }
})
SimilarPropertyEditHelper.js
({
    showHideModal : function(component) {
        var modal = component.find("editDialog");
        $A.util.toggleClass(modal, 'slds-fade-in-open');
        var overlay = component.find("overlay");
        $A.util.toggleClass(overlay, 'slds-backdrop--open');
        component.set("v.showDialog", "false");
    }
})
recordUpdated.evt
<aura:event type="APPLICATION" description="Event template" />
MyPropertyController.apxc
public with sharing class MyPropertyController {
    @AuraEnabled
    public static List<Property__c> getSimilarProperties (Id recordId, String searchCriteria, Decimal beds, Decimal price, Decimal priceRange ) {
         if (searchCriteria == 'Bedrooms') {
             return [
                 SELECT Id, Name, Beds__c, Baths__c, Price__c, Broker__c, Status__c, Thumbnail__c
                 FROM Property__c WHERE Id != :recordId AND Beds__c = :beds
             ];
         } else {
             Decimal range;
             if (priceRange == null) {
                 range = 100000;
             } else {
                 range = priceRange;
             }
             return [
                 SELECT Id, Name, Beds__c, Baths__c, Price__c, Broker__c, Status__c, Thumbnail__c
                 FROM Property__c WHERE Id != :recordId AND Price__c > :price - range AND Price__c < :price + range
             ];
         }
     }
}

PLEASE HELP!
Best Answer chosen by Drew Meyers 3
Patrick McClellanPatrick McClellan
I just completed the challenge after a frustrating process. I didn't even make it to verifying the challenge, I was getting errors when trying to edit the Similar Properties in the browser. I ended up deleting all of the components and starting over. That second time, everything works. 

I had no problem saving everything, even though they have this warning: Save the file. (Note: If you get an error, remove the Similar Properties component on the page in App Builder and then Save.)

I've visually compared my script for SimilarProperties.cmp to yours and I can't see any differences. Here's mine:
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global"  controller="MyPropertyController">
    <aura:attribute name="recordId" type="Id" />
    <aura:attribute name="similarProperties" type="Object[]" />
    <aura:attribute name="property" type="Property__c" />
    <aura:attribute name="remoteRecordId" type="Id" />
    <aura:attribute name="showDialog" type="String" default="false" />
    <aura:attribute name="searchCriteria" type="String" default="Price" />
    <aura:attribute name="priceRange" type="String" default="100000" />
    <aura:handler event="c:recordUpdated" action="{!c.doInit}" />
    <force:recordData aura:id="propertyService"
                      recordId="{!v.recordId}"
                      targetRecord="{!v.property}"
                      recordUpdated="{!c.doInit}"
                      layoutType="FULL" />
    
    <lightning:card iconName="custom:custom85" title="{! 'Similar Properties by ' + v.searchCriteria}" class="slds-is-relative">
        <div class="slds-p-left--medium slds-p-right--medium">
            <ul class="slds-list--vertical slds-has-dividers--top-space">
                <aura:iteration items="{!v.similarProperties}" var="item" indexVar="i">
                    <li class="slds-list__item">                   
                        <c:SimilarProperty propertyId="{!item.Id}" remoteRecordId="{!v.remoteRecordId}" showDialog="{!v.showDialog}" />
                    </li>
                </aura:iteration>
            </ul>
        </div>
        <lightning:spinner aura:id="spinner" variant="brand" size="large"/>
        <c:SimilarPropertyEdit showDialog="{!v.showDialog}" remoteRecordId="{!v.remoteRecordId}" />
    </lightning:card>
</aura:component>

Good luck.

All Answers

Raj VakatiRaj Vakati
Hi , 
You have below two extre attribues . 
<aura:attribute name="searchCriteria" type="String" default="Price" />
<aura:attribute name="priceRange" type="String" default="100000" />
See the code whihc works .
 
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" controller="MyPropertyController" >
    
    <aura:attribute name="recordId" type="Id" />
    <aura:attribute name="similarProperties" type="Object[]" />
    <aura:attribute name="property" type="Property__c" />
    <aura:attribute name="remoteRecordId" type="Id" />
    <aura:attribute name="showDialog" type="String" default="false" />
    <aura:handler event="c:recordUpdated" action="{!c.doInit}" />

    <force:recordData aura:id="propertyService"
                      recordId="{!v.recordId}"
                      targetRecord="{!v.property}"
                      recordUpdated="{!c.doInit}"
                      layoutType="FULL" />
    
    <lightning:card iconName="custom:custom85" title="Similar Properties">
        <div class="slds-p-left--medium slds-p-right--medium">
            <ul class="slds-list--vertical slds-has-dividers--top-space">
                <aura:iteration items="{!v.similarProperties}" var="item" indexVar="i">
                   <c:SimilarProperty propertyId="{!item.Id}" remoteRecordId="{!v.remoteRecordId}" showDialog="{!v.showDialog}" />

                </aura:iteration>
            </ul>
        </div>
        <lightning:spinner aura:id="spinner" variant="brand" size="large"/>

        <c:SimilarPropertyEdit showDialog="{!v.showDialog}" remoteRecordId="{!v.remoteRecordId}" />

    </lightning:card>
    
</aura:component>




 
Drew Meyers 3Drew Meyers 3
SimilarProperties.cmp does not save with that code. Says it does not have searchCriteria attribute..
Raj VakatiRaj Vakati
Take searchCriteria  attribute out from your designer 
Drew Meyers 3Drew Meyers 3
searchCriteria, and priceRange are used throughout most of the SimilarProperty files, the unit has you add them in about half way through.
Patrick McClellanPatrick McClellan
I just completed the challenge after a frustrating process. I didn't even make it to verifying the challenge, I was getting errors when trying to edit the Similar Properties in the browser. I ended up deleting all of the components and starting over. That second time, everything works. 

I had no problem saving everything, even though they have this warning: Save the file. (Note: If you get an error, remove the Similar Properties component on the page in App Builder and then Save.)

I've visually compared my script for SimilarProperties.cmp to yours and I can't see any differences. Here's mine:
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global"  controller="MyPropertyController">
    <aura:attribute name="recordId" type="Id" />
    <aura:attribute name="similarProperties" type="Object[]" />
    <aura:attribute name="property" type="Property__c" />
    <aura:attribute name="remoteRecordId" type="Id" />
    <aura:attribute name="showDialog" type="String" default="false" />
    <aura:attribute name="searchCriteria" type="String" default="Price" />
    <aura:attribute name="priceRange" type="String" default="100000" />
    <aura:handler event="c:recordUpdated" action="{!c.doInit}" />
    <force:recordData aura:id="propertyService"
                      recordId="{!v.recordId}"
                      targetRecord="{!v.property}"
                      recordUpdated="{!c.doInit}"
                      layoutType="FULL" />
    
    <lightning:card iconName="custom:custom85" title="{! 'Similar Properties by ' + v.searchCriteria}" class="slds-is-relative">
        <div class="slds-p-left--medium slds-p-right--medium">
            <ul class="slds-list--vertical slds-has-dividers--top-space">
                <aura:iteration items="{!v.similarProperties}" var="item" indexVar="i">
                    <li class="slds-list__item">                   
                        <c:SimilarProperty propertyId="{!item.Id}" remoteRecordId="{!v.remoteRecordId}" showDialog="{!v.showDialog}" />
                    </li>
                </aura:iteration>
            </ul>
        </div>
        <lightning:spinner aura:id="spinner" variant="brand" size="large"/>
        <c:SimilarPropertyEdit showDialog="{!v.showDialog}" remoteRecordId="{!v.remoteRecordId}" />
    </lightning:card>
</aura:component>

Good luck.
This was selected as the best answer
Drew Meyers 3Drew Meyers 3
Whatever the small differences were allowed me to complete. Thank you!
Cloud EliteCloud Elite
Guys - can anyone explain the apex class controller, what did it mean by price range ? can you explain it how it define it as range ? 
Sandra Kuc 9Sandra Kuc 9

Hello guys, what about this one?

"We didn't find SimilarProperties.design with the necessary attributes. Check the copied code and try again."

<design:component label="Similar Properties">
    <sfdc:objects>
        <sfdc:object>Property__c</sfdc:object>
    </sfdc:objects>
    <design:attribute name="searchCriteria" label="Search By" datasource="Bedrooms, Price" default="Price" description="Search for similar houses based on what criteria?" />
    <design:attribute name="priceRange" label="Price Range" default="100000" description="When searching by Price, search using the price plus or minus this amount" />   
</design:component>
Sandra Kuc 9Sandra Kuc 9

If someone ever had this message:

"We didn't find SimilarProperties.design with the necessary attributes. Check the copied code and try again."

Replace this:

<design:attribute name="searchCriteria" label="Search By" datasource="Bedrooms, Price" default="Price" description="Search for similar houses based on what criteria?" />
    <design:attribute name="priceRange" label="Price Range" default="100000" description="When searching by Price, search using the price plus or minus this amount" />


for this:

<design:attribute name="searchCriteria" label="Search By" datasource="Bedrooms, Price, Sq Foot" default="Price" description="Search for similar houses based on what criteria?"/>
<design:attribute name="priceRange" label="Price Range" default="100000" description="When searching by Price, search using the price plus or minus this amount"/>


in the SimilarProperties.desin file.

They're simply checking that you are not too lazy for do this task step by step and you do not go to the end to the page to copy ready code. It's a trap!