Lightning Web Component Specialist Super badge: Challenge 7 - salesforce

I am having trouble solving the Challenge 7 I have the required imports as well as required functions in the JS file. Still #Trailhead giving error:
We can’t find the getLocationFromBrowser() function in the component boatsNearMe controller. Make sure the component was created according to the requirements, including the use of 'getCurrentPosition()' to get the navigator’s geolocation, the arrow notation with 'position =>', getting the coordinates from the position, and assigning them to the controller’s properties 'latitude' and 'longitude, using the proper case sensitivity.
---- Removed the CODE Section in order to stay with Trailhead's Policy ----
I guess this is something which i am missing out in the code.

Your references to the Geolocation Latititude and Longitudes are missing an "_"
You have them like this (single underscores);
rowBoat.Geolocation_Latitude_s
And this need to be like this (double underscores);
rowBoat.Geolocation__Latitude__s
I haven't gone through all the code, but at least these look wrong in your code.
Also, not sure that the #track is explicitly needed in this case (anymore).

The verification code is extremely picky. If you remove the parentheses around the word position, I think it will work.

You can try 2 changes to pass the challenge,
remove the parentheses around position from the callback function of getCurrentPosition
follow below steps to rectify mapMarkers creation code
The data that is passed to the createMapMarkers is of below format,
'[{"attributes":{"type":"Boat__c","url":"/services/data/v48.0/sobjects/Boat__c/a022w000006RA28AAG"},"Name":"Sanya","Geolocation__Latitude__s":24.8513290,"Geolocation__Longitude__s":119.4862410,"Id":"a022w000006RA28AAG"},{"attributes":{"type":"Boat__c","url":"/services/data/v48.0/sobjects/Boat__c/a022w000006RA2DAAW"},"Name":"Longxue","Geolocation__Latitude__s":22.6216820,"Geolocation__Longitude__s":113.7630620,"Id":"a022w000006RA2DAAW"}]'
So, you may parse it using JSON.parse(boatData) and then call the map() function on it,
this.mapMarkers = JSON.parse(boatData).map((rowBoat) => {
return {
location: {
Latitude: rowBoat.Geolocation__Latitude__s,
Longitude: rowBoat.Geolocation__Longitude__s
},
title: rowBoat.Name
};
});
And definitely use double underscore to access Latitude and Longitude from Geolocation as shown above.
One more point, set the isLoading to true just before creating the mapMarkers and set it to false after it is created within the createMapMarkers method.
Hope this will work for you :)

Related

How to access mongoose populated fields?

I'm not able to access the populated fields of mongoose objects. I want to output it in my page.
Example:
"console.log(booking.assignedUser.first)" gives me back:
TypeError: Cannot read properties of undefined (reading 'first')
But from what I can tell, this should be working. The field is clearly there.
In my jsx file:
console.log(booking.assignedUser)
Object:
{
etc etc
assignedUser: { _id: new ObjectId("62f068b068802d58c8d35442"), first: 'driver' },
etc etc
}
So why I can access booking.assignedUser and it shows me the data, but booking.assignedUser.first doesn't work?
Because these values are being populated from the DB, I guess they aren't loading fast enough so it's giving me this error.
If I check to make sure the value exists first, then use it, it's working.
I'm working with a lot of this type of data in my app, so instead of outputting the jsx directly in the react object, I'm using a function to return it all for me which I pass in the db data.
using a ternary at the beginning of the output within the React component was not good enough, for example.
{ data ?
<Form>
<SomeStuffHere>
<SomeMoreStuffHere>
<Form.Control> {data.something} </Form.Control>
</Form>
: '' }
This was not good enough. It would still error out. I had to place the ternary immediately on the field in order for it to work.
Doing this for every single field would be a pain in the ass, so putting it into a function first seems to work better.
Probably , you are trying to achieve data's populates when data didn't set yet. Need to be sure data is set already.
You can use it like ;
booking.assignedUser && console.log(booking.assignedUser.first)
If the page can't view components due to data is empty, need to use this condition beginning of view component.
data.length > 0 && ...</Component/>

Can't find id of Angular ui-grid element with Selenium/Protractor

