【问题标题】:Angular 9 ng-content dynamic updateAngular 9 ng-content 动态更新
【发布时间】:2020-12-18 01:04:39
【问题描述】:

如何通过更新内容元素上的选择器来更新 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 可能不是一个非常适合的人选。为什么不制作一个包含render boolean 和 img src 的对象字典,然后通过这些对象进行 ngFor 并切换渲染属性?

标签: javascript angular ng-content


【解决方案1】:

谢谢大家的回复。这是我一直在寻找的解决方案:

我向 img 添加了一个结构指令,而不是使其成为 angular 组件,现在 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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      我没有关于ng-content 更新的问题的答案,ng-content 是 Angular 恕我直言的一个未充分记录的功能。但我确实有解决问题的办法:

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

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

      【讨论】:

      • 没问题 :) 我看到你刚刚创建了 StackOverflow 帐户,恭喜。如果网站上的任何答案对您来说都是定性的,您可以投票以奖励发布者。如果您提出问题并且答案解决了问题,您可以使用绿色复选标记接受它;)
      • 是的,谢谢您的回答。这对我来说有点倒退。如果我理解正确,最好用 *ngIf="img.render" 将它包装在 ng-contaner 中,以确保元素永远不会呈现。因为我有类似的情况,其中 'ImgComponent' 超过 5000,如果它全部呈现在 dom 中,我认为它会花费很多性能。
      猜你喜欢
      • 2020-11-03
      • 2018-05-24
      • 1970-01-01
      • 1970-01-01
      • 2020-03-18
      • 2022-12-22
      • 2018-08-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多