Looping through json object from a checkbox loop - javascript

I have a json object thats being loaded through a checkbox in an ng-repeat. It lists possible services and I'm trying to get access to the ones that have been checked when I submit the form.
I'm loading the checkbox through:
<label style="margin-right:10px" ng-repeat="item in dsServces">
<input
type="checkbox"
name="selectedFruits"
value="{{item.DefaultServiceID}}"
ng-model="expense.dsService[item.DefaultServiceName]"
> {{item.DefaultServiceName}}
</label>
I can see the expense is being built by testing with:
{{ expense.dsService }}
returns (when a couple are selected)
{"Email":true,"Backups":true}
But I can't work out how to loop through so it says just the service name so I can add them against the customer.
In the back end I have:
$scope.expense = {
tags: []
};
And on the submit:
angular.forEach($scope.expense, function(item) {
console.log(item);
});
Which spits out Object {Email: true, Backups: true} but I can't work out to have a loop where it just returns which ever objects are true.
My main aim is to have something like
angular.forEach(forloop) {
//service.item should be like 'Email' whatever the item.DefaultServiceName is
// the loop should be all items that are checked
addService(service.item);
});

If I am understanding properly, you want to push the key values of the object into an array. If that is the case, just make a little change to your forEach()
Like so:
// The first parameter is what you want to loop through
// Second is the iterator, you can separate out the key and values here
// The third is the context, since I put the array we want to push to in here
// we just need to call `this.push()` within the iterator
angular.forEach($scope.expense, function(value, key) {
this.push(key);
}, $scope.expense.tags);
Let me know if this helps.

Related

Vue trying to filter an array but I get no results

I have a Vue 3 application
I have an object of posts. Each post has a different category. At the top of the page I have check boxes that I can check to filter the array and only show the categories I added to another array called visibleList. If I click the check box for cars then 'cars' is added to visibleList.
I need to show only posts with the category of cars if I check the cars checkbox. Now if I check the box I see no posts
I created an extra object that I can use to filter the objects. That object is populated when I load the app.
When I check a box the posts disappear. In the console I can see the number of posts with the correct category showing true and the others showing false.
Here is my function for sorting the posts:
function filterPosts() {
filtered.value = posts.value;
if (visibleList.value.length != 0) {
filtered.value = filtered.value.filter((e) => {
visibleList.value.includes(e.category);
console.log(visibleList.value.includes(e.category));
});
} else {
filtered.value = posts.value;
}
}
What am I doing wrong that I cannot see the posts from the selected category?
Looks like you are not returning a value from the filter function. The filter function expects a boolean value to determine whether an element should be included in the filtered array or not.
filtered.value = filtered.value.filter((e) => {
return visibleList.value.includes(e.category);
});
Just an Alternative!!
Since you are using the arrow function, you can use this approach to filter down the value.
filtered.value = filtered.value.filter((e) => visibleList.value.includes(e.category));

Break map() function in React JS based on condition

