In my project I have wrapper classes that are reused often and some contain the 'gap' css property. Now I have a component that loads data asynchronously and that component is hidden if the returned data is empty.
The problem I face is that the wrappers I used to surround my component are still displayed and therefore cause the gap to activate. Below is an example with two wrappers, but depending on the use-cases it could be more or other wrappers that are needed.
At the moment:
Working data:
<card-wrapper>
<specific-margin-wrapper>
<component-loading-data />
</specific-margin-wrapper>
</card-wrapper>
Without data:
<card-wrapper>
<specific-margin-wrapper>
<component-loading-data style="display: none" />
</specific-margin-wrapper>
</card-wrapper>
My goal:
Working data:
<card-wrapper>
<specific-margin-wrapper>
<component-loading-data />
</specific-margin-wrapper>
</card-wrapper>
Without data:
<card-wrapper style="display: none" >
<specific-margin-wrapper style="display: none" >
<component-loading-data style="display: none" />
</specific-margin-wrapper>
</card-wrapper>
I want to "display: none" the wrapper classes when the child-component is not displayed too.
I tried to use css pseudo classes like :empty, but that didn't fully work:
:host:empty {
display: none;
}
Is there a css (less) solution that works like :empty but includes children with display:none ? Or some ngTemplate / ngContent magic that let's me dynamically add wrapper inside my component.
Ideally I want a solution within my "component-loading-data" so that I don't need to change the parent component where I use it
EDIT: Added StackBlitz example
Unfortunately, I didn't find a solution inside my loading-component, but I have a somewhat clean solution by referencing a parent element via id in the template.
I've created a directive that allows to hide given elements:
@Directive()
export abstract class HideableContainerDirective {
private readonly platformId = inject(PLATFORM_ID);
private readonly document: Document = inject(DOCUMENT);
private readonly renderer: Renderer2 = inject(Renderer2);
@Input() public hideableComponentId?: string;
protected hideComponent(): void {
if (!isPlatformBrowser(this.platformId)) return;
if (this.hideableComponentId) {
const element = this.document.getElementById(this.hideableComponentId);
if (element) {
this.renderer.setStyle(element, 'display', 'none');
}
}
}
}
Components that need to be hidden can extend the Directive and call the hideComponent() function accordingly.
export class MessageContainerComponent extends HideableContainerDirective implements OnInit {
public ngOnInit(): void {
const data = this.loadData();
if (data === undefined) {
this.hideComponent();
}
}
}
And set an id in the template to hide the referenced component:
<card-wrapper id='custom_data_container'>
<specific-margin-wrapper>
<component-loading-data [hideableComponentId]="'custom_data_container'" />
</specific-margin-wrapper>
</card-wrapper>