I have some Protractor tests that are running on an Angular application that uses ui-grid. I have some working smoke tests for the application, but I am just starting to implement tests using https://github.com/angular-ui/ui-grid/blob/master/test/e2e/gridTestUtils.spec.js to test the ui-grid components. The problem I'm having is that I need the actual id of the grid element in order to use the getGrid function.
I'm able to successfully locate the element using element(by.css("[id$='-grid-container']")), but for some reasons my attempts to get the full id out of the element have failed. Here is what I am trying:
var grid = element(by.css("[id$='-grid-container']"));
grid.getAttribute('id').then(function(result) {
console.log(result);
var myGrid = gridTestUtils.getGrid(result.toString());
gridTestUtils.expectCellValueMatch(myGrid, 0, 0, 'Cox');
});
The console.log(result); is not logging anything. It doesn't SEEM necessarily related to ui-grid, it's just Selenium isn't finding the id for some reason. As far as I can tell I'm using getAttribute correctly; it works with this syntax in other tests, but maybe I'm missing something. Any ideas why this isn't working?
Edit because my comment is unreadable:
Thanks for the suggestions. However, I'm still just as confused because
var grid = element(by.css("[id$='-grid-container']"));
console.log(grid.toString());
grid.getAttribute('id').then(function(result) {
console.log('======'+result);
var myGrid = gridTestUtils.getGrid(result.toString());
gridTestUtils.expectCellValueMatch(myGrid, 0, 0, 'Cox');
});
gives a console output of
[object Object]
======
so it seems like the element is being found, which I had already checked, and the console.log inside the promise is being executed.
It's like it can't find the 'id', which according to the API documentation means there is no id on the element. But that is definitely not true.
Not sure on the semantics, but you could try this, just to make sure that you are getting the first element, if multiple:
element.all(by.css('[id$="-grid-container"]')).first().getAttribute('id').then(function(result) {
console.log(result);
var myGrid = gridTestUtils.getGrid(result.toString());
gridTestUtils.expectCellValueMatch(myGrid, 0, 0, 'Cox');
});
Your code looks correct.
However, if your console.log(result) doesn't log anything, this means you either didn't find the element or the moment you execute the getAttribute() the element is no longer present.
See in the API description, that getAttribute() always returns a value, if the element is present.
Maybe try to extend console.log('======='+result); to figure out, if that line of code gets executed (I'm pretty sure it's not executed). Also try console.log(grid.toString());, which should output [object Object], if the element is really found.
As for the ElementFinder, I'm used to use the ' and " just the other way around, so element(by.css('[id$="-grid-container"]')); or shorter $('[id$="-grid-container"]').
Let me know, if this helped and you could further determine the cause.
Round 2
Let's exclude a few things
change getAttribute('id') to getAttribute('outerHTML') to see,
if there is anything logged.
change (result) to (resultattr) to exclude, that result is else used by a plugin, who put result as a global variable.
change grid.getAttribute() to be element(by.css("[id$='-grid-container']")).getAttribute
What are the results of those actions?

AngularFire - Get a firebaseObject for each item in a firebaseArray ng-repeat

I have an ng-repeat which is connected to a firebaseArray which is an index of a user's doc Ids.
I want to display a list of their docs with additional info for each one, e.g. it's title and description.
My firebase structure is:
+users
- userId1
-theirDocs
-docId1: true
-docId2: true
+docs
-docId1
- tile
- description
- url
-docId2
- etc etc
I've tried everything and still can't get this to work, it seems a pretty common use case. I've tried using a function that calls a firebaseObject each time. I've tried using a separate controller. I've tried a directive, I've even tried using firebase.utils library (I think out of date now).
Can anyone recommend the best way to do this using AngularFire? Thanks in advance!
It would be better to see a code snippet as to fully understand what you've tried first of all, as it's difficult to determine where the issues lie. That being said, as long as your rules are not preventing this, you may need to wait for the data to download using $loaded function beforehand.
EXAMPLE
This example is clearly available by following this link, yet here is an example for further clarity:
var yourFirebaseReference = firebase.database().ref("REPLACE WITH YOUR FIREBASE BRANCH HERE");
var data = $firebaseArray(yourFirebaseReference);
data.$loaded().then(function(x) {
console.log(data) // Example, you can do what you want with your 'data' now as the data has loaded
x === data; // true
}).catch(function(error) {
console.log("Error:", error);
});

