How to deep watch an object in angularjs excluding a specified pattern? - javascript

There is an nested object with certain properties which i don't want to be watched. It could be a pattern of properties starting with perhaps "_".
Here's a sample structure.
$scope.ObjectToBeWatched = {
"company": {
"ts": {
"_msg": {"nm":""},
"status": "success"
},
"ids": [
"000000010",
"000000011"
]
},
"_f": [
{
"code": "TY_IO",
"status": "fail"
}
]
}
Standard deep watch:
$scope.$watch("ObjectToBeWatched",function(newObj,oldObj){
},true);
Right now the watch is firing for any any change in any properties which is expected. So in above case any changes to properties
_msg, _f
should not fire.
Thanks for help.

You can try something like this:
$scope.$watch(function($scope) {
return $scope.listOfBigObjects.
map(function(bigObject) {
return bigObject.foo.
fieldICareAbout;
});
}, myHandler, true);
This grabs only the props you care about from the objects in an array. You can use an expression to check for certain field types inside the object map. If you don't have an array just skip that part.
Underscore has tons of functional methods to help w/ this as well if 'map' isn't exactly what you need to return fields you care about.

Related

Access items inside of an array of objects

I have a rather simple JSON file that I'm trying to access the items inside of. I had this working but for some reason it no longer works and it is making my brain hurt. Here is the JSON:
[
{
"firstItem":
{
"message": "firstItem is working",
"value": ["hello", "world"]
}
},
{
"secondItem":
{
"message": "secondItem is working",
"value": ["hello", "aliens"]
}
}
]
Note that there is an array of two objects (firstItem and secondItem) which have objects within them (message and value). I am trying to access these items like so:
// the json from above is equal to json
json.map(items => {
console.log(items.firstItem.message)
console.log(items.firstItem.value.join(", "))
console.log(items.secondItem.message)
console.log(items.secondItem.value.join(", "))
})
As always, any help would be appreciated.
Edit: I put the closing parenthesis on the joins. This was not part of my issue. I guess I'm too used to VSCode doing it for me. :)
You were missing a closing parentheses on your console.log join statements. The second and larger problem was that with map you are looping through firstItem first and then secondItem, so in the first iteration map doesn't know what secondItem is. I changed the names of each object to "item" and halved the code inside map to solve the problem:
const json = [
{
"item":
{
"message": "firstItem is working",
"value": ["hello", "world"]
}
},
{
"item":
{
"message": "secondItem is working",
"value": ["hello", "aliens"]
}
}
]
json.map(items => {
console.log(items.item.message);
console.log(items.item.value.join(", "));
})
Note that there is an array of two objects (firstItem and secondItem) which have objects within them (message and value). I am trying to access these items like so:
The example you show, shows an array containing two objects, where the first object has a property called firstItem and the second property has a property called secondItem. The properties in both the objects are objects themselves and both have two properties called message and value.
I hope that makes sense.

Javascript: Construct an object from array of objects based on matching property id's:

still quite new to higher order functions and trying to use them correctly here if possible.
I have a array of objects being returned from an api constructed like so:
[ {"gymId":3467, "halls": [{ "hallId": "25828", "instructorId": 1064,
"slotIds": [2088,2089], "sessionId":8188},
{"hallId": "25848", "instructorId": 1067, "slotIds": [2088,2089], "sessionId": 8188 }]}]
Expected result I want to achieve is to create a list of objects such as this from the array above ...
{2088: [{ "hallId":"25828", "instructorId":1064, "sessionId":8188 },
{ "hallId":"25848", "instructorId":1067, "sessionId":8188 }],
2089: [{ "hallId":"25828", "instructorId":1064, "sessionId":8188 },
{ "hallId":"25848", "instructorId":1067, "sessionId":8188 }]
}
I was thinking something along the lines of this
halls.reduce((acc, hall) => {
hall.slotIdIds.forEach(slotId => {
acc[slotId] = {
//expected object properties as above here.
};
});
return acc;
}, {}),
Problem is when I reduce in this way only one hallId is being returned and not the two matching hall ids where the slots exist.
Bit perplexed as to how to solve this one and would really appreciate any tips.

Destructuring objects in Javascript

