• PatMcClellan__c
  • NEWBIE
  • 150 Points
  • Member since 2017
  • Proton 7 Grouop

  • Chatter
    Feed
  • 2
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 9
    Questions
  • 60
    Replies
Hi,

I'm currently struggling with Lightning Component Framework Specialist Challenge 10.

The map is behaving as expected, but when I submit, I get the error:
Challenge Not yet complete... here's what's wrong: 
MapController.js must have an event handler named onPlotMapMarker that uses the latitude and longitude that were passed through the event to update the boat’s location.

This is my onPlotMarker() method:
onPlotMapMarker: function(component, event, helper) {
    	var id = event.getParam('sObjectId');
    	var latitude = event.getParam('lat');
    	var longitude = event.getParam('long');
    	var label = event.getParam('label');

		var leafletMap = helper.getLeafletMap(component, latitude, longitude);
		L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', {
		    attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
		}).addTo(leafletMap);
		
		L.marker([latitude, longitude]).addTo(leafletMap)
		    .bindPopup(label)
		    .openPopup();
    }
This is the helper:
({
	getLeafletMap : function(component, latitude, longitude) {
		var leafletMap = component.get('v.leafletMap');
		
		if (!leafletMap) {
	    	var mapContainer = component.find('map').getElement(); 
		    leafletMap = L.map(mapContainer, {zoomControl: false, tap: false})
		    	.setView([latitude, longitude], 13);
		    component.set('v.leafletMap', leafletMap);
		}

		return leafletMap;
	}
})
This is the aura:attribute for leafletMap:
<aura:attribute access="private" name="leafletMap" type="Object" />

Any help will be appreciated!






 
Hi,

I'm currently working on the Lightning Component Framework Specialist Superbadge.

When I click "New", at least as I've interpretted the requirements, the "Friends with Boats" pages is behaving as expected, but Trailhead complains:
Challenge Not yet complete... here's what's wrong: 
The BoatSearchForm component's "New" button should launch the default boat record create page using logic in its controller.

Have I misunderstood a requirement?

Here is my markup:
 
<aura:component controller="BoatSearchFormAuraCtrl" >
	<aura:attribute access="private" name="boatList" type="BoatType__c[]" default="[]" />
	<aura:attribute access="private" name="showNewButton" type="Boolean" default="false" />
	<aura:attribute access="private" name="selectedBoat" type="BoatType__c" />
	
	<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
	
	<h2 class="slds-page-header__title">Find a Boat</h2>
	<form>
		<lightning:layout horizontalAlign="center">
		    <lightning:select name="select" value="{!v.selectedBoat}">
		        <option value="">All Types</option>
		        <aura:iteration items="{!v.boatList}" var="boat">
		            <option value="{!boat.Name}" text="{!boat.Name}"></option>
		        </aura:iteration> 
		    </lightning:select>
		    <lightning:button name="Search" label="Search" variant="brand" />
		    <aura:if isTrue="{!v.showNewButton}">
		    	<lightning:button name="New" label="New" variant="neutral" onclick="{!c.createBoat}"/>
		    </aura:if>
		</lightning:layout>
	</form>	
</aura:component>
And here is my controller:
({
	doInit : function(component, event, helper) {
		component.set('v.showNewButton', $A.get('e.force:createRecord'));
		helper.setBoatTypeList(component);
	},
	
	createBoat : function(component) {
		var createRecordEvent = $A.get('e.force:createRecord');
		createRecordEvent.setParams({
			'entityApiName' : 'BoatType__c',
			'defaultFieldValues': {
				'Name': component.get('v.selectedBoat')
			},
		});
		createRecordEvent.fire();
	}
})





 
I'm trying to understand the efficiencies of Lightning Data Service versus using APEX. I DO understand that many people have a phobia regarding APEX, but I don't, so that's not a benefit to me. I'm really asking about things like performance (responsiveness), demands on the server, governor limits, etc.

Here's a specific example:
I'm building a Lightning Component (list.cmp) that iterates through 20 message__c records, using a tile.cmp to display 5 fields from message__c on each of the record tiles in the scrollable list. I can accomplish this 2 ways.
  1. listController calls APEX, returning a list<message__c>  of the 20 records with 5 fields per record. I aura:iterate through the list, passing a message__c object as the parameter. The tile.cmp receives the full message__c object and builds the tile. Or...
  2. listController calls APEX, returning a list of message__c Id numbers. I aura:iterate through the list passing only the recordId to tile.cmp, which uses force:recordData to pull the record data using LDS, then builds the tile.
