+ Start a Discussion
SFDC93 SfSFDC93 Sf 

Superbadge - Lightning Component Framework Specialist

Hi Friends, 
I'm struggling with some of the tasks here in the super badge. Please, can you share me a source code? I will start from scratch again. I have created multiple trailhead playgrounds still messed up somehow. Here is my current error "Challenge Not yet complete... here's what's wrong: 
The BoatSearchForm component is missing a lightning
: select component. Double check the requirements and try again." even though I have above component in my code list. 
I will tell you what I did so far for this task.
1. Created mentioned custom objects in the new Trailhead Playground org with the relationships and all. 
2. Developed some of the code. Please check the below code.

--------------------------------------------------------------------
BoatSearch.cmp
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" access="global" >
<lightning:card title="Find a Boat" class="slds-m-top_10px" >
     <c:BoatSearchForm />
</lightning:card>    
<lightning:card title="Matching Boats" >
     <c:BoatSearchResults /> 
</lightning:card>
<aura:handler name="formsubmit"
                  event="c:FormSubmit"
                  action="{!c.onFormSubmit}"
                  phase="capture"/>

</aura:component>
--------------------------------------------------------------------

BoatSearchResults.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" 
                access="global" controller="BoatSearchResults">
    <aura:handler name="init" action="{!c.doSearch}" value="{!this}"/>
    <aura:attribute name="boatTypeId" type="String" />
    <aura:attribute name="boats" type="Boat__c[]" />  
    <!--<aura:method name="search" description="Sample method with parameter">
        <aura:attribute name="boatTypeId" type="String"  />
    </aura:method>-->
    <!-- set up the aura:method for search -->
    <aura:method name="search" description="accepts boatTypeId
            and executes search that refreshes the boats attribute">
        <aura:attribute name="boatTypeId" type="Id"/>
    </aura:method>
    <!-- Display errors, if any -->
    <!--
    <aura:if isTrue="{!not(empty(v.errorString))}">
        <div class="recordError">
            <ui:message title="Error" severity="error" closable="true">
                {!v.errorString}
            </ui:message>
        </div>
    </aura:if>-->
    <aura:if isTrue="{!not(empty(v.boats))}">
        <lightning:layout multipleRows="true" horizontalAlign="center">
                <aura:iteration items="{!v.boats}" var="boatVar">
                    <lightning:layoutItem flexibility="grow"  class="slds-m-right_small" >   
                        <c:BoatTile boat="{!boatVar}"/>
                    </lightning:layoutItem>
                </aura:iteration>
        </lightning:layout>
         <aura:set attribute="else">
            <div class="slds-align_absolute-center">No boats found</div>
        </aura:set>
    </aura:if>
</aura:component>
----------------------------------------------------------------
BoatSearchForm.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" controller="BoatSearchFormController" >
    <aura:handler name="formsubmit"
                  event="c:FormSubmit"
                  action="{!c.onFormSubmit}"
                  phase="capture"/>
    
    <aura:attribute name="searchOptions" type='String[]' default='All'/>
    <aura:attribute name='searchOptionToIdMap' type='Map' default="{All:''}" />
    <aura:attribute name='showNewButton' type='Boolean' default='false'/>

        
    <lightning:layout horizontalAlign="center"   >

       <lightning:layoutItem class="slds-grid_vertical-align-center" >

           <lightning:select aura:id='typeSelect' name='selectItem' label='' onchange=''>
             <aura:iteration items='{!v.searchOptions}' var='option'>
                 <option value='{!option}' text='{!option}'></option>
             </aura:iteration>
         </lightning:select>
       </lightning:layoutItem>

       <lightning:layoutItem class="slds-grid_vertical-align-center" >
         <lightning:button label="Search" variant="brand" onclick='{!c.onFormSubmit}' />
         <aura:if isTrue='{!v.showNewButton}'>
            <lightning:button variant='neutral' label='New' onclick='{!c.createBoat}'/>
        </aura:if>
       </lightning:layoutItem>

    </lightning:layout>

