Issue
There are divs that display recipes (from a property on the component in an object array – ‘Recipes’, ‘Recipes’ includes a property ‘Recipes.diet’ that is a string of diets), I have a filterf component that sends subscriptions of diets (currently ‘Vegetarian,’GlutenFree’,’Vegan’). I want to hide recipes that include the diet keyword e.g. an observable of ‘Vegetarian’ hides all recipes that don’t have the ‘Vegetarian’ keyword included in their ‘diet’ property.
Currently I’m not getting difference.
I’ve tried using angular ngClass, ngStyle to dynamically filter the class lists to includes ‘.hide’ (which sets the display to none).
When I statically set the display to ‘none’ it’s successful, I’m currently trying a method that manipulates the Dom directly through HTML Element objects but that isn’t working either.
I’ve checked that the keywords are coming through, and they’re matching up successfully with the correct divs. I’ve tried just setting the style attribute through typescript and adding a class type (this is the method I’m trying below).
I know this will be a very simple issue but I’ve run out of ways to check, I’ve searched online and StackOverflow & tried about every variations of DOM/Angular changing I can think of.
HTML:
<div *ngFor="let recipe of recipes" id="{{recipe.title}}-card" (click)="recipeWasChosen(recipe)">
<app-recipe-title class="recipe-card" [recipe]="recipe">
</app-recipe-title>
</div>
Typescript:
this.recipeService.recipeRestrictions.subscribe((restrictions: string[]) => {
this.recipes.forEach((recipe: Recipe) => {
let hide = false;
for (const restriction of restrictions) {
if (!recipe.diet.includes(restriction)) {
hide = true;
}
}
if (hide) {
this.hideCardWithHTMLElement(recipe.title);
} else this.hideCardWithHTMLElement(recipe.title);
});
});
hideCardWithHTMLElement(title: string) {
let card = document.getElementById(`${title}card`);
if (card.classList.contains('hidden')) {
card.className = '';
} else card.className = 'hidden';
}
CSS:
.hidden {
display: none;
}
Solution
If you just want to filter your list by type of restriction, You don’t need to hide the elements, but you can filter out the ones that contain restrictions in general .you can do something like this
this.recipes$ = this.recipeService.recipeRestrictions
.pipe(
map((restrictions: string[]) => {
return this.recipes.filter((recipe) => restrictions.every((restriction) => !recipe.diet.includes(restriction)))
})
)
and in template
<div *ngFor="let recipe of recipes$ | async">
...
</div>