Either way, I have to do a SOQL query, but in the second instance, I'm just pulling recordIds. I do understand that if those same message__c records are displayed in other components on the page, that changes in one place will be automatically reflected elsewhere, but for this example, that's not the case. Just viewing the data in this one place. So this is strictly a question about performace.

I have actually already built this using the first method and it works fine, but I'm really trying to drink the LDS Kool-Aid and use it wherever it makes sense. I just need more info to understand whether it makes sense.

Same question for saving a new record via LDS vs APEX. Is LDS faster? easier on the server? better with regard to governor limits?
 
I know LDS only connects to one record at a time, but is that per component?
I want to use LDS on custom (parent) component ConversationDisplay to access a conversation__c record, and use LDS to create a new Message__c record from my (child) MessageEntry component that is included in Conversation Display. Possible?
I'm using LDS to create a new record -- it's a simple one field input. After input, the record is saved and the init handler for the component runs again, clearing out my {!v.Message} attribute -- I have verified that this new record is "empty". However, when I enter a new message, it is overwriting the previously saved record instead of creating a new record.

Do I need to do a full reload (instead of a refreshView) of the component to get a fresh new record? If so, the docs are not clear on that process (see code below). Specifically, does this go in the Controller for the component I'm refreshing? If so, then what's the 'c.myController' reference? 
refresh : function(component, event, helper) {
    var action = cmp.get('c.myController');
    action.setCallback(cmp,
        function(response) {
            var state = response.getState();
            if (state === 'SUCCESS'){
                $A.get('e.force:refreshView').fire();
            } else {
                 //do something
            }
        }
    );
    $A.enqueueAction(action);
}

 
I'm seeking more info on lightning:input for use in a Lightning Component.

What I want to do is have the input text field submit when the user presses the Enter key. However, the Enter key seems to be ignored by lightning:input. Also, I can't even retrieve the keycode with my handler.

component markup:
                  <lightning:input aura:id="body"
                                         label=""
                                         name="Body"
                                         placeholder="Enter message..."
                                         value="{!v.Message.Body__c}"
                                         onchange="{!c.keyCheck}"/>

                    </lightning:layoutItem>
And my keyCheck handler:
keyCheck: function(component, event, helper){
        console.log(event.getParams('keyCode')); 
        }
The handler is getting called, but the value is undefined. I think it's undefined because the event that is happening is NOT the keypress/keyDown/keyUp, but rather the input field is changing. But lightning:input chokes (won't compile) if I try to add a keyDown event in its parameters in the markup.

BTW, I've tried doing this with ui:inputText as well, and that doesn't work either.

Help please?

 

I'm building a Lightning Component that includes a ui:scrollerWrapper, containing an aura:iteration. I want the scroller to default scrollTo the bottom. 

I found this documentation: https://developer.salesforce.com/docs/atlas.en-us.208.0.lightning.meta/lightning/aura_compref_ui_scrollerWrapper.htm? that lists the Methods, including scrollTo(destination) where destination is a string with options "top", "bottom", "left" and "right".  But I can't figure out where to put that method.

My component markup:
 

<ui:scrollerWrapper class="scrollerSize" aura:Id="scroller">

        <aura:iteration items="{!v.messages}" var="message">
            <c:MessageTile message="{!message}" inits="{!v.conversation.GroupInits__c}"/>
        </aura:iteration>

    </ui:scrollerWrapper>
My css:
.THIS.scrollerSize {
    height: 400px;
}
I tried this in the doInit handler:
var scroller = component.find("scroller");
scroller.scrollTo('bottom');
But it doesn't work.

Advice?

 
I have the BoatReviews.cmp built and it looks correct, but I'm not sure the best way to pull the boatReview.CreatedById from the link on the name. I'm thinking it should be coded into the iteration markup, then the onUserInfoClick handler could extract the boatReview.CreatedById from the event... but I can't figure out how to make that work.

I've tried <a href> and <ui:outputURL> in the markup... can't make it work.

