Условный рендеринг с * ngTemplateOutlet не работает внутри formGroup правильно - PullRequest
2 голосов
/ 14 января 2020

Я построил многократно используемый ввод формы, который должен отображаться внутри формы либо с родительским formGroupName, либо как обычный элемент управления вводом.

Мой код выглядит следующим образом:

child.component. html:

 <ng-container *ngIf="hasFormGroup; then formFieldWithGroupName else formField">
 </ng-container>

<ng-template #formFieldWithGroupName>
   <span>control With Group Name</span>
   <div formGroupName="_general">
     <ng-container *ngTemplateOutlet="formField"></ng-container>

     <!-- MY ISSUE HERE: directly add the template below works but not best practice -->
     <!-- <input matInput placeholder="Project name" 
                          [formControlName]="controlName">  -->
   </div>
</ng-template>

<ng-template #formField>
   <span>control Without Group Name</span><br>
   <input matInput placeholder="Project name" 
                   [formControlName]="controlName"> 
</ng-template>

child.component.ts :

import { Component, OnInit, Input } from '@angular/core';
import { FormControl, FormGroup, ControlContainer, FormGroupDirective, Validators, FormBuilder, NgModel } from '@angular/forms';
@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css'],
  viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }]
})
export class ChildComponent implements OnInit {

  childForm;
  @Input() hasFormGroup: boolean = false;
  @Input() controlName: string;
  constructor(private parentF: FormGroupDirective) { }

  ngOnInit() {
    this.childForm = this.parentF.form;

    if(this.hasFormGroup) {
      this.childForm.controls._general.addControl(this.controlName, new FormControl());
    } else {
      this.childForm.addControl(this.controlName, new FormControl())
    }
  }

}

И содержимое родительского компонента app.component. html

<form [formGroup]="parentForm">
  <app-child [controlName]="'projectName'" [hasFormGroup]="false"></app-child>
  <app-child [controlName]="'projectName'" [hasFormGroup]="true"></app-child>
  <br>
  <hr>
  <app-child-2></app-child-2>

  Form Value: {{parentForm.value | json}}
</form>

Элемент управления внутри группы не работает должным образом. Но если я использую шаблон напрямую (без рендеринга с помощью ngTemplateOutlet), он принимает оба значения правильно.

Может кто-нибудь помочь мне выяснить, почему он не работает?

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

Здесь демонстрация Stackblitz:

https://stackblitz.com/edit/angular-form-magic-4k6m9h

1 Ответ

0 голосов
/ 14 января 2020

Элемент управления input не может получить своего родителя, потому что он внедрен без контекста. Поместите ссылку внутри шаблона, чтобы директива могла видеть его, когда ищет:

<ng-template #formField>
  <div formGroupName="_general">
    <span>control Without Group Name</span><br>
    <input matInput placeholder="Project name" 
                    [formControlName]="controlName"> 
  </div>
</ng-template>

Ho вправо, правка :

Замените весь ваш код только на input и используйте null, чтобы отменить formGroupName, когда он не актуален (удалить все шаблоны и прочее):

<div [formGroupName]="hasFormGroup ? '_general' : null">
  <input matInput placeholder="Project name" 
                  [formControlName]="controlName">
</div>
...