</aura:component>
-------------------------------------------------------------------------------

BoatSearchFormController.js

({    createBoat: function (component,event,helper) {
        var createRecordEvent = $A.get('e.force:createRecord');
        if (createRecordEvent) {
            var typeName = component.find('typeSelect').get('v.value');
            var typeMap = component.get('v.searchOptionToIdMap');
            var typeId = null;
            if (typeName && typeMap && typeMap[typeName]) {
                typeId = typeMap[typeName];
            }
            createRecordEvent.setParams({
                'entityApiName': 'Boat__c',
                'defaultFieldValues': {
                    'BoatType__c': typeId
                }
            });
            createRecordEvent.fire();
        }
    },
    
    onFormSubmit : function(component, event, helper){
        var boatTypeId = component.get("v.selectedType");
        console.log("Search button pressed " + boatTypeId);
        var formSubmit = component.getEvent("FormSubmit");
        formSubmit.setParams({"formData":
                            {"boatTypeId" : boatTypeId}
        });
        formSubmit.fire();
    },   
})
--------------------------------------------------------------
 BoatSearchResults.apxc

public with sharing class BoatSearchResults  {
    @AuraEnabled
     public static List <Boat__c> getBoats(String boatTypeId) {
      if(boatTypeId != '')  {
             return [SELECT id, BoatType__c, picture__c, name,contact__r.Name
                    FROM Boat__c
                    WHERE BoatType__c =:boatTypeId];
      } else {
          return [SELECT id, BoatType__c, picture__c, name,contact__r.Name
                    FROM Boat__c];
      }
         }
         }
------------------------------------------------------------
BoatSearchResultsHelper.js

({
    onSearch : function(component) {
        var action = component.get("c.getBoats");
        action.setParam({"boatTypeId":""});
        action.setCallback(this, function(response){
        var status = response.getState();
            if(status === "SUCCESS"){
             if(! $A.util.isEmpty(response.getReturnValue())){
                    component.set("v.boatTypeId",response.getReturnValue()); 
                } else {
                     component.set("v.recordError","No boats found");
                }
            }
        });
        $A.enqueueAction(action);
    }
})
-----------------------------------------------------------------
 FormSubmit.evt

<aura:event type="COMPONENT" description="Boat Event">
    <aura:attribute name="formData" type="Object"/>
    
</aura:event>
-------------------------------------------------------------------------
BoatSearchController.js

({
    onFormSubmit : function(component, event, helper){
        console.log("event received by BoatSearchController.js");
        var formData = event.getParam("formData");
        var boatTypeId = formData.boatTypeId;
        var BSRcmp = component.find("BSRcmp");
        var auraMethodResult = BSRcmp.search(boatTypeId);
        console.log("auraMethodResult: " + auraMethodResult);
    }
})
---------------------------------------------------------------------------
BoatTile.cmp
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes">
 <aura:attribute name="boat" type="Boat__c" />
    <aura:attribute name="selected" type="String" />
 <lightning:button class="tile">
        <div style="{!'background-image:url(\'' + v.boat.Picture__c + '\'); '}" class="innertile">
          <div class="lower-third">
           <h1 class="slds-truncate">{!v.boat.Contact__r.Name}</h1>
          </div>
        </div>
    </lightning:button>
 </aura:component>
--------------------------------------------------------------------------------
Any help much appreciated. I would love to hear some new tips and new techniques with this task. If you share some source code that would greately appreciated. 

Thank you
Raj VakatiRaj Vakati
Use this code for BoatSearchForm.cmp

https://github.com/donaldrivard/Lightning_Component_Framework_Specialist/blob/master/force-app/main/default/aura/BoatSearchForm/BoatSearchFormHelper.js​
 
<aura:component controller="BoatUtils" implements="flexipage:availableForAllPageTypes" access="global"> 
        <aura:registerEvent name="formsubmit" type="c:FormSubmit"/>
    
