ng-repeat with different nested json - javascript

So I have an API that returns a list of activities,but I have to get the info 2 items at a time so if I have 3 items on the first call the json returned would be something like this:
cesta{
fecha="14/08/2015 2:42:28 PM",
tipo="9",
pagina="1",
total="3",
inst [{
nu_doc_opened="N",
nu_doc="14",
nu_inst="1",
nb_wf{
cdata_section="Gestión calendario específico"
}
},
nu_doc_opened="N",
nu_doc="15",
nu_inst="2",
nb_wf{
cdata_section="Gestión calendario general"
}
}]
}
and on the next call the json returned would be like this
cesta{
fecha="14/08/2015 2:42:29 PM",
tipo="9",
pagina="2",
total="3",
inst {
nu_doc_opened="N",
nu_doc="16",
nu_inst="1",
nb_wf{
cdata_section="Gestión calendario específico"
}
}
}
I want to go throgh this json and get some of the data and put it in a table,so I'm trying to use ng-repeat like this: (Note that I only want to get some of the values not all)
$scope.basket= data.cesta.inst;
<tbody>
<tr ng-repeat="b in basket">
<td>{{b.nu_doc}}</td>
<td>{{b.nu_inst}}</td>
<td>{{b.nb_wf.cdata_section}}</td>
</tr>
</tbody>
The problem is that this works when the json has 2 or more objects in 'inst' (like in the first example) because it's an array, but when it has only 1 object won't work, What could I do so the ng-repeat work in both cases?
Thanks in advanced

This is because in second case it get object an when iterate the object the it gets the properties and values not the objects like in first array.
Wrap that object in array then it works.
$scope.basket= angular.isArray(data.cesta.inst) ? data.cesta.inst : [data.cesta.inst];

As you've realized, ng-repeat expects an array. If you can't force the endpoint to return an array always (even when there's only one data object), then you may have to write a hacky workaround.
One hacky idea:
$scope.basket = data.cest.inst.length !== undefined ? data.cest.inst : [data.cest.inst]
I think you get this, but in case not, here's the reason why $scope.basket needs to be an array:
In short: ng-repeat expects an array. In the first case, $scope.basket is an array of objects, but in the second, it's just an object. In the second, you need to place the object inside of an array (i.e. [{nu_doc: ...}]) so that the format is consistent. (Note: It's ok to have an array with only one object!)
For example, in the first case, you get:
$scope.basket = [{nu_doc: ...}, {nu_doc: ...}]
And that works fine with the ng-repeat statement as you've written it.
But in the second case, you get:
$scope.basket = {nu_doc: ...}
And so the ng-repeat will loop through the properties on that object (i.e. nu_doc, nu_inst ...) instead of treating it as an array with a single object, which is what you want.
So your second piece of JSON needs to be:
cesta{
fecha="14/08/2015 2:42:29 PM",
tipo="9",
pagina="2",
total="3",
inst [{
nu_doc_opened="N",
nu_doc="16",
nu_inst="1",
nb_wf{
cdata_section="Gestión calendario específico"
}
}
}]

Related

How to get a JSON object's key from the object itself in JavaScript/a Vue v-for loop?

I'm not looking for the keys that this object contains but the key of the object itself (the key in the array containing the object).
I have this JSON:
{
"Object name (text)": {
"raw": "Some more text.",
},
"Another name": {
"raw": "Some other text.",
}
}
and would like to get "Object name (text)" for the first item.
My Vue code is:
<CustomComponent
v-for="object in objects"
:key="getKey(object)"
:object="object"
/>
I'm not sure if the getKey-method approach is how one is intended to get unique identifiers for iterating through the JSON array. Its code currently is:
getKey(object) {
return Object.keys(object)[0];
}
Now I'd like to somehow pass the name of the object to the CustomComponent ("Object name (text)" in the first case).
One temporary workaround that I intended to use until I find something more appropriate was getting the keys from the objects array like so:
:objectName="getObjectName(object)" and itemNumber: -1 in data and this method:
getObjectName(object) {
this.itemNumber = this.itemNumber + 1;
var objectName = Object.keys(this.objects)[this.itemNumber];
console.log("Object name: ", objectName);
}
However, the first line of this method causes it to run hundreds of times instead of only two times (why is that?; it works in the first 2 executions of the method and when commenting out that line) and I think this is unlikely the proper method to simply retrieve the object's name/key.
It also didn't work when putting the above code into the getKey method which would make more sense (and I had the code in that method before creating a separate method to debug). Then the key could be accessed in the component with this.$vnode.key However, it keeps being undefined. This might be a separate problem even though it could resolve this problem here as well - I might create a new question for it. It enters the methods "getKey" and "getObjectName" 6 times each even though it only renders two items on the page, like it should.
-> How to get the JSON object's key in JavaScript?
(Preferably from the object itself after iterating through a JSON array with a loop with Vue instead of only indirectly by checking the objects array.)
Edit: as a workaround I have now done this:
var keys = Object.keys(this.objects);
keys.forEach(element => {
this.objectsWithKeys.push({
object: this.objects[element],
key: element
});
});
<CustomComponent
v-for="objectWithKeys in objectsWithKeys"
:key="objectWithKeys.key"
:object="objectWithKeys.object"
>
</CustomComponent>
this.$vnode.key
This is solved, I used var objectsWithKeys = data[Object.keys(data)]; and {{ $vnode.key }}.