How about a hint?
Cross-posting here from the Trailhead forum, where I'm working on the Lightning Components Framework SuperBadge. We're implementing LDS on a page, but NOT using force:hasRecordId. Instead, we're dynamically setting an aura:attribute, and then referencing it in the LDS parameter for recordId. I've been researching this for hours, but all the reference docs and Trailhead modules assume the case where you're using the implicit recordId on the page. No examples I can find where they're setting the recordId and then forcing the reload.

In this case, the id attribute is successfully being set, but LDS isn't loading the record. The error message says: The onBoatSelected handler in the BoatDetails controller must force Lightning Data Service to load the specified record, using logic in the controller.

In the controller, I'm using a reloadRecord command: component.find("service").reloadRecord() where "service" is the aura:id for the force:recordData element.

Is there some other command required to get the LDS to load the record?

Here's the component markup with the force:recordData info:
<aura:attribute name="id" type="String"/>
    <aura:attribute name="boat" type="Boat__c"/>
    <aura:attribute name="boatSimple" type="Boat__c"/>
    <aura:attribute name="recordError" type="String"/>

    <aura:handler event="c:BoatSelected" action="{!c.onBoatSelected}"/>

    <force:recordData aura:id="service"
                      recordId="{!v.id}"
                      mode="VIEW"
                      fields=  "Id,
                                Name,
                                Description__c,
                                Price__c, Length__c,
                                Contact__r.Name,
                                Contact__r.Email,
                                Contact__r.HomePhone,
                                BoatType__r.Name,
                                Picture__c"
                      targetRecord="{!v.boat}"
                      targetFields="{!v.boatSimple}"
                      targetError="{!v.recordError}"
                      recordUpdated="{!c.onRecordUpdated}" />
Am I screwing up something in the markup? 

 
I've got this challenge all wired up, but I have 2 issues. First, the selected boat highlight only works if I name the style "selected". If I call it "tile selected" it breaks (no error, just doesn't show a highlight). I know the 'selected' parameter is being passed correctly -- as I mentioned, it works great with a different style name, but the validation is checking for the specific name 'tile selected'.

If I change the style name to 'tile selected', the validation makes it past that part of the test, even though the CSS styling isn't working right.

The second issue in the validation says: BoatSearchResults.cmp must handle the BoatSelect event by calling a controller function named onBoatSelect. Here's the code I have in BoatSearchResults.cmp:
<aura:handler name="BoatSelect" event="c.BoatSelect" action="{!c.onBoatSelect}" />
And here's the handler in BoatSearchResultsController.js:
onBoatSelect: function(component, event, helper){
        component.set("v.selectedBoatId", event.getParam("boatId"));  
    }
I'm not sure why the validation is choking on this. Any ideas? Did I miss something?



 
I'm not clear why they're instructing us to package up the BoatTypeId as a property of an object called formData. Why not just pass the BoatTypeId directly?  Here's what it says:
 
Use a new event c:FormSubmit named formsubmit with an Object attribute named formData to pass the selected boatTypeId—as a property of formData—from BoatSearchForm to its parent component BoatSearch. Do this via a controller function called onFormSubmit() attached to the Search button.
In the 
BoatSearch component, handle FormSubmit with a controller action named onFormSubmit. Pass formData.boatTypeId from the controller to a public method on the BoatSearchResults component called search.
 
Why not just do this:
onFormSubmit : function(component, event, helper){
        var boatTypeId = component.get("v.selectedType");
        console.log("Search button pressed " + boatTypeId);
        var formSubmit = component.getEvent("formsubmit");
        formSubmit.setParams({"boatTypeId": boatTypeId});
        formSubmit.fire();
    },

 
Hi, I have a problem. When I want to create a Master-Detail Relationship which is has to be related to Property in the field "Select the other object to which this object is related" | "Related To" I don't have such option as "Property".
I know LDS only connects to one record at a time, but is that per component?
I want to use LDS on custom (parent) component ConversationDisplay to access a conversation__c record, and use LDS to create a new Message__c record from my (child) MessageEntry component that is included in Conversation Display. Possible?
I'm using LDS to create a new record -- it's a simple one field input. After input, the record is saved and the init handler for the component runs again, clearing out my {!v.Message} attribute -- I have verified that this new record is "empty". However, when I enter a new message, it is overwriting the previously saved record instead of creating a new record.

