Angular 9 ng-内容动态更新
Angular 9 ng-content dynamic update
如何通过更新内容元素上的选择器来更新 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');
}
}
当我点击按钮时,一个 class 被添加到元素中,但是 ng-content 永远不会更新。我能以某种方式让它工作吗?或者我如何过滤 ng-content 中的组件?
我无法回答您关于 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
属性。
您需要访问组件中的宿主元素,因为您提出的解决方案将您的自定义 img 组件封装到本机组件中。我建议在这里使用自定义属性指令。参见 Stackblitz example
谢谢大家的回复。这是我一直在寻找的解决方案:
我向 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
如何通过更新内容元素上的选择器来更新 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');
}
}
当我点击按钮时,一个 class 被添加到元素中,但是 ng-content 永远不会更新。我能以某种方式让它工作吗?或者我如何过滤 ng-content 中的组件?
我无法回答您关于 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
属性。
您需要访问组件中的宿主元素,因为您提出的解决方案将您的自定义 img 组件封装到本机组件中。我建议在这里使用自定义属性指令。参见 Stackblitz example
谢谢大家的回复。这是我一直在寻找的解决方案:
我向 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