如何删除 Angular 添加到组件的包装元素?

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

我正在制作一个 Angular 应用程序 + Tailwind,它是一个大型水平页面,允许用户使用

scroll-snap-type
从左向右滚动。当我尝试清理代码并创建可重用组件时,呈现的 html 与我将所有 HTML 放在一个组件中时不同。

我创建了一个ScrollContainerComponent:

import { ChangeDetectionStrategy, Component, ElementRef, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-scroll-container',
  standalone: true,
  template: `
    <div
      class="flex snap-x snap-proximity h-screen w-full mx:auto overflow-x-scroll overflow-y-hidden "
      #scrollContainer
    >
      <ng-content></ng-content>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ScrollContainerComponent {
  @ViewChild('scrollContainer')
  scrollContainer!: ElementRef;

  ngAfterViewInit() {
    this.scrollContainer.nativeElement.addEventListener('keydown', this.handleKeydown.bind(this));
  }

  handleKeydown(event: KeyboardEvent) {
    switch (event.key) {
      case 'ArrowLeft':
        this.scrollLeft();
        break;
      case 'ArrowRight':
        this.scrollRight();
        break;
    }
  }

  scrollLeft() {
    this.scrollContainer.nativeElement.scrollLeft -= 100;
  }

  scrollRight() {
    this.scrollContainer.nativeElement.scrollLeft += 100;
  }
}

还有一个孩子:

import { ChangeDetectionStrategy, Component } from '@angular/core';

@Component({
  selector: 'app-scroll-child',
  template: `<div class="snap-start shrink-0 grid w-full h-screen place-items-center text-8xl">
    <ng-content></ng-content>
  </div>`,
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
})
export class ScrollChildComponent {}

但是,只有当我像这样使用它时它才有效:

<app-scroll-container>
      <div class="snap-start shrink-0 bg-amber-200 grid w-full h-screen place-items-center  text-8xl">1</div>
      <div class="snap-start shrink-0 bg-blue-200 grid w-screen h-screen place-items-center text-8xl">2</div>
      <div class="snap-start shrink-0 bg-orange-200 grid w-screen h-screen place-items-center text-8xl">3</div>
      <div class="snap-start shrink-0 bg-green-200 grid w-screen h-screen place-items-center text-8xl">4</div>
    </app-scroll-container>

而不是使用

<app-scroll-child>1</app-scroll-child>

请帮我删除包装元素角度添加到

app-scroll-child

angular scroll tailwind-css encapsulation
1个回答
0
投票

这可能有点 hacky,但您可以让容器组件从每个子组件中提取内容,手动将该内容附加到自身,然后从其视图中删除子组件。

为此,子组件需要有对其视图内容的公共引用,以便容器组件可以访问它,如下所示:

@Component({
  selector: 'app-scroll-child',
  template: `<div #targetEl <------------------------ Add this template variable
  class="snap-start shrink-0 grid w-full
    h-screen place-items-center text-8xl">
  <ng-content></ng-content>
  </div>`,
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
})
export class ScrollChildComponent {
  @ViewChild('targetEl') targetEl: ElementRef; // <-- and this reference to it
}

然后,在容器组件中,您需要添加一个 ContentChildren 引用,以允许容器迭代子级、提取其内容并将其内容直接附加到容器内,如下所示:

export class ScrollContainerComponent {
  @ViewChild('scrollContainer')
  scrollContainer: ElementRef;

  @ContentChildren (ScrollChildComponent)
  scrollChildComponents: QueryList<ScrollChildComponent> // <-- Add this

  ngAfterViewInit() {
    this.scrollChildComponents.forEach((child: ScrollChildComponent) => { // <-- and this
      this.scrollContainer.nativeElement.appendChild(child.targetEl.nativeElement)
    })
  }
}

将子内容直接附加到容器中后,您只需删除子组件引用/包装器即可。

为此,您可以将

*ngIf
附加到容器内的
ng-content
,并在内容附加完成后,将
*ngIf
引用设置为
false
,这将从容器中删除
<app-scroll-child>
元素。容器。

因此您的容器组件更改将如下所示:

@Component({
  selector: 'app-scroll-container',
  standalone: true,
  imports: [
    CommonModule
  ],
  template: `
    <div
      class="flex snap-x snap-proximity h-screen w-full mx:auto overflow-x-scroll overflow-y-hidden "
      #scrollContainer
    >
      <ng-content *ngIf="showContentChildren"></ng-content> <----- Add *ngIf here
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ScrollContainerComponent {
  @ViewChild('scrollContainer') scrollContainer: ElementRef;
  @ContentChildren (ScrollChildComponent) scrollChildComponents: QueryList<ScrollChildComponent>

  protected showContentChildren = true

  constructor(
    private cd: ChangeDetectorRef
  ) {}

  ngAfterViewInit() {
    this.scrollChildComponents.forEach((child: ScrollChildComponent) => {
      this.scrollContainer.nativeElement.appendChild(child.targetEl.nativeElement)
    })
    setTimeout(() => {
      this.showContentChildren = false // <------------ hide child components here
      this.cd.markForCheck()
    })
  }
}

这里有一个 StackBlitz 展示了这种方法。

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