Do I need to do a full reload (instead of a refreshView) of the component to get a fresh new record? If so, the docs are not clear on that process (see code below). Specifically, does this go in the Controller for the component I'm refreshing? If so, then what's the 'c.myController' reference? 
refresh : function(component, event, helper) {
    var action = cmp.get('c.myController');
    action.setCallback(cmp,
        function(response) {
            var state = response.getState();
            if (state === 'SUCCESS'){
                $A.get('e.force:refreshView').fire();
            } else {
                 //do something
            }
        }
    );
    $A.enqueueAction(action);
}

 
I'm seeking more info on lightning:input for use in a Lightning Component.

What I want to do is have the input text field submit when the user presses the Enter key. However, the Enter key seems to be ignored by lightning:input. Also, I can't even retrieve the keycode with my handler.

component markup:
                  <lightning:input aura:id="body"
                                         label=""
                                         name="Body"
                                         placeholder="Enter message..."
                                         value="{!v.Message.Body__c}"
                                         onchange="{!c.keyCheck}"/>

                    </lightning:layoutItem>
And my keyCheck handler:
keyCheck: function(component, event, helper){
        console.log(event.getParams('keyCode')); 
        }
The handler is getting called, but the value is undefined. I think it's undefined because the event that is happening is NOT the keypress/keyDown/keyUp, but rather the input field is changing. But lightning:input chokes (won't compile) if I try to add a keyDown event in its parameters in the markup.

BTW, I've tried doing this with ui:inputText as well, and that doesn't work either.

Help please?

 

I'm building a Lightning Component that includes a ui:scrollerWrapper, containing an aura:iteration. I want the scroller to default scrollTo the bottom. 

I found this documentation: https://developer.salesforce.com/docs/atlas.en-us.208.0.lightning.meta/lightning/aura_compref_ui_scrollerWrapper.htm? that lists the Methods, including scrollTo(destination) where destination is a string with options "top", "bottom", "left" and "right".  But I can't figure out where to put that method.

My component markup:
 

<ui:scrollerWrapper class="scrollerSize" aura:Id="scroller">

        <aura:iteration items="{!v.messages}" var="message">
            <c:MessageTile message="{!message}" inits="{!v.conversation.GroupInits__c}"/>
        </aura:iteration>

    </ui:scrollerWrapper>
My css:
.THIS.scrollerSize {
    height: 400px;
}
I tried this in the doInit handler:
var scroller = component.find("scroller");
scroller.scrollTo('bottom');
But it doesn't work.

Advice?

 
Hi,

I'm currently struggling with Lightning Component Framework Specialist Challenge 10.

The map is behaving as expected, but when I submit, I get the error:
Challenge Not yet complete... here's what's wrong: 
MapController.js must have an event handler named onPlotMapMarker that uses the latitude and longitude that were passed through the event to update the boat’s location.

This is my onPlotMarker() method:
onPlotMapMarker: function(component, event, helper) {
    	var id = event.getParam('sObjectId');
    	var latitude = event.getParam('lat');
    	var longitude = event.getParam('long');
    	var label = event.getParam('label');

		var leafletMap = helper.getLeafletMap(component, latitude, longitude);
		L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', {
		    attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
		}).addTo(leafletMap);
		
		L.marker([latitude, longitude]).addTo(leafletMap)
		    .bindPopup(label)
		    .openPopup();
    }
This is the helper:
({
	getLeafletMap : function(component, latitude, longitude) {
		var leafletMap = component.get('v.leafletMap');
		
		if (!leafletMap) {
	    	var mapContainer = component.find('map').getElement(); 
		    leafletMap = L.map(mapContainer, {zoomControl: false, tap: false})
		    	.setView([latitude, longitude], 13);
		    component.set('v.leafletMap', leafletMap);
		}

		return leafletMap;
	}
})
This is the aura:attribute for leafletMap:
<aura:attribute access="private" name="leafletMap" type="Object" />

Any help will be appreciated!






 
I have the BoatReviews.cmp built and it looks correct, but I'm not sure the best way to pull the boatReview.CreatedById from the link on the name. I'm thinking it should be coded into the iteration markup, then the onUserInfoClick handler could extract the boatReview.CreatedById from the event... but I can't figure out how to make that work.

I've tried <a href> and <ui:outputURL> in the markup... can't make it work.

