Angular元素两次调用组件构造函数

时间:2019-02-11 14:25:32

标签: javascript angular angular-elements

我正在使用递归查询构建器表单,该表单类似于this,以角度7,具有反应形式。意味着,用户可以通过单击Add rule来继续添加并行规则,也可以通过单击Add group来添加组。 我创建了两个组件,QueryDesignerComponentQueryComponentQueryDesignerComponent保存外部容器,条件为ANDORQueryComponent保存行输入,即LHSoperator和{{1 }}。

  1. 当用户单击RHS时,我正在通过在Add rule中用QueryComponent推送一个条目来扩展规则。我要用QueryDesignerComponent重复一遍。
  2. 当用户单击*ngFor时,我正在Add group内调用QueryDesignerComponent,这使其递归。我要用QueryComponent重复一遍。

我已经完成了在角度应用程序中的实现及其在角度应用程序中的正常工作。

现在,我正在尝试将此流移植到angular elements中,以使其可重用,而不管环境如何。

这就是我将第一行[*ngFor]放在QueryComponent内的方式,

QueryDesignerComponent

通过这种方式,我可以管理<div class="qd--criteria"> <div class="row qd--body qd--clear-margin-lr"> <div class="col-md-12 qd--condition-container"> <query [data]="data" [operators]="operators" [(queryForm)]="queryForm"></query> </div> </div> </div>中的并行查询和组,

QueryComponent

这就是我创建自定义角度元素的方式,

<!--Top level container for query view | everything related should go here: start-->
<div class="qd--query-container" [formGroup]="queryForm" *ngIf="queryForm">
    <div class="row" formArrayName="queries">
        <!--Repeat the dynamically added/removed queries: start-->
        <div class="col-md-12 qd--query-inputs-container" *ngFor="let query of currentQueries.controls; let queryIndex = index">
            <div class="row qd--query-inputs" [formGroupName]="queryIndex">
                <!--Actual query inputs: start-->
                <div class="col-md-10 qd--condition-holder">
                    <div class="row no-gutter">
                        <!--Left hand side input: start-->

                        <!--Left hand side input: end-->

                        <!--Operator: start-->

                        <!--Operator: end-->

                        <!--Right hand side input: start-->

                        <!--Right hand side input: end-->
                    </div>
                </div>
                <!--Actual query inputs: start-->

                <!--Group options: start-->

                <!--Group options: end-->

                <!--Group query: start-->
                <div *ngIf="query !== undefined" class="ai--query-groups">
                    <div *ngFor="let group of getGroups(query).controls; let groupIndex=index" class="ai--query-group">
                        <query-designer
                                [data]="data"
                                [operators]="operators"
                                [queryForm]="group"
                                (removeQueryGroup)="removeQueryGroupHandler($event)"
                                [queryIndex]="queryIndex"
                                [groupIndex]="groupIndex"></query-designer>
                    </div>
                </div>
                <!--Group query: end-->

            </div>
        </div>
        <!--Repeat the dynamically added/removed queries: end-->
    </div>
</div>
<!--Top level container for query view: start-->


<!--Repeat the dynamically added/removed queries: start-->
<div class="col-md-12 qd--query-inputs-container" *ngFor="let query of currentQueries.controls; let queryIndex = index">
    <div class="row qd--query-inputs" [formGroupName]="queryIndex">
        <!--Actual query inputs: start-->
        <div class="col-md-10 qd--condition-holder">
            <div class="row no-gutter">
                <!--Left hand side input: start-->

                <!--Left hand side input: end-->

                <!--Operator: start-->

                <!--Operator: end-->

                <!--Right hand side input: start-->

                <!--Right hand side input: end-->
            </div>
        </div>
        <!--Actual query inputs: start-->

        <!--Group options: start-->

        <!--Group options: end-->

        <!--Group query: start-->
        <div *ngIf="query !== undefined" class="ai--query-groups">
            <div *ngFor="let group of getGroups(query).controls; let groupIndex=index" class="ai--query-group">
                <query-designer
                        [data]="data"
                        [operators]="operators"
                        [queryForm]="group"
                        (removeQueryGroup)="removeQueryGroupHandler($event)"
                        [queryIndex]="queryIndex"
                        [groupIndex]="groupIndex"></query-designer>
            </div>
        </div>
        <!--Group query: end-->

    </div>
</div>
<!--Repeat the dynamically added/removed queries: end-->

在第一个渲染中,它工作正常,我能够添加@NgModule({ imports: [ CommonModule, BrowserModule, NgSelectModule, FormsModule, ReactiveFormsModule, CoreModule ], declarations: [ AppComponent, QueryComponent, QueryDesignerComponent ], entryComponents: [QueryDesignerComponent], providers: [] }) export class AppModule { constructor(private injector: Injector) { const strategyFactory = new ElementZoneStrategyFactory(QueryDesignerComponent, injector); const customElement = createCustomElement(QueryDesignerComponent, { injector, strategyFactory }); customElements.define('query-designer', customElement); } ngDoBootstrap() { } } 个并行行。但是,当我单击n时,Add group的构造函数被调用了两次!这使得QueryDesignerComponent的第一个实例接收QueryDesignerComponent,第二个实例接收正确的值。

我关注了why ngOnInit called twice?,相关的github issuengOnInit and Constructor are called twice,但是我没有运气!

有人知道我如何摆脱这个问题?任何帮助/指导将不胜感激!

3 个答案:

答案 0 :(得分:2)

我也有同样的问题,Angular Elements也有。

问题是我在Angular7组件内调用了Angular7组件,在app.module.ts上,我用与Angular7组件名称相同的名称自举了子组件。

父级调用my-child-component时,它同时调用了Angular7和自定义元素。

因此,解决方法是在这种情况下使用不同的名称。

答案 1 :(得分:0)

另一种可能是app.module.ts中的以下代码

platformBrowserDynamic().bootstrapModule(AppModule).catch(err => { console.error(err) });

答案 2 :(得分:0)

我尝试了这个,并为Angular元素工作。 从@NgModule中删除了Bootstrap,并在ngDoBootstrap中而不​​是构造函数中添加了自定义元素定义。

请找到以下代码以供参考。

 @NgModule({
  declarations: [
    MyComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  schemas: [
    CUSTOM_ELEMENTS_SCHEMA
  ],
  providers: [MyService]
})
export class AppModule implements DoBootstrap{ 
  constructor(private injector: Injector) {
  }
  ngDoBootstrap(appRef: ApplicationRef) {
    const el = createCustomElement(MyComponent, { injector: this.injector });
    customElements.define('my-widget', el);
  }
}