如何动态地将包装器添加到 Angular 组件?

问题描述 投票:0回答:1

在我的项目中,我有经常重用的包装类,其中一些包含“gap”css 属性。现在我有一个异步加载数据的组件,如果返回的数据为空,该组件将被隐藏。

我面临的问题是我用来包围组件的包装器仍然显示,因此导致间隙激活。下面是一个带有两个包装器的示例,但根据用例,可能需要更多或其他包装器。

此刻:

工作数据:

<card-wrapper>
  <specific-margin-wrapper>
    <component-loading-data />
  </specific-margin-wrapper>
</card-wrapper>

没有数据:

<card-wrapper>
  <specific-margin-wrapper>
    <component-loading-data style="display: none" />
  </specific-margin-wrapper>
</card-wrapper>

我的目标:

工作数据:

<card-wrapper>
  <specific-margin-wrapper>
    <component-loading-data />
  </specific-margin-wrapper>
</card-wrapper>

没有数据:

<card-wrapper style="display: none" >
  <specific-margin-wrapper style="display: none" >
    <component-loading-data style="display: none" />
  </specific-margin-wrapper>
</card-wrapper>

当子组件也没有显示时,我想“显示:无”包装类。

我尝试使用像 :empty 这样的 css 伪类,但这并没有完全起作用:

:host:empty {
  display: none;
}

是否有一个 css(较少)解决方案,其工作方式类似于 :empty 但包含带有 display:none 的子项? 或者一些 ngTemplate / ngContent 魔法,让我可以在组件中动态添加包装器。

理想情况下,我希望在“组件加载数据”中找到一个解决方案,这样我就不需要更改使用它的父组件

编辑: 添加了 StackBlitz 示例

angular typescript less angular17
1个回答
0
投票

您可以使用

template reference variables
@ContentChild
contentChild
信号来显示/隐藏组件,我们可以使用
@HostBinding('style.display')
装饰器动态地将样式添加到宿主元素(包装器)。

<app-scroll-wrapper>
  <app-card-wrapper>
    <app-specific-margin-wrapper>
      <div class="no-data" #noData></div> <!-- template reference variable -->
    </app-specific-margin-wrapper>
  </app-card-wrapper>
</app-scroll-wrapper>

TS:

@Component({
  ...
})
export class SpecificMarginWrapperComponent {
  // @ContentChild('noData') noData!: ElementRef<any>;
  noData: Signal<ElementRef<any> | undefined> = contentChild('noData');

  @HostBinding('style.display')
  get displayStyle() {
    return !this.noData() ? 'block' : 'none';
  }

  ngAfterContentInit() {
    console.log(this.noData());
  }
}

完整代码:

import {
  Component,
  ContentChild,
  ElementRef,
  HostBinding,
  contentChild,
  Signal,
} from '@angular/core';

@Component({
  selector: 'app-specific-margin-wrapper',
  standalone: true,
  imports: [],
  templateUrl: './specific-margin-wrapper.component.html',
  styleUrl: './specific-margin-wrapper.component.css',
})
export class SpecificMarginWrapperComponent {
  // @ContentChild('noData') noData!: ElementRef<any>;
  noData: Signal<ElementRef<any> | undefined> = contentChild('noData');

  @HostBinding('style.display')
  get displayStyle() {
    return !this.noData() ? 'block' : 'none';
  }

  ngAfterContentInit() {
    console.log(this.noData());
  }
}

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.