<aura:attribute name="options" type="BoatType__c[]" />
    <aura:attribute name="selectedValue" type="String" default=""/>
    <aura:handler name="init" value="{!this}" action="{!c.loadOptions}" />
    <aura:attribute name='showNewButton' type='Boolean' default='false'/>

    <aura:method name="checkShowNewButton" action="{!c.loadButton}" />
    <aura:method name="loadBoatTypes" action="{!c.loadOptions}" />
    
    <lightning:layout horizontalAlign="center">
    
    <lightning:layoutItem flexibility="auto" padding="horizontal-small">
       <lightning:select name="boatSelect" label="" aura:id="boatSelect" value="{!v.selectedValue}">
        <option text="All Types" value=""/>
        <aura:iteration items="{!v.options}" var="item">
               <option text="{!item.Name}" value="{!item.Id}" selected="{!item.selected}"/>
         </aura:iteration>
         
    </lightning:select>
    </lightning:layoutItem>
    
    <lightning:layoutItem flexibility="auto" padding="around-medium">
    		<lightning:button variant="brand" label="Search" onclick="{! c.onFormSubmit }" aura:id="SearchButton" />
    
            <aura:if isTrue='{!v.showNewButton}'>
                <lightning:button variant="neutral" label="New" onclick="{! c.createRecord }" aura:id="NewButton"/>
            </aura:if>
        </lightning:layoutItem>         
</lightning:layout>


</aura:component>
 
({
    loadOptions: function (component, event, helper) {
            helper.getTypesOfBoats(component);
            helper.renderNewButton(component);

    },

    loadBoats: function (component, event, helper) {
        helper.getTypesOfBoats(component);
    },

    loadButton: function (component, event, helper) {
        helper.renderNewButton(component);

    },

    createRecord : function (component, event, helper) {
        
        var boat = component.find("boatSelect").get("v.value");
        if(!boat){
            boat = null;
        }
        var createRecordEvent = $A.get("e.force:createRecord");
        createRecordEvent.setParams({
            "entityApiName": "Boat__c",
            "defaultFieldValues": {
                'BoatType__c' : boat
            }

        });
        createRecordEvent.fire();
    },

    fuckme :  function(component, event, helper){
            console.log('fucking JOKE');
    },
    onFormSubmit : function(component, event, helper){
        var boatTypeId = component.get("v.selectedValue");
        console.log("Search button pressed " + boatTypeId);
        var formSubmit = component.getEvent("formsubmit");
        formSubmit.setParams({"formData":
                            {"boatTypeId" : boatTypeId}
        });
        formSubmit.fire();
    },
})
 
({
    getTypesOfBoats : function(component) {
    		var action = component.get("c.getBoatTypes");
    		action.setCallback(this, function(response) {
                var state = response.getState();
                if (state === "SUCCESS") {
                		component.set("v.options", response.getReturnValue());
                }
                
                else if (state === "INCOMPLETE") {
                    // do something
                }
                else if (state === "ERROR") {
                    var errors = response.getError();
                    if (errors) {
                        if (errors[0] && errors[0].message) {
                            console.log("Error message: " + 
                                     errors[0].message);
                        }
                    } else {
                        console.log("Unknown error");
                    }
                }
            });

            // optionally set storable, abortable, background flag here

            // A client-side action could cause multiple events, 
            // which could trigger other events and 
            // other server-side action calls.
            // $A.enqueueAction adds the server-side action to the queue.
            $A.enqueueAction(action);
    		
    		
    	
    },
    renderNewButton: function (component) {
        var createRecordEvent = $A.get('e.force:createRecord');
        if (createRecordEvent) {
            component.set('v.showNewButton', true);
            
        }
    }
})

 
Kalidas PonrajKalidas Ponraj
Failed to save BoatSearchForm.cmp: No EVENT named markup://c:launchNewBoatForm found : [markup://c:BoatSearchForm]: Source

When i saving BoatSearchForm i got this kind of error.....plz help me to solve the challenge 2