Javascript apply .join() to item in object collection only if not undefined/empty/null?

In Javascript I have a collection of objects, whose values I'm storing in variable
var filters = {
BeginDate: $("#BeginDateRange").val(),
EndDate: $("#EndDateRange").val(),
ListOfCodes: $("#ListOfCodes").val(),
//ListOfCodes: $("#ListOfCodes").val().join(),
...
}
Based on where I use the collection, some of its objects remain 'undefined', and it is intended.
ListOfCodes above is an array of string values, and I want to pass it to the binder as a single comma-separated string (e.g ["1"], ["2"] -> "1,2")
I was able to make a use of .join(), and it worked successfully. However, I found later that the code will crash if the .join() does not have a value to join.
Is there a way to apply .join() INSIDE the collection to the variable ONLY if it has value? Something like
var filters = {
BeginDate: $("#BeginDateRange").val(),
EndDate: $("#EndDateRange").val(),
ListOfCodes: if( $("#ListOfCodes").val() )
{$("#ListOfCodes").val().join()}
else
{$("#ListOfCodes").val()} //value remains undefined
,
...
}
EDIT: I ask about the possibility of applying .join() method inside the collection, not checking for empty values.
Just moving this as an answer.
What about a ternary statement?
ListOfCodes: ($("#ListOfCodes").val()) ? $("#ListOfCodes").val().join() : null

How to retrieve data from json data

[{"id":7,"message":"This is another test message","taker_id":"131","giver_id":"102","status":"0","stamp":"2016-08-11"}]
That's my response. I try to get a datum. I have tried data.id but it fails and returns undefined.
As I assume that you are working with a JSON string, you first have to parse the string into and JSON object. Else you couldn't reach any of the properties.
parsedData = JSON.parse(data);
Then you can get your property:
parsedData[0].id
This seems to work just fine
var data = [{
"id":7,
"message":"This is another test message",
"taker_id":"131",
"giver_id":"102",
"status":"0",
"stamp":"2016-08-11"
}];
console.log(data[0].id);
https://jsbin.com/jewatakize/
if you just want to get the id from this one object then data[0].id will work just fine.
If you expect to have multiple objects in that same array then you can use a loop.
for example if this is angular you can do:
<div ng-repeat='info in data'>
<p>{{info.id}}</p>
</div>
This will allow you to iterate through multiple objects within the array and get all id's.
The problem here is that you have here an array of objects, and you are trying to access it without indexing.
You should first parse it using and then access the object by indexing
let objects = JSON.parse(data)
console.log(objects[0].id)

An explanation for this context of the.reduce() method and Object.assign()

