How to access object field in server array response? - javascript

I made a parse.com get request, the returned data is stored in:
$scope.tastes = data.results
{
"createdAt": "2016-03-16T07:39:15.745Z",
"objectId": "Cmg8GdOv2Z",
"updatedAt": "2016-03-16T07:39:15.745Z",
"user": {
"__type": "Pointer",
"className": "_User",
"objectId": "vYOsndWlto"
},
"userTastes": [
{
"actualite": {
"checked": true
},
"economie": {
"checked": true
},
"entrepreneuriat": {
"checked": false
}
}
]
}
Well, I want to get userTastes array.
I've tried
.success(function (data, status) {
$scope.tastes = data.results.userTastes;
console.log($scope.tastes);
})
However nothing is returned. I think that I'm missing something.
My question : How do I get userTastes in $scope.tastes ?

I writing a separate answer because I believe this needs further explanation and not just the fix to your problem.
You only provided an object response in your question, but apparently you are getting an array response from your server, while you can directly access object fields, on array objects you need to access the position first, Ex:
$scope.objectResponse = {"foo":"bar"};
console.log($scope.objectResponse.foo); // Will print "bar"
in contrast array responses:
$scope.arrayResponse = [{"foo":"bar"}];
console.log($scope.arrayResponse[0].foo); // Will print "bar"
Just make sure you are getting the response you want from your server.

results[0].userTastes work worked perfectly thanks !
If someone have a tutorial link or good course about array and objects in JS because I'm a little bit confused about that.
Have a good day !

Related

cause of TypeError: Cannot read properties of undefined

I'm trying to fetch some data from an API. The below code "works" when I log the results to console like console.log(liveInfo.tracks), but when I try to do console.log(liveInfo.tracks.current) it fails with this error: TypeError: Cannot read properties of undefined (reading 'current'). Isn't liveInfo.tracks.current how one would normally access the key-value pair?
componentDidMount() {
fetch('https://kchungradio.airtime.pro/api/live-info-v2')
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
liveInfo: result
})
}
)
}
The json looks more or less like this:
{
"station": {
"env": "production",
},
"tracks": {
"previous": {
"name": "a",
"metadata": {
"id": 1,
},
},
"current": {
"name": "b",
"metadata": {
"id": 2,
}
}
}
}
Because at some point liveInfo.tracks was undefined
Although there is a lack of hints, a common mistake when fetching data from lifecycle is trying to retrieve the value through the state before setData occurs.
Before you use liveInfo, make sure that data fetching is finished
like this
class SomeComponent = {
render() {
if(!this.state.liveInfo?.tracks?.current) return null
....
}
}
It looks you are trying to access to the current before it is filled on the componentDidMount, it means before the fetch has been performed. I suggest you to initialize the state like this:
state = {
isLoaded: false,
liveInfo: {
tracks: {
curent: {}
}
}
};
So you will be able to access the current property inside tracks without facing the TypeError. I made a codesandbox, so you can check an example there.
If this does not solve your problem, please let me know ;)
Your call looks right,
another way to get the value is console.log(liveInfo.tracks["current"]);
but I think your tracks has no value at runtime. Maybe you can show us more code where you are call console.log.
Maybe you run twice in your statement and at first time it is undefined and throw the error. So add a null check like this console.log(liveInfo?.tracks?.current);
Use Question mark (?)
? will check for null. If your object is null ? will handle it.
liveInfo?.tracks?.current
this is the right approach.
Further -
liveInfo?.tracks?.current?.metadata

Could anyone make me understand what does the code mean in vue.js

