如何从列表显示ng-templates [英] How to display ng-templates from list

查看:72
本文介绍了如何从列表显示ng-templates的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个AppComponent,其中保存着ShapeComponents的列表.我实现了一些扩展ShapeComponent的组件,例如LineComponentCircleComponentRectangleComponent.它们每个都有自己的ng-template#shapeTemplate. 在我的app.component.html中,我想遍历ShapeComponents的列表并显示每个ng-template(来自LineComponentCircleComponent等).

I have an AppComponent which holds a list of ShapeComponents. I implemented some Components which extends the ShapeComponent like LineComponent, CircleComponent, RectangleComponent. Each of them has its own ng-template with #shapeTemplate. In my app.component.html I want to iterate over the list of ShapeComponents and display each ng-template (from LineComponent, CircleComponent etc).

所以我有

shapes: ShapeComponent[] = []

其中包含LineComponent,CircleComponent等

which hold a LineComponent, CircleComponent etc

我想要这样的东西

<div *ngFor="let shape of shapes">
    <!-- How to display the ng-template from for example LineComponent or Circle -->
</div>

我认为使用@ViewChildren或@ContentChildren会很有用,但不知道如何处理

I thought using @ViewChildren or @ContentChildren would be useful but no idea how to deal with that

推荐答案

我找到了解决方案.实际上,我在github上找到了一个很棒的帖子

I found the solution. Actually I found an excellent post on github

https://github.com/shivs25/angular5-canvas-drawer .我采用了这种解决方案来实现自己的解决方案.

https://github.com/shivs25/angular5-canvas-drawer. I took this solution to implement my own.

因此,所有功劳归Billy Shivers所有.干得好.

So all the credits go to Billy Shivers. Well done.

这是解决方案

直线和圆的设置可以动态设置,下面仅是直线和圆的示例

The settings for line and circle can be dynamic set, below is just an example of a line and circle

CircleComponent和HTML模板

CircleComponent and HTML template

import { Component } from '@angular/core';
import { ShapeComponent } from '../shape/shape.component';

@Component({
    selector: 'app-circle',
    templateUrl: './circle.component.html',
    styleUrls: ['./circle.component.css']
})
export class CircleComponent extends ShapeComponent {

    constructor() {
        super('circle');
    }
}

html

<ng-template #elementTemplate>
    <svg:circle [attr.cx]="50" [attr.cy]="50" [attr.r]="40" stroke="black" stroke-width="3" fill="red" />
</ng-template>>

LineComponent和HTML模板

LineComponent and HTML template

import { Component } from '@angular/core';
import { ShapeComponent } from '../shape/shape.component';

@Component({
    selector: 'app-line',
    templateUrl: './line.component.html',
    styleUrls: ['./line.component.css']
})
export class LineComponent extends ShapeComponent {

    constructor() {
        super('line');
        console.log('linecomponent:constructor');
    }

}

html

<ng-template #elementTemplate>
    <svg:line [attr.x1]="100" [attr.y1]="100" [attr.x2]="200" [attr.y2]="200" style="stroke:#006600; stroke-width:1px" />
</ng-template>>

ShapeComponent和HTML

The ShapeComponent and HTML

import { Component, OnInit, ViewChild, TemplateRef, AfterViewInit } from '@angular/core';

@Component({
    selector: 'app-shape',
    templateUrl: './shape.component.html',
    styleUrls: ['./shape.component.css']
})
export class ShapeComponent implements OnInit, AfterViewInit {
    shapeType: string;
    visible: boolean = true;

    id: string = 'unknown';

    @ViewChild('elementTemplate')
    elementTemplate: TemplateRef<any>;

    constructor(shapeType: string) {
        console.log('shapecomponent constructor :', shapeType);
        this.shapeType = shapeType;
    }

    setid(value: string): void {
        this.id = value;
    }

    ngOnInit() {
        console.log('ShapeComponent ngOnInit()');
    }

    ngAfterViewInit(): void {
        console.log('!!!!!!!!! ShapeComponent ngAfterViewInit: ', this.elementTemplate);
    }

}

html:无

组件类型的枚举

export enum ShapeTypes {
    Line,
    Circle,
    Rectangle
}

