首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按顺序加载动态创建的组件

按顺序加载动态创建的组件
EN

Stack Overflow用户
提问于 2016-12-20 12:13:50
回答 3查看 1.2K关注 0票数 0

我试图使用以下代码实现动态组件-

代码语言:javascript
复制
createWidget(template: string) {
    const html = template;
    if (!html) return;

    if (this.cmpRef) {
        this.cmpRef.destroy();
    }
    const compMetadata = new Component({
        selector: 'dynamic-html',
        template: html
    });
    this.createComponentFactory( this.compiler, compMetadata )
        .then(factory => {
            const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
            console.log("Injector: " + injector);
            this.vcRef.createComponent(factory, 0, injector, []);
            console.log( "Create Widget End.." );
        });
} 

createComponentFactory( compiler: Compiler, metadata: Component) {

    @Component( metadata )
    class DynamicComponent { };
    @NgModule({
        imports: [ CommonModule, FormsModule ],
        declarations: [ DynamicComponent ]
    })
    class DynamicHtmlModule { }
    return compiler.compileModuleAndAllComponentsAsync( DynamicHtmlModule )
        .then(( moduleWithComponentFactory: ModuleWithComponentFactories<any> ) => {
            return moduleWithComponentFactory.componentFactories.find( x => x.componentType === DynamicComponent );
        });
}

在调用createWidget方法时,代码运行良好-

this.createWidget('Angular2');

但问题是,当我多次使用for循环调用createWidget时,生成的模板是反向有序的。请看我的柱塞https://plnkr.co/edit/hqKYsGlyuk78tg61zjfd?p=preview

在这个柱塞示例中,Angular2比Angular1之前显示。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-12-20 12:34:09

你有两个选择:

1-创建模块是同步的,为了确保组件以与for循环相同的顺序出现在DOM中,您需要像这样使用循环索引:

代码语言:javascript
复制
for(var i = 1; i <= 2; i++) {
      this.createWidget('<h1>Angular' + i + '</h1>' , i-1);  // minus 1 because you're starting from 1  !!!!!
    }


createWidget(template: string , index) {
        const html = template;
        if (!html) return;

        if (this.cmpRef) {
            this.cmpRef.destroy();
        }
        const compMetadata = new Component({
            selector: 'dynamic-html',
            template: html
        });
        this.createComponentFactory( this.compiler, compMetadata )
            .then(factory => {
                const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
               this.vcRef.createComponent(factory, index, injector, []);
            });
    } 

因为在循环中有一个异步函数( createComponentFactory ),所以您永远不能保证第一个组件总是首先创建的,而第二个组件是第二个组件,因为第一个组件的编译可能需要超过第二个组件,然后第二个组件将首先被解析。

对于这种情况,更具体和更可靠的方法是传递索引并确保将它们按For循环的相同顺序排列。

这是你的柱塞,运转良好。

https://plnkr.co/edit/VmmwzzrcJq6En5tXcyl6?p=preview

2-同步创建模块,然后您可以信任它们将始终按照顺序出现,而无需自己定义索引。

代码语言:javascript
复制
export class App {
  name:string;
  constructor(public compiler: Compiler, public vcRef: ViewContainerRef) {
    this.name = 'Angular2';
    for(var i = 1; i <= 2; i++) {
      this.createWidget('<h1>Angular' + i + '</h1>');  
    }

  }

  createWidget(template: string ) {
        const html = template;
        if (!html) return;

        if (this.cmpRef) {
            this.cmpRef.destroy();
        }
        const compMetadata = new Component({
            selector: 'dynamic-html',
            template: html
        });
        let factory = this.createComponentFactory( this.compiler, compMetadata )
        const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
               this.vcRef.createComponent(factory, undefined , injector, []);

    } 

    createComponentFactory( compiler: Compiler, metadata: Component ) {
        @Component( metadata )
        class DynamicComponent { };
        @NgModule({
            imports: [ CommonModule ],
            declarations: [ DynamicComponent ]
        })
        class DynamicHtmlModule { }
        let moduleWithComponentFactory = compiler.compileModuleAndAllComponentsSync( DynamicHtmlModule )
            console.log(moduleWithComponentFactory.componentFactories)
                return moduleWithComponentFactory.componentFactories.find( x => x.componentType === DynamicComponent );

    }

}

https://plnkr.co/edit/9WNrVABMupq1q2YKO5wi?p=preview

票数 2
EN

Stack Overflow用户

发布于 2017-05-28 15:51:25

您可以尝试计算indexvcRef.createComponent方法,如

代码语言:javascript
复制
loadedIndices: number[] = [];
...
let renderedIndex = this.loadedIndices.indexOf(Math.max.apply(Math, this.loadedIndices.filter(x => x <= index))) + 1;

this.vcRef.createComponent(factory, renderedIndex, injector, []);

this.loadedIndices.push(index);
this.loadedIndices.sort((a, b) => a - b);

其中,index是每个组件的目标索引。

柱塞实例

票数 1
EN

Stack Overflow用户

发布于 2016-12-20 12:18:47

只需将0

代码语言:javascript
复制
this.vcRef.createComponent(factory, 0, injector, []);

这使得每个组件被插入到位置0(在所有其他组件之前)。

如果没有显式索引,则在前面添加的组件后面追加每个组件:

代码语言:javascript
复制
this.vcRef.createComponent(factory, {injector: injector, projectableNodes: []});
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41242124

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档