Could anyone make me understand the below scenario because I tried searching the web and unable to find any info.
I have the below code which does not work because infox is null. But when i change it "infox: []" then it works fine. I need to understand why is it so ?
data:{
infox:null
}
methods: {
loadmore: function () {
axios.get(this.url)
this.infox.push(...response.data);
}}
Next I want to understand what does the three dot stands for in ...response.data and why I cannot code in the below manner without three dots which makes more sense. I would really appreciate if you could point me to the source.
methods: {
loadmore: function () {
axios.get(this.url)
this.infox.push(response.data);
}}
Below is my JSON data
[
{
"Categories": "Fashion",
"Clicked": 30,
"EndDate": "2019-08-21",
"HomepageSpotlight": "No",
"ImageMainPage": "/static/images/fashion16.jpg",
"MainPage": "Yes",
"Mainhomepage": "No",
"Rating": 5,
"SlugTitle": "buy-clothes-with-50-Off",
},
{
"Categories": "Fashion",
"Clicked": 145,
"EndDate": "2019-08-21",
"HomepageSpotlight": "No",
"ImageMainPage": "/static/images/fashion10.jpg",
"MainPage": "Yes",
"Mainhomepage": "No",
"SlugTitle": "get-upto-60-off-on-jeans",
}
]
The this.infox variable refers to the infox:null in your example, so it does not work because null, obviously, does not have the method push.
When you change the infox to an Array like infox: [] then it works because an Array does have the method push.
Three dots operator is a new feature in ES6, you can read about it in a lot of articles, for example here: https://dev.to/sagar/three-dots---in-javascript-26ci
In your case the this.infox.push(...response.data) will populate each element of the data into the infox array. Your data is the array it'self, so it will copy the data array to the infox array.
The this.infox.push(response.data) string will result in putting all the data array in just one element of the infox array.

Get the JSON object that matches a specific value