Based on referencing the method/object definitions on MDN I am trying to construct a layman's step by step explanation of how the following script (from the previous post) is working to help my understand of it (and hopefully so I can adapt it further)
There's a few things I don't get so my attempt will probably seem a bit muddled but hoping someone can put me right where I'm off track/confused ...
(n.b. the encode function is just to encode html and required from node.js package)
var arr = {
"a": "Some strings of text",
"b": "to be encoded",
"c": "& converted back to a json file",
"d": "once they're encoded"
}
var encodedValues = Object.keys(arr).reduce(function(out,key) {
return Object.assign(out, {[key]: endcode(arr[key])})
}, {});
console.log(encodedValues);
Explanation
Create a variable “encodedValues” which will:
1 Object.keys(arr)
loop over and return the object arr’s properties in the order they are provided
2 .reduce(function(out,key)
First applying the following function to execute on each value in the array ("and reduce it to a single value" *):
3 return Object.assign(out, {[key]: endcode(arr[key])})
The function copies the values of all properties from the source object to a target object we will call “out”.
4 The source object has an encoding function {[key]: encode(arr[key])} applied to it so that where key is an object encode is applied to its property
5 }, {});
I assume this part , {} is the initialValue for .reduce i.e. the value used as the first argument to the first call of the callback, which starts as an empty object?
6
Object.keys returns an array (of the given object arr's encoded properties in the order they were provided)
7 which is then logged to the console
*I don't understand how or why we "reduce it to a single value" in this case??
Doesn't that suggest a concatination of the values is part of the process:
"Some strings of text" + "to be encoded" + "& converted back to a json file" + "once they're encoded". I don't really get how or why this is part of the working solution
Thanks!
What reduce() does is loop over the array, call your function for each item, and each time, it passes your function the return value of the previous iteration so that you can "build upon" it.
For example, you could use reduce() to total up an array of numbers. The iterator function would take in the running total, add to it, and then return the new total. Or, you could use it to concatenate a bunch of strings, where the iterator takes in the existing string, concatenates something onto it, and then returns the new string.
In this case, you're simply taking in an object (the parameter named out), doing stuff to it, then returning it so that the next iteration can keep working on it. When reduce() gets through all the keys, it will return the object you've been building upon. That goes into your encodedValues variable.

Order of operations with JSON.stringify

I have the following fiddle http://jsfiddle.net/kc11/h6nh1gvw/1/ . I'm not experienced with JS.
I see that ;
alert(JSON.stringify(getCarData()[0]));
produces :
{"car":"Mercedes A 160","year":2006,"available":true,"comesInBlack":"yes"}
but:
alert(JSON.stringify(getCarData())[0]);
produces:
[
Could someone explain in plain english what is happening here? Intuitively I feel that the second operation should work in producing the first JSON record as well.
In your first line of code you provide you are serializing an object and getting the result as a JSON string. The second example it seems you were trying to treat that object as an array and serialize the first element of that array that comes back.
Assuming this is the case you need to alter the location of the parenthesis in your code to be:
alert(JSON.stringify(getCarData()[0]));
What you wrote will actually just take the first character from the JSON string returned (which is "["). Hence the output that you get from this.
One other thing that is noteworthy here though is the fact that you aren't going to get what you expect when you index an object. You probably should specify a property name that you hope to serialize, something like:
alert(JSON.stringify(getCarData()["car"]));
You get the point. Best of luck!
Lets break down what alert(JSON.stringify(getCarData())[0]); is trying to do.
Remeber PEMDAS? We are basically doing the same thing.
The deepest parenthesis call is getCarData(), which returns the array.
Next, you call JSON.stringify() on that array, which returns a string.
And finally, you call [0], which effectively grabs the first character of that string.
Assuming JSON.stringify doesn't throw an error, the result of JSON.stringify(foo) is a String, let's call this str, so
JSON.stringify(getCarData())[0];
// same as
JSON.stringify(foo)[0]; // foo = getCarData()
// same as
str[0];
So by using the [0] here you're getting the first character from a String. This will be a "[" if you've stringified an Array
Now we understand this, let's look back at JSON.stringify(foo[0]), assuming foo is Array-like.
The [0] here is selecting the item at index 0 of the array, let's call this item, so
JSON.stringify(getCarData()[0]);
// same as
JSON.stringify(foo[0]); // foo = getCarData()
// same as
JSON.stringify(item);
// so we end up with
str2; // not the same as str
This time we have stringified something from JavaScript but not done anything further, so the result is the JSON representation of whatever we called stringify on (in your case it was an Object)
getCarData() is an array of objects.
getCarData()[0] is the first object of this array of objects, so it can be stringified.
JSON.stringify(getCarData()[0]) will return a string of the the first object of the array of objects.
JSON.stringify(getCarData()) will return a string of the entire array of objects.
JSON.stringify(getCarData())[0] will return the first letter of the string produced by the above command, which is [, because you're essentially doing something like "hi"[0] which is a character, whereas previously you did {"hi","hello"}[0] which is a string element.
There is a fundamental difference between the two orders of operations, which I will explain below.
TLDR
The first call to JSON.stringify() you do gets the car data you want and then stringifies it, while the second way stringifies an array of objects containing car data and then tries to access the first element in that string, which is the first character of that string.
Let's break down what the following line is doing:
alert(JSON.stringify(getCarData()[0]));
First
getCarData()
returns and Array that has an object in it at position 0. The [0] is saying give me the first item from the array of car data returned by getCarData().
You then pass this object to the JSON.stringify() function to be stringified. This works as you expect returning:
{"car":"Mercedes A 160","year":2006,"available":true,"comesInBlack":"yes"}
The second stringify call you make:
alert(JSON.stringify(getCarData())[0]);
is getting the car data (which is returned as an array) and passing it to the JSON.stringify function.
JSON.stringify(getCarData())
This will return an array of objects containing car data. JSON then tries to stringify the array, and returns
[{"car":"Mercedes A 160","year":2006,"available":true,"comesInBlack":"yes"},{"car":"Citroen C4 Coupe","year":2008,"available":false,"comesInBlack":"yes"},{"car":"Audi A4 Avant","year":2011,"available":true,"comesInBlack":"no"},{"car":"Opel Astra","year":2004,"available":false,"comesInBlack":"yes"},{"car":"BMW 320i Coupe","year":2011,"available":false,"comesInBlack":"no"}]
Next you try to access the first item in this stringified array, but since it is now a string (not an array) it just returns [, the first character of the string.
In conclusion
The first way you do it gets the data you want and then stringifies it, while the second way stringiness an array of objects containing car data and then tries to access the first element in a string, which is the first character of that string.

Categories

Resources