ShapeHolderComponent

The ShapeHolderComponent

import { Component, OnInit, ViewChild, TemplateRef, AfterViewInit } from '@angular/core';

import { ShapeComponent } from '../shape/shape.component';
import { LineComponent } from '../line/line.component';
import { CircleComponent } from '../circle/circle.component';
import { ShapeTypes } from '../model/shape-types';

@Component({
    selector: 'app-shapeholder',
    templateUrl: './shapeholder.component.html',
    styleUrls: ['./shapeholder.component.css']
})
export class ShapeholderComponent implements OnInit, AfterViewInit {

    @ViewChild('elementTemplate')
    elementTemplate: TemplateRef<any>;

    shapes: ShapeTypes[];

    constructor() {
        this.shapes = [];
        this.shapes.push(ShapeTypes.Line);
        this.shapes.push(ShapeTypes.Circle);
        console.log('shapeholder shapes :', this.shapes);
    }

    ngOnInit() {
        console.log('ShapeHolderComponent : ngOnInit()');
    }

    ngAfterViewInit(): void {
        console.log('!!!!!!!!! ShapeHolder ngAfterViewInit: ', this.elementTemplate);
    }

}

html,为svg在CSS中设置宽度的高度

html, set height in width in css for the svg

<svg>
    <ng-container *ngFor="let shape of shapes; let i = index">
        <ng-container svg-dynamic [componentData]="shape">
        </ng-container>
    </ng-container>
</svg>

其中最重要的部分是指令

And the most import part of it, the directive

import { Directive, Input, ViewContainerRef, Injector, ComponentFactoryResolver } from '@angular/core';
import { ShapeComponent } from './shape/shape.component';
import { LineComponent } from './line/line.component';
import { CircleComponent } from './circle/circle.component';
import { ShapeTypes } from './model/shape-types';

@Directive({
    selector: '[svg-dynamic]'
})
export class SvgDynamicDirective {

    constructor(private _viewContainerRef: ViewContainerRef, private _resolver: ComponentFactoryResolver) {

    }

    @Input() set componentData(data: ShapeTypes) {
        console.log('set componentdata : ', data);

        let injector = Injector.create([], this._viewContainerRef.parentInjector);
        console.log('injector:', injector);
        let factory = this._resolver.resolveComponentFactory(this.buildComponent(data));
        console.log('factory:', factory);
        let component = factory.create(injector);
        console.log('component:', component);
        let c: ShapeComponent = <ShapeComponent>component.instance;

        console.log('viewContainerRef:', this._viewContainerRef);
        console.log('elementTemplate:', c.elementTemplate);
        this._viewContainerRef.clear();
        this._viewContainerRef.createEmbeddedView(c.elementTemplate);
    }

    private buildComponent(data: ShapeTypes): any {
        switch (data) {
            case ShapeTypes.Line:
                return LineComponent;
            case ShapeTypes.Circle:
                return CircleComponent;
        }
        return null;
    }

}

和app.component html

And the app.component html

<div style="text-align:center">
    <h1>
        Welcome to {{ title }}!
    </h1>
    <app-shapeholder></app-shapeholder>
</div>

app.component

The app.component

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'demo1';
}

还有app.module.ts

And the app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { ShapeComponent } from './shape/shape.component';
import { LineComponent } from './line/line.component';
import { ShapeholderComponent } from './shapeholder/shapeholder.component';
import { SvgDynamicDirective } from './svg-dynamic.directive';
import { CircleComponent } from './circle/circle.component';

@NgModule({
    entryComponents: [
        LineComponent,
        ShapeComponent,
        CircleComponent
    ],
    declarations: [
        AppComponent,
        LineComponent,
        ShapeComponent,
        CircleComponent,
        ShapeholderComponent,
        SvgDynamicDirective,
    ],
    imports: [
        BrowserModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }

还有我的应用的最终屏幕截图

And a final screen shot of my app

我希望这个答案对您有用,并且可以在您自己的应用中使用它.这个想法是创建动态模板视图

I hope you find this answer usefull and can use it in your own app. The idea is to create dynamic templates views

这篇关于如何从列表显示ng-templates的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