How about a hint?
Cross-posting here from the Trailhead forum, where I'm working on the Lightning Components Framework SuperBadge. We're implementing LDS on a page, but NOT using force:hasRecordId. Instead, we're dynamically setting an aura:attribute, and then referencing it in the LDS parameter for recordId. I've been researching this for hours, but all the reference docs and Trailhead modules assume the case where you're using the implicit recordId on the page. No examples I can find where they're setting the recordId and then forcing the reload.

In this case, the id attribute is successfully being set, but LDS isn't loading the record. The error message says: The onBoatSelected handler in the BoatDetails controller must force Lightning Data Service to load the specified record, using logic in the controller.

In the controller, I'm using a reloadRecord command: component.find("service").reloadRecord() where "service" is the aura:id for the force:recordData element.

Is there some other command required to get the LDS to load the record?

Here's the component markup with the force:recordData info:
<aura:attribute name="id" type="String"/>
    <aura:attribute name="boat" type="Boat__c"/>
    <aura:attribute name="boatSimple" type="Boat__c"/>
    <aura:attribute name="recordError" type="String"/>

    <aura:handler event="c:BoatSelected" action="{!c.onBoatSelected}"/>

    <force:recordData aura:id="service"
                      recordId="{!v.id}"
                      mode="VIEW"
                      fields=  "Id,
                                Name,
                                Description__c,
                                Price__c, Length__c,
                                Contact__r.Name,
                                Contact__r.Email,
                                Contact__r.HomePhone,
                                BoatType__r.Name,
                                Picture__c"
                      targetRecord="{!v.boat}"
                      targetFields="{!v.boatSimple}"
                      targetError="{!v.recordError}"
                      recordUpdated="{!c.onRecordUpdated}" />
Am I screwing up something in the markup? 

 

Hello all,

I'm currently working through Step 7 of the new "Lightning Component Framework Specialist" superbadge, and I'm running into an error while checking the challenge:

"The AddBoatReview controller's onSave() function doesn't fire the BoatReviewAdded event."

The problem is that I'm testing the component right now, and my event is being received by the parent just fine, and my tabset switches to the "Reviews" section like it should, so know it's being handled correctly. I've tried using both a Component event and an Application event just to debug a bit (even though Component is the best option for this scenario), and that doesn't change anything. Any idea what could be triggering this error message?

Relevant code:

AddBoatReviewController.js

onSave : function(component, event, helper){
    	component.set("v.boatReview.Boat__c",component.get("v.boat.Id"));

        component.find("service").saveRecord(function(saveResult) {
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {

               var cmpEvent = component.getEvent("reviewAdded");
		       cmpEvent.fire();

               //Attempt at trying an Application event instead
		       //var cmpEvent = $A.get("e.c:BoatReviewAdded");
		       //cmpEvent.fire();


                var resultsToast = $A.get("e.force:showToast");
                //Toast code and other saveResults states below...
AddBoatReview.cmp
<aura:registerEvent name="reviewAdded" type="c:BoatReviewAdded"/>
     
    <!-- Display form -->
    <lightning:layout multipleRows="true">
            <lightning:layoutItem size="12" padding="around-small">
                <lightning:input name="title" label="Title" value="{!v.boatReview.Name}"/>
            </lightning:layoutItem>

            <lightning:layoutItem size="12" padding="around-small">
                <label class="slds-form-element__label" for="input-id-01">Description</label>
                <lightning:inputRichText value="{!v.boatReview.Comment__c}" disabledCategories="FORMAT_FONT"/>
            </lightning:layoutItem>

            <lightning:layoutItem size="12" class="slds-align--absolute-center">
                <lightning:button iconName="utility:save" label="Submit" onclick="{!c.onSave}"/>
            </lightning:layoutItem>
    </lightning:layout>
BoatDetails.cmp
<aura:handler name="reviewAdded" event="c:BoatReviewAdded" action="{!c.onBoatReviewAdded}"/>

BoatDetailsController.js

onBoatReviewAdded : function(component, event, helper) {
	console.log("Event received");
	component.set("v.selTabId", "boatreviewtab");
}
We're instructed to send an email to the finance group -- that's pretty vague. I'm going to create a Finance group, made up of the CFO and subordinates. Am I missing something in the instructions?