为NativeScript动态生成Angular2组件

时间:2016-12-30 02:10:35

标签: angular nativescript angular2-nativescript

我需要从服务器下载内容并将内容集成到我的Nativescript / Angular2应用中。内容提供商希望能够格式化文本。我使用过HtmlView和WebView,但它们有一些限制。

  1. WebView无法动态增长以适应内容的大小 例如StackLayout。它创建了一个不滚动的滚动区域 适合我们想要提供的用户体验。

  2. HtmlView非常 有限的HTML / CSS格式支持,特别是在Android上。 <font color='green'>例如不起作用!

  3. 所以我开始考虑动态生成Angular2组件。那是从服务器下载模板。我一直在关注SO Answer中的讨论并取得了一些成功。 UI是从运行时提供的简单字符串呈现的,是的!示例项目可以在github dynamic-demo上找到。 enter image description here

    为此,我已经更新了NG模板项目:

    @Component({
        selector: "my-app",
        templateUrl: "app.component.html",
    })
    export class AppComponent implements AfterViewInit { 
        @ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef;
    
        constructor(
             @Inject('DynamicComponent') private _dynamicComponent: DynamicComponent
        ){};
    
        ngAfterViewInit() {
            this._dynamicComponent.addComponent(
                this.container,
                ` <Label text="Hello, World!" class="h1 text-center"> </Label>
                  <Button text="Tap Again" (tap)="onTap()" class="btn btn-primary btn-active"> </Button>  
                `
            )
        }
    
        public counter: number = 16;
          public get message(): string {
            if (this.counter > 0) {
                return this.counter + " taps left";
            } else {
                return "Hoorraaay! \nYou are ready to start building!";
            }
        }
    
        public onTap() {
            this.counter--;
        }
    }
    

    增强的核心是我添加的DynamicComponent类:

    import { Injectable, Compiler, Component, NgModule, ViewContainerRef} from '@angular/core'
    
    @Injectable()
    export class DynamicComponent {
        constructor(private compiler: Compiler) {}
    
        public addComponent(container: ViewContainerRef, template: string) {
            @Component({template: template})
            class TemplateComponent {
    
                onTap(args) {
                    console.log('onTap()');
                }
            }
    
            @NgModule({declarations: [TemplateComponent]})
            class TemplateModule {}
    
            const mod = this.compiler.compileModuleAndAllComponentsSync(TemplateModule);
            const factory = mod.componentFactories.filter((comp) =>
            comp.componentType === TemplateComponent
            );
            const component = container.createComponent(factory[0]);
        }
    }
    

    我想获得有关我的方法的一般反馈。

    1. 这会有用吗?
    2. 我是否需要担心原始StackOverflow讨论中较大答案的问题?
    3. 如何进行设置,以便我可以将该动作功能作为DynamicClass的输入提供,而不是像我已经完成的那样将它们嵌入到班级中 与onTap()

1 个答案:

答案 0 :(得分:1)

以下是我的问题3的解决方案:

ngAfterViewInit() {
    var component = <any> 
        this._dynamicComponent.addComponent(
            this.container, `
            <Label text="Hello, World!" class="h1 text-center"> </Label>
            <Button text="Tap Again" (tap)="onTap()" class="btn btn-primary btn-active"> </Button>  
         ` );

    component.prototype.onTap = () => {
        this.counter++;
    } 
}

我更新addComponent以返回动态创建的TemplateComponent类,然后我像在JS中一样向对象添加一个函数。有点难看,但它有效。