I'm building a little web-app to practice and learn Vue.js and working with APIs.
For a particular problem I want to solve, I would like to return the object that has the matching uuid that I request.
With my current knowledge, I understand I can do this by implementing some sorts and loops logic.
However I'm still new with JS, Vue.js, so I'm not sure if there is a better way to approach this.
Is there a built in function, or some form of "best practice" to approach this?
methods: {
fetchItem(row) {
// row.target_uuid -- this is the UUID I want
// this.$props.todoItems; -- this contains the json objects
// return this.$props.todoItems[i] where this.$props.todoItems[i]['uuid'] == row.target_uuid
},
This is a snippet of my $props.todoItems for context
[
{
"title": "Install Maris",
"uuid": "9ec9ea6b-0efc-4f6a-be2e-143be5748d3a",
"field_completed": "False"
},
{
"title": "Figure out why VS Code sucks",
"uuid": "85120da5-ee59-4947-a40f-648699365c73",
"field_completed": "False"
},
{
"title": "Start designing portfolio",
"uuid": "243c1960-7ade-4a68-9a74-0ccc4afa3e36",
"field_completed": "False"
},
{
"title": "Meal Prep",
"uuid": "85b64b18-9110-44d8-bd2d-8f818b0a810f",
"field_completed": "False"
},
{
"title": "Sharpen knives",
"uuid": "8a7ac5f6-8180-4f20-b886-628fd3bcfc85",
"field_completed": "False"
},
{
"title": "Set up SSH keys",
"uuid": "f879c441-8c05-4f24-9226-125c62576297",
"field_completed": "False"
}
]
If you know you're looking for exactly one item (or the first item that matches) you should take a closer look at the Array.find() method provided by JS. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)
Also take a look at all the other methods the Array prototype provides, most of them are fairly descriptive and solve most of the basic problems you'll encounter.
To use this in your Vue app you can either have a method that returns your todo based on a provided uid like this
todoByUid(uidToFind) {
return this.todos.find(todo => todo.uid == uidToFind)
}
If you only care about a currently selected item a computed value as Jacob mentioned is the way to go:
computed() {
selectedTodo() {
return this.todos.find(todo => todo.uid == this.selectedUid)
}
}

How to get string from API depending on another string in same section?

(Sorry if the title doesn't make much sense, I had no idea how to word the question right and that was the best way I could think of)
So I have an API (the steam API) that returns something like this:
{
"playerstats": {
"steamID": "76561197962837077",
"gameName": "ValveTestApp260",
"stats": [
{
"name": "total_kills",
"value": 3255
},
{
"name": "total_deaths",
"value": 4816
},
...
{
"name": "total_shots_hit",
"value": 3642
}
{
"name": "total_shots_fired",
"value": 4572
}
...
],
}
}
So I want to get the value for total_shots_hit and total_shots_fired, but it's in a different order for different people so I was wondering how I would get the value depending on the name in each of the sections? The way I'm doing it right now is by doing statsResponse.playerstats.stats[39].value, but it's not in the 39th spot for everyone, so I was wondering how I would get it? I'm using JavaScript/jQuery if that helps at all.
Any help is appreciated :)
EDIT: Figured out how to do it, I used a for loop to go through every response until it found the item I wanted, then used that number to find the same value
You can use Array.find() to find an object in an array by one of its properties.
var o = stats.find(function(item) {
return item.name === 'total_shots_hit';
}
console.log(o.value) // value property, e.g. 3642

Populating kendo-tree using from Json

I am in Angular environment using Kendo. All I want to do is following:
Take Json
Produce Kendo tree using it
I have tried it with simple data and it seems to work fine. But this time I have somewhat complex data and it seems like it does not work well with complex Json. I have been trying to have it render Json but it seems like it keeps on thinking and never comes back. I have created a sample Dojo for reference:
http://dojo.telerik.com/EdOqE
I am not sure what am I doing wrong but it just does not seem to work. Can anyone help me with this please?
I presume you have controll over the resultant json, because you'll have to change it a little to fit the TreeView's expected format. Check this out:
{
"items": [{ // Projects
"Id": 0,
"Name": "Your Example Project",
"CreatedOn": "",
"hasChildren": true,
"items": [{ // Analyses
"Id": 0,
"Name": "1.0 - Your Example Run",
"CreatedOn": "",
"hasChildren": true,
"items": [{ // Samples
"Id": 0,
"Name": "Sample 1",
"hasChildren": false,
"Description": "ample frample sample"
}, {
"Id": 0,
"Name": "Sample 2",
"hasChildren": false,
"Description": null
}]
}]
}]
};
The above json is what I did to work in the widget. First of all, the collection properties were renamed to items. All of them, in all levels. With that, kendo will know how property it should deal with. A hasChildren property was added to let it know when it has to show the expand icon. Otherwise it will show the expand option even if the item doesn't haves any children. So user clicks it and get an empty result.
This is the widget initialization options:
{
dataSource: new kendo.data.HierarchicalDataSource({
data: things,
schema: {
data: "items"
}
}),
dataTextField: "Name"
};
With schema.data I tell which property kendo will deal as the collection item. The dataSource expects an array, but if you give him an object, you have to set this property. If it was an array, then kendo would look for item property of each child for default. dataTextField is the name of the property it will use as the label.
Demo
Here is another demo with the data as an array. No need to set schema.data.
Update:
I was afraid you would say that. Yes, there is a way to deal with the data if you can't change it in the server-side. You have to intercept the data at the schema.parse() method and change the resultant data object property to items, so then the widget will understand:
schema: {
data: "items",
parse: function(data) {
if (data.hasOwnProperty("Projects")) {
return { items: data.Projects };
}
else if (data.hasOwnProperty("Analyses")) {
return { items: data.Analyses };
}
else if (data.hasOwnProperty("Samples")) {
return { items: data.Samples };
}
}
}
Demo
Every node when opened will call parse with items collection as data parameter. You have to return a new object with the property name as items instead of Projects, Analysis or Samples.
I forgot you can't touch the data, so can't add hasChildren property as well. Then you have to add a tiny logic into parse to set those properties in each level, otherwise the expand icon would not appear:
schema: {
data: "items",
parse: function(data) {
if (data.hasOwnProperty("Projects")) {
data.Projects.forEach(p => {
p.hasChildren = false;
if (p.hasOwnProperty("Analyses")) {
p.hasChildren = true;
}
});
return { items: data.Projects };
}
else if (data.hasOwnProperty("Analyses")) {
data.Analyses.forEach(a => {
a.hasChildren = false;
if (a.hasOwnProperty("Samples")) {
a.hasChildren = true;
}
});
return { items: data.Analyses };
}
else if (data.hasOwnProperty("Samples")) {
return { items: data.Samples };
}
}
}
Demo
It is ugly, I know. But get used to Kendo, it is the it goes with it.

Categories