Конструктор компонента вызывается дважды с элементами Angular

Я работаю над формой построителя рекурсивных запросов, которая чем-то похожа на это, в angular 7 , с реактивной формой. Это означает, что пользователь может продолжать добавлять параллельное правило, нажимая Add rule, и может добавлять группу, нажимая Add group. Я создал два компонента, QueryDesignerComponent и QueryComponent. QueryDesignerComponent содержит внешний контейнер с условиями AND и OR, а QueryComponent содержит ввод строки, то есть LHS, operator и RHS.

  1. Когда пользователь нажимает Add rule, я расширяю правило, просто добавляя еще одну запись с QueryComponent внутри QueryDesignerComponent. Я повторяю это с *ngFor.
  2. Когда пользователь нажимает Add group, я вызываю QueryDesignerComponent внутри QueryComponent, что делает его рекурсивным. Я повторяю это с *ngFor.

Я закончил с реализацией, и она отлично работает в угловом приложении, которое имеет угловую среду.

Теперь я пытаюсь перенести этот поток в элементы angular, чтобы его можно было использовать повторно, независимо от среды. .

вот как я помещаю первую строку [ 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 получать undefined, а второй экземпляр получать правильные значения.

Я следил за почему ngOnInit вызывается дважды?, связанный с проблема с github и ngOnInit и Constructor вызываются дважды, но мне не повезло!!

Кто-нибудь знает, как я могу избавиться от этой проблемы? Любая помощь/рекомендации будут высоко оценены!


person Ravindra Thorat    schedule 11.02.2019    source источник
comment
Предоставьте больше кода, чтобы воспроизвести эту проблему.   -  person web.dev    schedule 11.02.2019
comment
Вы пытались загрузить этот модуль с отложенной загрузкой? angular.io/guide/lazy-loading-ngmodules github.com/angular/angular/issues/12869   -  person Joel Garcia Nuño    schedule 11.02.2019
comment
@web.dev, добавил больше кода. пожалуйста, взгляните   -  person Ravindra Thorat    schedule 11.02.2019
comment
@JoelGarciaNuño, позволь мне проверить. это очень быстрый вопрос, прежде чем переходить по фактической ссылке, но помогает ли это в угловых элементах?   -  person Ravindra Thorat    schedule 11.02.2019
comment
Это помогает загрузить компонент один раз, может не вызывать снова конструктор. Для использования отложенной загрузки используйте # на пути вашего маршрутизатора angular.io/guide/lazy-loading-ngmodules#routes-at-the-app-level но сделайте перерыв, может простая проблема, когда вы нажимаете кнопку более двух раз, сколько раз называется конструктор?   -  person Joel Garcia Nuño    schedule 11.02.2019
comment
@JoelGarciaNuño, 1. Я не использую маршрутизатор, ему просто нужно отобразить представление и вывести вывод во внешнее представление HTML 2. каждый раз, когда я нажимаю кнопку Add group, конструктор вызывается дважды, и поскольку он не получает правильные значения, групповой вид не отображается   -  person Ravindra Thorat    schedule 11.02.2019


Ответы (3)


У меня была такая же проблема и с Angular Elements.

Проблема заключалась в том, что я вызывал компонент Angular7 внутри компонента Angular7, а в app.module.ts я загрузил дочерний компонент с тем же именем, что и имя компонента Angular7.

Когда родитель вызывал my-child-component, он вызывал как Angular7, так и пользовательский элемент.

Таким образом, исправление состоит в том, чтобы использовать разные имена в этом случае.

person Matheus Fantinel    schedule 01.03.2019

Другой возможностью может быть следующий фрагмент кода в app.module.ts.

platformBrowserDynamic().bootstrapModule(AppModule).catch(err => { console.error(err) });
person Giggs    schedule 15.04.2019
comment
Не могли бы вы объяснить, как это вызывает проблему. - person Ms.Tamil; 25.02.2020
comment
Это действительно сработало для меня! Я видел, как мои компоненты загружались дважды при первой загрузке страницы. Удаление этой строки устранило проблему, хотя я до сих пор не знаю, почему. - person stefa.rossi; 12.05.2020

Я попробовал это и работал с элементами Angular. Удален Bootstrap из @NgModule и добавлено определение пользовательского элемента в 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);
  }
}
person Vinod Krishnan    schedule 16.09.2020