Requirement: Basically I have an array of employee object in React JS, say empList. This empList contains primitive fields & again an inner array of another "address" objects, say addressList. I want to fetch data for all employees if they belong to city "ABC". They can have multiple address in city "ABC", but they should be fetched only once & pushed into finalList only once.
Problem : I am able to filter the employees having address in city "ABC" but in case, they have multiple address in city "ABC", then they are added to the finalList multiple times. So, I want to check for all addresses for an employee & in case, any one is found in city "ABC", I want to add it to finalList, break this inner map() function & go to outer map() to check for next employee.
Below is my code snippet.
var finalList =[];
empList.map(function(employee) {
var valid = employee.addressList.map(function(address) {
if (address.city.startsWith("ABC")) {
finalList.push(employee);
//Employee pushed to validList once, so now break from inner map() function & goto second line/execute on next employee object
}
}); //.slice(0,1); Slice doesn't work here since I want the condition to be true first, then break it.
You can use the some which tests whether at least one element in the array passes the test condition.
Read about some here.
var finalList = empList.filter(e => e.addressList.some(a => a.city.startsWith("ABC")));
Also I've updated your logic to use filter (instead of map) which creates a new array with all elements that pass the provided condition.
You can read about filter at here.

Angular2 - Why does initializing my array cause problems with my data structure?

I have a component that is subscribed to some data used to populate a table. This table uses *ngFor to loop over the array of data and output it to the page, typical stuff.
When I define my array like so importResults: ImportResults[];, my data appears to get stored as intended and I am left with an array of objects.
ngOnInit() {
// Subscribe to our subject that lets us know about the added employees
this._massEmpService.importedData.subscribe(obj => {
if (obj) {
obj.checked = false;
this.importResults = obj;
}
});
}
With this setup, I can use *ngFor without issues by simply doing:
<tbody>
<tr *ngFor="let i of importResults" >
<td>
<input type="checkbox"
id="checkbox_{{ i.QID }}"
[checked]="i.checked"
(click)="toggleSelectedEmployee(i)"
[(ngModel)]="i.checked" />
</td>
...
</tr>
</tbody>
However... when I initialize my array like so importResults: ImportResults[] = []; it alters my data structure.
This leaves me with an array of arrays of objects?
This causes me to have to do some weird nested looping on my table which doesn't seem right.
<tbody *ngFor="let res of importResults">
<tr *ngFor="let i of res" >
<td>
<input type="checkbox"
id="checkbox_{{ i.QID }}"
[checked]="i.checked"
(click)="toggleSelectedEmployee(i)"
[(ngModel)]="i.checked" />
</td>
...
</tr>
</tbody>
Is this expected behavior to need to nest stuff like this? The first way works fine for how I would expect to be able to loop but because its not initialized, I can't push new data to it which is why I had to go with the expected way of defining it Array[] = [];
Am I doing something wrong here?
In your first instance, you declare the variable, but don't initialize it, then when you subscribe to the data service you assign the resulting array of objects to the variable:
this.importResults = obj;
In your second case, you declare the variable and initialize it as an empty array:
importResults: ImportResults[] = [];
Then when you get your data back from the service you're doing this:
this.importResults.push(obj);.
This is taking the returned array of objects from the data service and pushing it into the array you've already created, so that's why it ends up being nested. In the first, you're making your variable equal to the array of objects you're getting back, and in the second you're pushing the array of objects into the existing array.
If you used the same assignment in the second case:
this.importResults = obj;
You wouldn't have this problem, whether you initialized the variable to an empty array when you declared it or not.
If what you're trying to do is fetch one or more objects from a service and add them to an existing array, which may already have one or more objects inside, then you want to return the objects via subscribe, and iterate over them, pushing each object in that returned array one at a time into the existing array.

Observable array and computed error

I have a list of checkboxes that execute functions on check and uncheck. I also have an observable array that holds the values of the checkboxes currently active (put into local storage). The relevant code is here:
this.layerToggleChecked = knockout.observableArray();
// ...
this.layerToggle = function (source, name, type, url, description) {
return knockout.computed({
read: function () {
return this.layerToggleChecked();
},
write: function (checked) {
if (checked) {
alert("loading");
this.layerToggleChecked.push(source());
} else {
alert("removing");
this.layerToggleChecked.remove(source());
}
}
}, this);
}
The checkboxes work as planned triggering the functions until I added return this.layerToggleChecked(); which returns
knockout-3.2.0.js:13 Uncaught TypeError: b.push is not a function
Knockout's checked binding handles arrays differently from other values. You're expecting a true or false to be written to the computed observable, but you're returning an array, which obviously aren't the same.
From http://knockoutjs.com/documentation/checked-binding.html:
Special consideration is given if your parameter resolves to an array. In this case, KO will set the element to be checked if the value matches an item in the array, and unchecked if it is not contained in the array.
When the user checks or unchecks the checkbox, KO will add or remove the value from the array accordingly.
Since you're using an array to hold the checked values, you're better off binding directly to it:
<input type="checkbox" data-bind="checkedValue: source, checked: layerToggleChecked" />

How to select a key/value pair with two further keys/values nested inside?

I am using the below code to iterate through a JSON object which has a dynamic key at the top level.
for (var key in data.query.results.json) {
if(firstSkipped == false) {
firstSkipped = true; // sets skipping variable to true so condition is met on next iteration
} else {
for (var key2 in data.query.results.json[key]) {
if(key2 == "http:__purl.org_rss_1.0_title")
titles.push(data.query.results.json[key][key2].value); // pushes titles to array
It works fine however, I need to add another field which is complicating things. The fields below all just have a single value inside them, however, the new field I need to add has a further two keys, each with a value. I need to select just one of these and display the value. I've tried doing the following but I just get 'undefined'.
for (var key3 in data.query.results.json[key]) {
if(key3 == "0")
isbns.push(data.query.results.json[key][key2][key3].value); // pushes urls to array
}
I'm just trying to select the 3rd Key down, then search through each field until it finds the key called '0', then push its value to an array.
Any ideas where I'm going wrong? I can try and post a sample of the JSON if it doesn't make sense without seeing it.
Here is what the data looks like (it is the ISBN field I'm trying to get to):

Categories

Resources