Angular元素两次调用组件构造函数 [英] Component constructor is getting called twice with Angular elements

查看:93
本文介绍了Angular元素两次调用组件构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理一个递归查询生成器表单,该表单类似于中的 >角7,具有反应形式。意味着,用户可以通过单击添加规则来继续添加并行规则,也可以通过单击添加组。
我创建了两个组件, QueryDesignerComponent QueryComponent QueryDesignerComponent 保存外部容器,条件为 AND OR QueryComponent 保存行输入,即 LHS operator RHS


  1. 当用户单击添加规则时,我只是通过再推一个来扩展规则 QueryDesignerComponent 中包含 QueryComponent 的条目。我用 * ngFor 重复此操作。

  2. 当用户单击添加组我在 QueryComponent 内调用 QueryDesignerComponent ,这使其递归。我用 * 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 内的并行查询和组,



 <!-查询视图的顶级容器|所有相关的内容都应在此处:start->< div class = qd--query-container [formGroup] = queryForm * ngIf = queryForm> < div class = row formArrayName = queries> < ;!-重复动态添加/删除的查询:start-> < div class = col-md-12 qd--query-inputs-container * ngFor =让对currentQueries.controls的查询;让queryIndex = index> < div class = row qd--query-inputs [formGroupName] = queryIndex> <!-实际查询输入:start-> < div class = col-md-10 qd--condition-holder> < div class = row no-gutter> <!-左手侧输入:开始-> <!-左手侧输入:结束-> <!-操作员:开始-> <!-运算符:end-> <!-右侧输入:开始-> <!-右侧输入:结束-> < / div> < / div> <!-实际查询输入:start-> <!-组选项:开始-> <!-组选项:end-> <!-组查询:开始-> < div * ngIf = query!==未定义 class = ai--query-groups> < div * ngFor =让getGroups(query).controls的组;让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> <!-组查询:end-> < / div> < / div> < ;!-重复动态添加/删除的查询:end-> < / div>< / div>< ;!-查询视图的顶层容器:start-< !!-重复动态添加/删除的查询:start->< div class =  col-md-12 qd--query-inputs-container * ngFor =让查询currentQueries.controls;让queryIndex = index> < div class = row qd--query-inputs [formGroupName] = queryIndex> <!-实际查询输入:start-> < div class = col-md-10 qd--condition-holder> < div class = row no-gutter> <!-左手侧输入:开始-> <!-左手侧输入:结束-> <!-操作员:开始-> <!-运算符:end-> <!-右侧输入:开始-> <!-右侧输入:结束-> < / div> < / div> <!-实际查询输入:start-> <!-组选项:开始-> <!-组选项:end-> <!-组查询:开始-> < div * ngIf = query!==未定义 class = ai--query-groups> < div * ngFor =让getGroups(query).controls的组;让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> <!-组查询:end-> < / div>< / div>< ;!-重复动态添加/删除的查询:end->  



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

  @NgModule({
进口:[
CommonModule,
BrowserModule,
NgSelectModule,
FormsModule,
ReactiveFormsModule,
CoreModule
],
声明:[
AppComponent,
QueryComponent,
QueryDesignerComponent
],
entryComponents:[QueryDesignerComponent],
提供者:[]
})
导出类AppModule {
构造函数(私有注入器:Injector){
const strategyFactory = new ElementZoneStrategyFactory(QueryDesignerComponent,jector);
const customElement = createCustomElement(QueryDesignerComponent,{jector,strategyFactory));
customElements.define('query-designer',customElement);
}

ngDoBootstrap(){}
}

在第一个渲染中,它工作正常,我能够添加 n 个并行行。但是,当我单击添加组时, QueryDesignerComponent 的构造函数被调用了两次!这使得 QueryDesignerComponent 的第一个实例接收 undefined ,第二个实例接收正确的值。



我关注了为什么ngOnInit被调用了两次?,与 github问题,但是我发现没有运气!



有人知道怎么做吗?我可以摆脱这个问题吗?任何帮助/指导都将不胜感激!

解决方案

我对Angular Elements也遇到了同样的问题。



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

当父级调用my-child-component时,它同时调用了Angular7和Custom Element。



,解决方法是在这种情况下使用其他名称。


I am working on a recursive query builder form, which is something similar to this, in angular 7, with reactive form. Means, the user can keep adding a parallel rule by clicking on Add rule and can add a group by clicking on Add group. I have created two components, QueryDesignerComponent and QueryComponent. QueryDesignerComponent holds the outer container, with AND and OR condition and QueryComponent holds the row input, that's LHS, operator and RHS.

  1. When user clicks Add rule I am growing the rule just by pushing one more entry with QueryComponent inside QueryDesignerComponent. I am repeating this with *ngFor.
  2. When the user clicks Add group I am callings the QueryDesignerComponent inside QueryComponent, which makes it recursive. I am repeating this with *ngFor.

I am done with the implementation and its working fine within angular app, which has an angular environment.

Now, I am trying to port this flow in angular elements, to make it reusable, regardless of the environment.

this is how I am placing first row [ QueryComponent ] inside 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>

and this way I am managing the parallel query and groups inside 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-->

This is how I am creating a custom angular element,

@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() { }
}

In the first render, it's working fine and I am able to add n number of parallel rows. But, when I click the Add group, QueryDesignerComponent's constructor is getting called twice! This makes the first instance of QueryDesignerComponent to receive undefined and second instance to receive correct values.

I followed why ngOnInit called twice?, related github issue and ngOnInit and Constructor are called twice but, I found no luck!!

Does anyone know how can I get rid of this issue? Any help/guidance would be much appreciated!

解决方案

I just had the same issue, with Angular Elements too.

Problem was that I was calling an Angular7 component inside an Angular7 component, and on app.module.ts I had bootstrapped the child component with the same name as the Angular7 component name.

When parent called my-child-component it was calling both the Angular7 one and the Custom Element one.

So, the fix is to use different names in this case.

这篇关于Angular元素两次调用组件构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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