Let's say I have some data in an array. Each element of that array is an object that can have:
an id
some data
a property (let's call it sub) that would contain an array of objects with the same properties (including that sub property).
Basically, that is a nested data where each object can hold more object.
I know I can walk that data tree with a recursive function like this one, but I'm wondering if there is something that underscore or angular can offer me that would avoid me having to threat all that boilerplate and just do something like data.findNestedById(12345, "sub");
Take a look at this https://github.com/s3u/JSONPath it might be helpful to you. Include the required script reference into your page and then you can try it somehting like this.
JSONPath({json: jsonObject, path: pathToLookFor});
Demo http://plnkr.co/edit/6uNp23JkuRkQCI1KnmAK?p=preview
Related
I wasnt quite sure what to call this question but here is what i want to do:
I am currently creating a series geneator for chartjs that will help me create my datasets.
now the way i want to do it is by simply using object keys to extract data from each element in my array.
Each element of an array could look something like this:
as you can see this object contains other objects inside of them.
This creates a problem because say i want the name of the object feedback_skill i would have to do the following:
data.forEach(function (x) {
x['feedback_skill']['name']
});
Which cannot be hold into one variable.
Now what i could do is pass the following array: serieKey = ['feedback','name'] suggesting that the first element in the array is the first key and the next element is the variable i want to hit.
However these datasets can have an unlimited number of layers so my question to you guys is:
Is there a smart way of doing this?
I'm not aware of a native JavaScript way of doing this, but various JavaScript frameworks allow you to access deep-properties from objects like this. For example Dojo has lang.getObject and I can see that there is a JQuery plugin that does something similar, lodash as well. If you're not using these frameworks, then you could always create your own util function to perform something similar.
These types of utility function allow you to pass the target as a "dot-notation" property, so you could call:
lang.getObject("feedback_skill.name", false, x)
Using Dojo for example, but they're all much of a muchness.
I don't see any problem with your approach, unlimited number of layers can be handled in the following manner :
data.forEach(function(x){
for(i in seriesKey)
x = x[seriesKey[i]]; // x will contain whatever you wanted to retrieve when the loop ends
doSomething(x);
}
seriesKey can be an array like the one in your example, with as many elements as you need to traverse to the depth you want.
I have a HTML fragment that iterates over key, value collection. When I create an object and put some value in, then iterate trough that object via HTML fragment, all works perfectly.
However since I need keys in specific order, I'm using a Map instead of plain object. This time when I debug I can see that my insertion order was preserved, but for some reason the HTML fragment which iterates over collection doesn't seem to know how to do so. I see nothing on my screen when I use the map object, opposed to the regular object when I see unordered content
tr ng-repeat="(key, value) in rowTitlesValues"
Is how my HTML fragment looks like, when I switch rowTitlesValues back to object works again, what am I doing wrong, and how does one keep insertion order or how do I sort object so it's keys are in custom order?
From Angular reference on ng-repeat (link):
Iterating over object properties
It is possible to get ngRepeat to iterate over the properties of an object using the following syntax:
<div ng-repeat="(key, value) in myObj"> ... </div>
You need to be aware that the JavaScript specification does not define the order of keys returned for an object. (To mitigate this in Angular 1.3 the ngRepeat directive used to sort the keys alphabetically.)
Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser when running for key in myObj. It seems that browsers generally follow the strategy of providing keys in the order in which they were defined, [...]
If this is not desired, the recommended workaround is to convert your object into an array that is sorted into the order that you prefer before providing it to ngRepeat. You could do this with a filter such as toArrayFilter or implement a $watch on the object yourself.
Additionally, I do not think Angular 1.x knows how to iterate over a Map. I believe this line in the code proves it:
collectionKeys = [];
for (var itemKey in collection) { // iterates your object using `in`, not `of` or `Map.forEach()`
...
}
// ng-repeat then iterates the collectionKeys to create the DOM
So you will probably need to act as Angular docs suggest:
[...] convert your object into an array that is sorted into the order that you prefer before providing it to ngRepeat. You could do this with a filter such as toArrayFilter or implement a $watch on the object yourself.
I am getting a model deferred object with a structure like this:
How can I find out how many objects are present inside this object (in this case, three). If I use Object.keys(myObject).length, it includes the object observer and other data also like _computeBindings,_bindings etc. I have even tried to use hasOwnProperty while calculating the length but its not giving me desired result.
One way I can figure out is to iterate over the index and get the last index value like this:
can.each(myObject,function(myObject,index){
// Get the last index value and put it into some variable
});
Is there an API for this?
can.Map has a keys function that will give you an Array of the keys in your Map and from that you can get how many Objects by checking that Array's length.
Using a can.List as your data structure would also work. The keys in your data are numeric and you need to check the length, all things that can.List is built for.
Try using myObject.attr('length')
The model _data attribute contains a copy of just the model without the bindings. The easiest way to do this is to use:
Object._data.length
I am using this.get('controller.raceModal').content, I am trying to achieve is this;
If I dig into the following expression
this.get('controller.raceModal').content.content
I find an array with a bunch of objects, I am trying to see if one of the methods in content will allow me to do a find. The objects have an attribute 'id' which I would like to do a find on something like:
this.get('controller.raceModal').content.find({'id', '15'})
Is this possible?
You didn't say where you are trying to do this (controller, route) but if it is truely an array you should be able to do this:
this.get('controller.raceModal').findBy('id', '15')
Would like to maintain a map/hash of DOM objects. Can they serve as key objects? If not, what are the alternatives, please? If there are better ways - kindly enlist them as well.
You can put anything as the key, but before actual use it is always converted to string, and that string is used as a key.
So, if you look at what domObject.toString() produces, you see it is not a good candidate. If all of your dom objects have an id, you could use that id.
If not, and you still desperately need a key based on DOM object, you probably could do with using, for example, _counter attribute with automatic counter in background putting new unique value in a DOM object if _counter is not yet present.
window already maintains all DOM objects as properties. Instead of putting your own keys for each 'DOM object' try to use window or document object and methods that uses index based on the layout of DOM tree.
No, because object keys are strings.
You'd have to "serialise" your objects by id or something, then perform a lookup later. Probably not worth it, depending on what your actual goal is here.
No, but you can set an attribute on the DOM element that contains a number, which you would have as the index in a numerically-indexed array.
Easiest is to set a data-attribute on the element instead.
Not exact. But I think you want something like below. You can do with jquery,
The .serializeArray() method creates a JavaScript array of objects, ready to be encoded as a JSON string. It operates on a jQuery object representing a set of form elements. The form elements can be of several types
Refer below link :
http://api.jquery.com/serializeArray/