Доступ к форме родителя в дочернем

#angular #validation

Вопрос:

У меня есть такая структура, как эта:

 <form #myForm="ngForm">
  <div class=row>
    <app-section-a [myForm]="myForm"></app-section-a>
 

и мой детский компонент:

 @Component({
...
  viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ]
})
// ...
@Input() myForm: ElementRef;
 
 <input ...>
<button type=submit [disabled]="!myForm.valid">
 

и это прекрасно работает для обеспечения того, чтобы все компоненты в форме были учтены на предмет действительности. Дело в том, что я не думаю, что мне нужно передавать ссылку на ngForm непосредственно в качестве входных данных. Как мне пропустить этот ввод и все равно заставить это работать?

деталь: оказывается, это проект angular 5.

Комментарии:

1. если вы пытаетесь создать подформу, я бы рекомендовал проверить github.com/cloudnc/ngx-sub-form и эта статья dev.to/maxime1992/…

2. Я имею в виду, что это уже сделано. Мне просто нужна эта оптимизация

3. передача формы в качестве входных данных, на мой взгляд, прекрасна. Но вы не должны использовать ElementRef —> передать FormGroup

4. @Riscie, мне нужны только свойства элемента, такие как действительность .. если я создам группу форм, разве мне не придется применять это во всех дочерних компонентах? Я определенно не хочу всего этого делать. Причина, по которой я вообще не хочу передавать ссылку, заключается в том, что она добавляет ненужную сложность всем дочерним компонентам. Я хочу, чтобы в дизайне было меньше технических долгов.

5. Я согласен с @Riscie, предпочтительнее передать группу форм. Или, если вам нужна только действительность, почему бы вам просто не передать valid значение, а не всю группу форм

Ответ №1:

Полный рабочий пример приведен по этой ссылке на StackBlitz.

Прежде всего, вам вообще не нужно переходить ngForm к дочернему компоненту. Потому что вы можете определить, что дочерний компонент является частью родительской группы форм, используя ControlContainer NgForm массив поставщиков дочерних компонентов и предоставляя его.

В этом примере один родительский компонент app.component загружает дочерний компонент, *ngFor и мы только что добавили ControlContainer в массив поставщиков дочерний компонент. Здесь нам просто нужно динамически присваивать разные имена каждому дочернему компоненту, для этого нам нужно передать индекс как @Input() дочернему компоненту и присвоить его name свойству InputField.

Если какой-либо из inputControl имеет ошибку, то submit кнопка родительского контроля отключена.

app.component.html есть…

 <form #heroForm="ngForm" class="container">
   <div id="parent" *ngFor="let i of [0,1,2]"  >
      <app-child [id]="i 1" [name]="i 1" ></app-child>
   </div>
  <hr>
    {{heroForm.value | json}}
  <hr>
  <div>
     <app-button-submit></app-button-submit>
  </div>
</form>
 

app-button-submit.html

 <button type="submit" class="btn btn-success"
  [disabled]="!control.form.valid">Submit</button>
 

Мы привязываемся ControlContainer непосредственно к [disabled] состоянию кнопки с помощью инъекции зависимостей.. смотрите constructor() файл класса ниже.

приложение-кнопка-отправить.ts

 import {ControlContainer, NgForm} from '@angular/forms';

@Component({
   selector: 'app-button-submit',
   templateUrl: './button-submit.component.html',
   styleUrls: ['./button-submit.component.css'],
   providers : [{provide : ControlContainer, useExisting : NgForm}]
})
export class ButtonSubmitComponent  {
   constructor(private control : NgForm) { }
}
 

child-component.html

 <div class="form-group" >
   <label [for]="Name">Name</label>    
      <input type="text"  class="form-control"  [id]="id" required [(ngModel)]="vname" [name]="Name"  #names="ngModel">
        {{vname}}
   <div [hidden]="names.valid || names.pristine" class="alert alert-danger"> 
      Name is required  
   </div>
</div>
 

дочерний компонент.ts

 import {ControlContainer, NgForm} from '@angular/forms';

@Component({
   ---,
   viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ]
})
 export class ChildComponent implements OnInit {
   @Input('id') id;
   @Input ('name') Name;
 }
 

здесь ControlContainer мы позаботимся о привязке NgForm Родительского компонента к Дочернему компоненту.

Комментарии:

1. Спасибо. Мне нравится твое мышление… но для этих целей кнопка отправки должна находиться в дочернем компоненте, а не в родительском

2. Хорошо. stackblitz.com/edit/… Ознакомьтесь с этой обновленной ссылкой

3. constructor(private control : NgForm) { } эта одна строка-все, что мне было нужно (хотя, вероятно, она должна быть публичной). Но я действительно ценю, насколько основателен ваш ответ, отличный ответ!

4. Рад!! Ответ полезен для вас.