Reputation: 498
I'm trying to filter this objects array and keep the original one aside.
{"departments":
[
{
“name": “AAA",
“selected”: true,
"courses": [
{
"name": “course1",
“selected”: true,
“titles”:
[{
"name": “title1",
“selected”: true
},
{
"name": “title2",
“selected”: false
}]
},
{
"name": “course2",
“selected”: false,
“titles”:
[{
"name": “title1",
“selected”: false
}]
}
]
},
{
“name": “BBB",
“selected”: false,
"courses": [{...}]
{...}
]
}
I want to find all the selected departments, courses and titles. And it should be in the same format. I tried with below code, but it change original data. I want to keep that aside too.
const depts = departments.filter((dept: any) => {
if (dept.selected) {
dept.courses = dept.courses.filter((course: any) => {
if (course.selected) {
if (course.titles) {
course.titles = course.titles.filter(({selected}: any) => selected);
}
return true;
}
return false;
});
return true;
}
return false;
});
What would be considered the best solution in this case?
Upvotes: 0
Views: 311
Reputation: 706
I don't know if you prefer an API false. Here is my tip:
You can to use an API Json Server.
Install JSON Server
npm install -g json-server
Create a db.json file with some data
{
"posts": [
{ "id": 1, "title": "json-server", "author": "typicode" }
],
"comments": [
{ "id": 1, "body": "some comment", "postId": 1 }
],
"profile": { "name": "typicode" }
}
Start JSON Server
json-server --watch db.json
Now if you go to http://localhost:3000/posts/1
, you'll get
{ "id": 1, "title": "json-server", "author": "typicode" }
you can search your array of objects using various shapes and it will come filtered. More about the API here: https://github.com/typicode/json-server
(Use a filter to do your searches on the Angular, it will bring you right what you need, use a method inside your component)
Upvotes: 0
Reputation: 2575
const filterSelected = obj => {
return {
...obj,
departments: obj.departments.map(dep => {
return {
...dep,
courses: dep.courses.map(course => {
return {
...course,
titles: course.titles.filter(title => title.selected),
};
}).filter(course => course.selected),
};
}).filter(dep => dep.selected),
};
}
const all = {
departments: [
{
name: "AAA",
selected: true,
courses: [
{
name: "course1",
selected: true,
titles: [
{
name: "title1",
selected: true
}, {
name: "title1",
selected: false
}
]
}, {
name: "course2",
selected: false,
titles: [
{
name: "title1",
selected: false
}
]
},
]
}
]
};
console.log(filterSelected(all));
Upvotes: 0
Reputation: 22876
Shorter alternative can be to use the JSON.parse
reviver parameter :
var arr = [{ name: "AAA", selected: true, courses: [{name: "course1", selected: true, titles: [{ name: "title1", selected: true }, { name: "title1", selected: false }]}, { name: "course2", selected: false, titles: [{ name: "title1", selected: false }]}]}]
var result = JSON.parse(JSON.stringify(arr), (k, v) => v.map ? v.filter(x => x.selected) : v)
console.log( result )
Upvotes: 1
Reputation: 4854
your filtering logic seems to be correct. only problem is that code changes original array. in order to overcome this problem just create a deep clone of original array and run filtering logic on it
filterArray() {
const clone = JSON.parse(JSON.stringify(this.departments));
const depts = clone.filter((dept: any) => {
if (dept.selected) {
dept.courses = dept.courses.filter((course: any) => {
if (course.selected) {
if (course.titles) {
course.titles = course.titles.filter(({ selected }: any) => selected);
}
return true;
}
return false;
});
return true;
}
return false;
});
console.log(depts);
}
here is a demo https://stackblitz.com/edit/angular-xx1kp4
Upvotes: 1