$on('value...) gives me "undefined is not a function" in angularfire

I have started to use angularjs and now am following a tutorial about angularjs with angularfire. In the tutorial there is a section to learn how to use child_added
angular.module('firebaseApp').service('MessageService', function(FBURL, $q, $firebase) {
var messageRef = new Firebase(FBURL).child('messages');
var fireMessage = $firebase(messageRef).$asArray();
return {
childAdded: function childAdded(limitNumber, cb) {
fireMessage.$on('child_added', function(snapshot){
console.log(snapshot);
var val = snapshot.val();
cb.call(this,{
user: val.user,
text: val.text,
name: snapshot.name()
});
});
},
and main controller :
MessageService.childAdded(5, function(addedChild){
$timeout(function() {
$scope.messages.push(addedChild);
});
});
When I use the code, chrome developer tools is giving an error :
TypeError: undefined is not a function
adressing .$on in MessageService and .childadded in controller.
This is a video tutorial and I can see him working like this. I checked many answers but could not find a way. My best shot is I guess different versions of angularjs and angularfire. But that did not help me either. Can you help me to solve it?
Thank you in advance.
I thought I'd offer a bit of clarity on the topic for those who are taking this tutorial on tutsplus. First, we should pay attention to the versions of firebase and angularfire that we are using, compared to what the instructor is using. This might seem obvious, but there are many out there who fail to realize it. Whenever watching a tutorial, you should always check the version of ANY package you are using. This world of software moves really fast, and up-to-date tutorials are a luxury.
Pay attention to your bower.json file in your project. Note the version of the following lines:
"firebase": "~2.0.4",
"angularfire": "~0.9.0"
You can see here the version of the dependencies I used. Chances are, you were like me, and your version will differ from what you find in the teacher's version. The instructor offers his source files on the course main page. Download those files, which should be titled SourceFiles_RTWebAppAngularFirebase.zip. Once downloaded, open it, and you will see a list of packaged zip files contained in a file called Firebase Source. Find lesson-16-angularfire.zip, and also open it. A folder titled "Firebase" should be provided, and there you will find the instructor's app that he created during the tutorial. Check out his bower.json file, and check it against what you have. According to what I found, both versions of firebase and angularfire were vastly different. This means only one thing: we have some reading to do.
Go here and check out the releases of AngularFire: https://github.com/firebase/angularfire/releases
Scroll down, and read the release notes of v0.8.0. A very important note is found here.
$on() and $off() no longer exist. Similar functionality can be obtained with $watch() but should be discouraged for trying to manually manage server events (manipulation should be done with data transformations through $extendFactory() instead).
Obviously now, we understand that we can't follow blindly in the instructor's footsteps. We have to try mimicking his app's functionality. Reading what I posted above, we can use $watch to obtain similar functionality. However, I honestly tried to make this work, and the functionality that $watch delivers is not exactly the functionality we are trying to achieve. Ideally, we should synchronize our empty messages array $scope.messages with $firebase(messageRef).$asArray(). That wouldn't be as fun though.
The route I took was this: I looked at what cb.call() was doing, which is the following
MessageService.childAdded(function(addedChild) {
$scope.messages.push(addedChild);
});
This call back function pushes an object created from cherry picked values obtained from a snapshot returned from a 'child_added' event. The real leverage here is the snapshot, which is provided by the $firebase module itself with Firebase.on(). If you read the docs for the "Child_Added" event, it says
This event will be triggered once for each initial child at this location, and it will be triggered again every time a new child is added. The DataSnapshot passed into the callback will reflect the data for the relevant child
The DataSnapshot returned for every "initial" child at this location, is what initially populates the list of messages. This means that we can change this:
fireMessage.$on('child_added', function(snapshot){
console.log(snapshot);
var val = snapshot.val();
cb.call(this,{
user: val.user,
text: val.text,
name: snapshot.name()
});
});
back to this:
messageRef.on('child_added', function(snapshot) {
var val = snapshot.val();
cb.call(this,
user: val.user,
text: val.text,
name: snapshot.key()
});
});
The messages should populate again on the front page. Your code should be stable enough as well to follow the instructor during the remainder of the Refactor lesson.

Ext JS - Can I 'chain' methods on a field?

HI,
I am just trying to set a field value and disable it at the same time.
Can this be done in ext js? The docs are very weak on this subject.
something like this generates errors:
myForm.getForm().findField('start_date').setValue('').setDisabled(true);
I'm used to JQuery which does this sort of thing nicely but haven't had luck with Ext.
Thanks for any help.
Actually, Field.setValue does in fact return a reference to the field (docs), so you should be able to call setDisabled (inherited from Component) as you have it. You must have some other issue going on. Maybe findField('start_date') is returning null. You have to make sure all the return values are what you expect. Use Firebug to figure out the error, or break apart your statement and see which call is actually failing.
Anything is "chainable" as long as the return value is the object itself (usually denoted as this in the docs). In jQuery, everything operates on DOM elements, so it is consistent. In Ext, you have lots of components with various behaviors. Sometimes chaining makes sense, sometimes it does not -- just make sure you check the docs when you aren't sure.
i agree with bmoeskau it should work if the field is there and found by the form. I would advise you to to it something like that to prevent errors:
var field = myForm.getForm().findField('xyz');
if(field !== undefined)
{
field.setValue('');
field.setDisabled(true);
}
else
{
// Error Handling
}
This is because setValue() method doesn't return field object. You cannot use setDisabled() in such way.
EDIT: (For those down-voting morons)
From ExtJS documentation:
method: setValue(value)
Parameters:
value : Mixed
The value to set
Returns:
void

Resources