Issue
I am trying to filter some observable nested array in angular with the filter function in combination pipe function of the RxJs library.
Question: I only want to show the categories with surveys given by a specific date.
Simplified situation: My angular component has 3 radiobuttons (values 1,2,3). If i click on one of them it goes to my 'FilterChanged($event.value)' function. In this function i would like to filter the data that is provided by an api. This api at first provides all the categories. After retrieving the data i would like to filter according to the radio-button.
This is the data i get back from the api:
[
{
"category": "A",
"surveys": [
{
"day": "1",
"answers": [
{
"name": "1",
"value": "a"
},
{
"name": "2",
"value": "b"
},
{
"name": "3",
"value": "c"
}
]
},
{
"day": "2",
"answers": [
{
"name": "1",
"value": "a"
},
{
"name": "2",
"value": "b"
},
{
"name": "3",
"value": "c"
}
]
},
{
"day": "3",
"answers": [
{
"name": "1",
"value": "a"
},
{
"name": "2",
"value": "b"
},
{
"name": "3",
"value": "c"
}
]
}
]
},
{
"category": "B",
"surveys": [
{
"day": "2",
"answers": [
{
"name": "1",
"value": "a"
},
{
"name": "2",
"value": "b"
},
{
"name": "3",
"value": "c"
}
]
},
{
"answers": [
{
"name": "1",
"value": "a"
},
{
"name": "2",
"value": "b"
},
{
"name": "3",
"value": "c"
}
]
},
{
"day": "2",
"answers": [
{
"name": "1",
"value": "a"
},
{
"name": "2",
"value": "b"
},
{
"name": "3",
"value": "c"
}
]
}
]
}
]
If radio button 1 is selected i would like to only show the category A and only show it has 1 survey because thats the only survey matching the filter.
Whyd doesn't this code works?? the update filter gets triggerd at the radiobox change event. For me this is much more readable than the reduce with spreader functions.
updateFilter(filterDays : number): void {
var filterDate = this.getFilterDate(filterDays);
this.surveyTypes$ = this.allSurveyTypes$.pipe(map((types) => this.filterSurveyTypes(types, filterDate)));
}
filterSurveyTypes(types : SurveyType[], filterDate : Date) : SurveyType[] {
return types.filter(type => type.surveys.filter(survey => moment(survey.filledInDate).isSameOrAfter(filterDate)).length);
}
and a lot more variations but it does not seem to work. I think i should not need a map because i am not transforming any data so filter should be fine but is not working for me so far.
I appreciate any help. Thanks
Solution
not positive what you're looking for, but it seems like you want to filter the outer array based on what's in the inner array and also filter the inner array, this can be achieved in one pass with reduce:
function filterOuterByInner(array, value) {
return array.reduce((acc, v) => {
const tmp = { ...v }; // create shallow copy
tmp.surveys = tmp.surveys.filter(a => a.day === value); // filter surveys array by value
if (tmp.surveys.length)
acc.push(tmp); // add to acc array if any surveys after filter
return acc;
}, []);
}
then just use it in your map:
this.categories$ = combineLatest(this.allcategories$, this.value$).pipe(map(([categories, val]) => filterOuterByInner(categories, val)));
Answered By - bryan60
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.