Angular 9 ng内容动态更新

问题描述

我如何通过更新内容元素上的选择器来更新ng-content?

我在app.component.html中有代码

<my-slider>
  <img src="../../assets/logo1.png" />
  <img src="../../assets/logo2.png" />
</my-slider>

这是代码my-slider.component.ts:

@Component({
  selector: 'my-slider',template: '<ng-content select=".render" ></ng-content>
             <button (click)="render()"> Show</button>',styleUrls: ['./slider.component.css']
})
export class SliderComponent {
  @ContentChildren(ImgComponent) img: QueryList<ImgComponent>;
  constructor() { }
  render() {
    this.img.last.show();
  }
}

和ImgComponent.ts

@Component({
  selector: 'img',template: '',})
export class ImgComponent {
  render: boolean = false;

  constructor(
    private elRef: ElementRef,private renderer: Renderer2
  ) { }

  show() {
    this.render = true;
    this.renderer.addClass(this.elRef.nativeElement,'render');
  }
  hide() {
    this.render = false;
    this.renderer.removeClass(this.elRef.nativeElement,'render');
  }
}

当我单击按钮时,将向该元素添加一个类,但是ng-content从不更新。我能以某种方式使其工作吗?或者如何过滤ng-content中的组件?

解决方法

关于ng-content更新,我没有您的问题的答案,并且ng-content是Angular IMHO的文档不足的功能。但是我确实有解决问题的方法:

<img 
  *ngFor="let img of images"
  [style.display]="img.render ? undefined : 'none'"
  [src]="img.src"
></img>

然后,在组件上制作一个public images: {render: boolean,src: string}[],并切换项目的render属性。

,

由于建议的解决方案将自定义img组件封装到本机组件中,因此您需要访问组件中的host元素。我建议在这里使用自定义属性指令。参见Stackblitz example

,

非常感谢您的回复。这是我一直在寻找的解决方案:

我已经向img添加了一个结构指令,而不是使其成为有角度的组件,现在app.component.html看起来像:

<app-slider>
  <img *myImg scr="../../assets/logo1.png" />
  <img *myImg scr="../../assets/logo1.png" />
</app-slider>

my-slider.component.ts并没有真正改变。无论如何,我只是删除了select='.render'

@Component({
  selector: 'app-slider',template: `<ng-content></ng-content>
            <br/>
            <button (click)="render()">Toggle</button>`,})
export class SliderComponent {
  @ContentChildren(ImgDirective) img: QueryList<ImgDirective>;
  constructor() { }
  ngAfterContentInit() {
    this.img.first.show();
  }
  render() {
    if (!this.img.last.render) {
      this.img.last.show();
    } else {
      this.img.last.hide();
    }
  }
}

最后我的结构指令ImgDirective:

import { Directive,TemplateRef,ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[myImg]'
})
export class ImgDirective {
  render: boolean = false;
  constructor(
    private viewContainer: ViewContainerRef,private templateRef: TemplateRef<any>,) { }

  ngOnInit() {
    this.viewContainer.clear();
  }

  show() {
    this.render = true;
    this.viewContainer.createEmbeddedView(this.templateRef)
  }

  hide() {
    this.render = false;
    this.viewContainer.clear();
  }
}

以下示例:link