In my code base I have an object:
let myObject = {
"version": 1,
"traceId": "123456789",
"session": {},
"trigger": {
"service": "some_service_is_here",
"action": "update",
"resource": "transaction"
},
"changesets": [
{
"update": {
"retryCount": 1
},
"conditions": {
"equal": {
"subscriptionId": "aaaaaaaaaaaa",
"transactionId": "bbbbbbbbbbbb"
}
}
},
{
"update": {
"retryCount": 2
},
"conditions": {
"equal": {
"subscriptionId": "ccccccccccccc",
"transactionId": "dddddddddddddd"
}
}
}
]
}
I need to extract some properties from that object. So far it is done using Lodash. There are more extractions going on, but they are fairly identical. Several examples of using it with Lodash:
const trigger = _.get(myObject, 'trigger', null);
const retryCount = _.get(myObject, 'changesets[0].update.retryCount', null);
It works and behaves as expected. I would like to improve this code, by eliminating Lodash and start using Destructuring.
So far I have this:
const trigger = _.get(myObject, 'trigger', null);
becomes
const {trigger} = myObject;
And also:
const retryCount = _.get(myObject, 'changesets[0].update.retryCount', null);
becomes
const {changesets: [{update:{retryCount:retryCount = null}}]} = myObject;
It also works, test are passing:
Now I have several questions:
Is this the correct practice to extract those values?
Is it worth it, in terms of speed and code readability?
The second destructuring example. I will receive an changeset array, that has many objects (unknown number), but I am always interested in the first one. The lodash example illustrates that. When I destructure, I do not specify that I need a first one (zero based) it comes in by default. Do I need somehow to specify I need the zeroth one, or it is default behaviour?
Yes, but currently your variants are not equal. You need to specify null to be default value in variant with destructuring .
Code is not faster. As for readability - it depends.
You currently specify index explicitly by items' position in the list. So for example
const {changesets: [,,{update}]} = myObject;
would explicitly extract 3rd element. You don't need to do anything extra.
PS retryCount:retryCount better don't specify the same name twice. it looks confusing. Reader(like me) will re-read for several times trying to figure out the difference.

How to get the name of the array in json data using JavaScript

I have a JSON object which comes back like this from a JavaScript API call:
{
"myArray": [
{
"version": 5,
"permissionMask": 1
},
{
"version": 126,
"permissionMask": 1
}
]
}
How can I access the name of the array (i.e myArray) in JavaScript. I need to use the name of the array to determine the flow later on.
Use getOwnPropertyNames to get a list of the properties of the object in array form.
Example:
var myObj = {
"myArray": [
{
"version": 5,
"permissionMask": 1
},
{
"version": 126,
"permissionMask": 1
}
]
},
names = Object.getOwnPropertyNames(myObj);
alert(names[0]); // alerts "myArray"
Note: If the object can have more than one property, like myArray, myInt, and myOtherArray, then you will need to loop over the results of getOwnPropertyNames. You would also need to do type-testing, as in if(names[0] instanceof Array) {...} to check the property type. Based on your example in your question, I have not fleshed all of that out here.
Object.keys(data)[0]
# => "myArray"
A terminology note: This solution assumes you have a JavaScript object. You might have a JSON string, in which case this is the solution:
Object.keys(JSON.parse(data))[0]
# => "myArray"
However, "JSON object", in JavaScript, is just one - the one I used just now, that has JSON.parse and JSON.stringify methods. What you have is not a JSON object except perhaps in a trivial interpretation of the second case, where all values in JavaScript are objects, including strings.
The other answers are good if you have no control over the return format.
However, if you can, I'd recommend changing the return format to put the important values you care about as actual values instead of keys to make it clearer. For example, something like this:
result =
{
"name: "myArray",
"value": [
{
"version": 5,
"permissionMask": 1
},
{
"version": 126,
"permissionMask": 1
}
]
}
Then, it's a lot clearer to reliably access the property you care about: result.name

How to filter the json data using Underscore

I am new to Underscore. I have a json array which is pasted below. If I want to filter the below array based on developed field having "yes" as value. How can I do using Underscore.js. Currently I am iterating over the content of array and manually selecting the objects and populating in into another array. Is there a better way to do using Underscore?
{
"content": [
{
"stateName": "Karnataka",
"population": 1000000,
"developed": "yes"
},
{
"stateName": "Kerala",
"population": 1000000,
"developed": "yes"
},
{
"stateName": "Tamilnadu",
"population": 1023213213213,
"developd": "yes"
},
{
"stateName": "Bsadasd",
"population": 1023213213213,
"developed": "no"
}
]
}
Not sure if I'm missing something here but the obvious underscore function is filter:
var developedStates = _.filter(data.content, function(state){
return state.developed == 'yes';
});
You can filter an array on its properties by using _.where :
where _.where(list, properties)
Looks through each value in the list, returning an array of all the values that contain all of the
key-value pairs listed in properties.
which leads to
var filtered = _.where(data.content, {developed: "yes"});
and a demo http://jsfiddle.net/nikoshr/NExZC/
As far as I know, underscore doesn't have a way to help you with this task. You can do this without using underscore with a native Javascript method called select:
var filteredArray = originalArray.select(function(item, index) {
return item.developed == "yes"; // Include this item if it has a proper value
});
Note that the select method is only available in browsers that support EcmaScript 5 specifications, so for older browsers you will need some supporting library like es5-shim.

Categories