Javascript 如何使用当前表单API将父组件的FormGroup传递给其子组件

Javascript 如何使用当前表单API将父组件的FormGroup传递给其子组件,javascript,angular,angular2-forms,typescript1.8,Javascript,Angular,Angular2 Forms,Typescript1.8,我想将父组件的FormGroup传递给它的子组件,以便使用子组件显示错误消息 鉴于以下家长: parent.component.ts export class BasicInfoComponent implements OnInit { @Input() breakpoint; @Input() formGroup: FormGroup; basicInfo: FormGroup; constructor() { } ngOnInit(): void { this.

我想将父组件的
FormGroup
传递给它的子组件,以便使用子组件显示错误消息

鉴于以下家长:

parent.component.ts

export class BasicInfoComponent implements OnInit {
  @Input() breakpoint;
  @Input() formGroup: FormGroup;
  basicInfo: FormGroup;
  constructor() { }

  ngOnInit(): void {
    this.basicInfo = new FormGroup({
      full_name: new FormControl('Riki maru'),
      dob: new FormControl(''),
    });
    this.formGroup.addControl('basicInfo', this.basicInfo);
  }
}
从'@angular/core'导入{Component,OnInit}
进口{
反应式表单指令、AbstractControl、FormBuilder、FormControl、FormGroup、验证器
}来自“@angular/forms”
@组成部分({
moduleId:module.id,
选择器:“父cmp”,
templateUrl:'language.component.html',
样式URL:['language.component.css'],
指令:[错误消息组件]
})
导出类ParentCmp实现OnInit{
表格:表格组;
第一:抽象控制;
二是抽象控制;
构造函数(私有_fb:FormBuilder){
this.first=新表单控件(“”);
this.second=新表单控件(“”)
}
恩戈尼尼特(){
this.form=this.\u fb.group({
“第一”:这个。第一,
“秒”:这是秒
});
}
}
现在,我想将上面的form:FormGroup变量传递给下面的子组件:

错误消息.component.ts

export class BasicInfoComponent implements OnInit {
  @Input() breakpoint;
  @Input() formGroup: FormGroup;
  basicInfo: FormGroup;
  constructor() { }

  ngOnInit(): void {
    this.basicInfo = new FormGroup({
      full_name: new FormControl('Riki maru'),
      dob: new FormControl(''),
    });
    this.formGroup.addControl('basicInfo', this.basicInfo);
  }
}
从'@angular/core'导入{Component,OnInit,Input}
从“@angular/common”导入{NgIf}
从'@angular/forms'导入{REACTIVE_FORM_指令,FormGroup}
@组成部分({
moduleId:module.id,
选择器:“epimss错误消息”,
模板:`{{errorMessage}}}`,
样式:[],
指令:[反应形式指令,NgIf]
})
导出类ErrorMessagesComponent实现OnInit{
@Input()ctrlName:string
构造函数(私有_形式:FormGroup){}
ngOnInit(){}
获取错误消息(){
//在主机(父)窗体中查找控件
让ctrl=this.\u form.find(this.ctrlName);
console.log('ctrl |',ctrl);
//for(让propertyName为ctrl.errors){
////如果控件有错误
//if(ctrl.errors.hasOwnProperty(propertyName)&&ctrl.touched){
////从验证服务返回相应的错误消息
//返回CustomValidators.getValidatorErrorMessage(propertyName);
//      }
//    }
返回null;
}
构造函数formGroup表示父级的formGroup-以其当前形式,它不起作用


我试图在

中遵循这个过时的示例,我将表单作为输入传递给子组件

@Component(
    {
      moduleId: module.id,
      selector: 'epimss-error-messages',
      template: `
   <span class="error" *ngIf="errorMessage !== null">{{errorMessage}}</span>`,
      styles: [],
      directives: [REACTIVE_FORM_DIRECTIVES, NgIf]

    })
export class ErrorMessagesComponent implements OnInit {
  @Input()
  ctrlName: string

  @Input('form') _form;

  ngOnInit() {
         this.errorMessage();
      }

  errorMessage() {
    // Find the control in the Host (Parent) form
    let ctrl = this._form.find(this.ctrlName);

    console.log('ctrl| ', ctrl)

//    for (let propertyName of ctrl.errors) {
//      // If control has a error
//      if (ctrl.errors.hasOwnProperty(propertyName) && ctrl.touched) {
//        // Return the appropriate error message from the Validation Service
//        return CustomValidators.getValidatorErrorMessage(propertyName);
//      }
//    }

    return null;
  }
@组件(
{
moduleId:module.id,
选择器:“epimss错误消息”,
模板:`
{{errorMessage}}`,
样式:[],
指令:[反应形式指令,NgIf]
})
导出类ErrorMessagesComponent实现OnInit{
@输入()
ctrlName:字符串
@输入(“形式”)\u形式;
恩戈尼尼特(){
这个.errorMessage();
}
errorMessage(){
//在主机(父)窗体中查找控件
让ctrl=this.\u form.find(this.ctrlName);
console.log('ctrl |',ctrl)
//for(让propertyName为ctrl.errors){
////如果控件有错误
//if(ctrl.errors.hasOwnProperty(propertyName)&&ctrl.touched){
////从验证服务返回相应的错误消息
//返回CustomValidators.getValidatorErrorMessage(propertyName);
//      }
//    }
返回null;
}
当然,您需要将表单从父组件传递给子组件,您可以用不同的方式来完成,但最简单的是:

在你父母的某个地方

     <epimss-error-messages [form]='form'></epimss-error-messages>

在父组件中执行以下操作:

<div [formGroup]="form">
  <div>Your parent controls here</div>
  <your-child-component [formGroup]="form"></your-child-component>
</div>
这个答案应该足以满足您的需要,但如果您想了解更多,我在这里写了一篇博客:


这是在父formGroup中使用的子组件的一个示例: 子组件ts:

import { Component, OnInit, Input } from '@angular/core';
import { FormGroup, ControlContainer, FormControl } from '@angular/forms';


@Component({
  selector: 'app-date-picker',
  template: `
  <mat-form-field [formGroup]="form" style="width:100%;">
  <input matInput [matDatepicker]="picker" [placeholder]="placeHolder" [formControl]="control" readonly>
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>
<mat-icon (click)="clearDate()">replay</mat-icon>`,
  styleUrls: ['./date-picker.component.scss']
})

export class DatePickerComponent implements OnInit {
  public form: FormGroup;
  public control : FormControl;
  @Input() controlName : string;
  @Input() placeHolder : string;


  constructor(private controlContainer: ControlContainer) { 
  }

  clearDate(){
    this.control.reset();
  }

  ngOnInit() {
    this.form = <FormGroup>this.controlContainer.control;
    this.control = <FormControl>this.form.get(this.controlName);
    }

}

使用方法如下:

 <app-date-picker class="col-md-4" [formGroup]="feuilleForm" controlName="dateCreation" placeHolder="Date de création"></app-date-picker>

如果要从子组件访问父组件,可以访问FormControl实例的父属性

要获取父错误,请执行以下操作:

const parent = control.parent;
const errors = parent.errors;

父组件:

    @Component({
      selector: 'app-arent',
      templateUrl: `<form [formGroup]="parentFormGroup" #formDir="ngForm">
                       <app-child [formGroup]="parentFormGroup"></app-child>
                    </form>         `
    })
    
    export class ParentComponent implements {
        
     parentFormGroup :formGroup
    
     ngOnChanges() {        
       console.log(this.parentFromGroup.value['name'])
     }
  }
    @Component({
      selector: 'app-Child',
      templateUrl: `<form [formGroup]="childFormGroup" #formDir="ngForm">
                        <input id="nameTxt" formControlName="name">
                    </form>         `
    })
    
    export class ChildComponent implements OnInit {
     @Input()  formGroup: formGroup
    
     childFormGroup :formGroup
    
    ngOnInit() {
      // Build your child from
      this.childFormGroup.addControl('name', new FromControl(''))
    
      /* Bind your child form control to parent form group
         changes in 'nameTxt' directly reflect to your parent 
         component formGroup
        */
      let ctrls = this.childFromGroup.controls;
      this.formGroup.controls = ctrls;
   
     }
  }
<form [formGroup]="registerStudentForm" (ngSubmit)="onSubmit()">
<app-basic-info [breakpoint]="breakpoint" [formGroup]="registerStudentForm"></app-basic-info>
<button mat-button>Submit</button>
</form>
<mat-card [formGroup]="basicInfo">
    <mat-card-title>Basic Information</mat-card-title>
    <mat-card-content>
      <mat-grid-list
        [gutterSize]="'20px'"
        [cols]="breakpoint"
        rowHeight="60px"
      >
        <mat-grid-tile>
          <mat-form-field appearance="legacy" class="full-width-field">
            <mat-label>Full name</mat-label>
            <input matInput formControlName="full_name" />
          </mat-form-field>
        </mat-grid-tile>
    </mat-grid-list>
</mat-card-content>
</mat-card>
export class RegisterComponent implements OnInit {
    constructor() { }

    registerForm = new FormGroup({});
  
    onSubmit() {
      console.warn(this.registerForm.value);
    }
  
  }
@组件({
选择器:'app arent',
模板URL:`
`
})
导出类ParentComponent实现{
父窗体组:窗体组
ngOnChanges(){
console.log(this.parentFromGroup.value['name'])
}
}
子组件:

    @Component({
      selector: 'app-arent',
      templateUrl: `<form [formGroup]="parentFormGroup" #formDir="ngForm">
                       <app-child [formGroup]="parentFormGroup"></app-child>
                    </form>         `
    })
    
    export class ParentComponent implements {
        
     parentFormGroup :formGroup
    
     ngOnChanges() {        
       console.log(this.parentFromGroup.value['name'])
     }
  }
    @Component({
      selector: 'app-Child',
      templateUrl: `<form [formGroup]="childFormGroup" #formDir="ngForm">
                        <input id="nameTxt" formControlName="name">
                    </form>         `
    })
    
    export class ChildComponent implements OnInit {
     @Input()  formGroup: formGroup
    
     childFormGroup :formGroup
    
    ngOnInit() {
      // Build your child from
      this.childFormGroup.addControl('name', new FromControl(''))
    
      /* Bind your child form control to parent form group
         changes in 'nameTxt' directly reflect to your parent 
         component formGroup
        */
      let ctrls = this.childFromGroup.controls;
      this.formGroup.controls = ctrls;
   
     }
  }
<form [formGroup]="registerStudentForm" (ngSubmit)="onSubmit()">
<app-basic-info [breakpoint]="breakpoint" [formGroup]="registerStudentForm"></app-basic-info>
<button mat-button>Submit</button>
</form>
<mat-card [formGroup]="basicInfo">
    <mat-card-title>Basic Information</mat-card-title>
    <mat-card-content>
      <mat-grid-list
        [gutterSize]="'20px'"
        [cols]="breakpoint"
        rowHeight="60px"
      >
        <mat-grid-tile>
          <mat-form-field appearance="legacy" class="full-width-field">
            <mat-label>Full name</mat-label>
            <input matInput formControlName="full_name" />
          </mat-form-field>
        </mat-grid-tile>
    </mat-grid-list>
</mat-card-content>
</mat-card>
export class RegisterComponent implements OnInit {
    constructor() { }

    registerForm = new FormGroup({});
  
    onSubmit() {
      console.warn(this.registerForm.value);
    }
  
  }
@组件({
选择器:“应用程序子项”,
模板URL:`
`
})
导出类ChildComponent实现OnInit{
@Input()formGroup:formGroup
childFormGroup:formGroup
恩戈尼尼特(){
//让你的孩子从
this.childFormGroup.addControl('name',new FromControl('')
/*将子窗体控件绑定到父窗体组
“nameTxt”中的更改直接反映到您的家长
组件窗体组
*/
让ctrls=this.childFromGroup.controls;
this.formGroup.controls=ctrls;
}
}

ngOnInit很重要-这在构造函数中不起作用。 我更喜欢查找
FormControlDirective
——它是在子组件的祖先层次结构中找到的第一个

constructor(private formGroupDirective: FormGroupDirective) {}

  ngOnInit() {
    this.formGroupDirective.control.addControl('password', this.newPasswordControl);
    this.formGroupDirective.control.addControl('confirmPassword', this.confirmPasswordControl);
    this.formGroup = this.formGroupDirective.control;
  }

我会这样做,我已经将子表单数据作为组传递给父表单,这样您就可以在提交调用中分离表单数据

家长:

    @Component({
      selector: 'app-arent',
      templateUrl: `<form [formGroup]="parentFormGroup" #formDir="ngForm">
                       <app-child [formGroup]="parentFormGroup"></app-child>
                    </form>         `
    })
    
    export class ParentComponent implements {
        
     parentFormGroup :formGroup
    
     ngOnChanges() {        
       console.log(this.parentFromGroup.value['name'])
     }
  }
    @Component({
      selector: 'app-Child',
      templateUrl: `<form [formGroup]="childFormGroup" #formDir="ngForm">
                        <input id="nameTxt" formControlName="name">
                    </form>         `
    })
    
    export class ChildComponent implements OnInit {
     @Input()  formGroup: formGroup
    
     childFormGroup :formGroup
    
    ngOnInit() {
      // Build your child from
      this.childFormGroup.addControl('name', new FromControl(''))
    
      /* Bind your child form control to parent form group
         changes in 'nameTxt' directly reflect to your parent 
         component formGroup
        */
      let ctrls = this.childFromGroup.controls;
      this.formGroup.controls = ctrls;
   
     }
  }
<form [formGroup]="registerStudentForm" (ngSubmit)="onSubmit()">
<app-basic-info [breakpoint]="breakpoint" [formGroup]="registerStudentForm"></app-basic-info>
<button mat-button>Submit</button>
</form>
<mat-card [formGroup]="basicInfo">
    <mat-card-title>Basic Information</mat-card-title>
    <mat-card-content>
      <mat-grid-list
        [gutterSize]="'20px'"
        [cols]="breakpoint"
        rowHeight="60px"
      >
        <mat-grid-tile>
          <mat-form-field appearance="legacy" class="full-width-field">
            <mat-label>Full name</mat-label>
            <input matInput formControlName="full_name" />
          </mat-form-field>
        </mat-grid-tile>
    </mat-grid-list>
</mat-card-content>
</mat-card>
export class RegisterComponent implements OnInit {
    constructor() { }

    registerForm = new FormGroup({});
  
    onSubmit() {
      console.warn(this.registerForm.value);
    }
  
  }
Child.ts

export class BasicInfoComponent implements OnInit {
  @Input() breakpoint;
  @Input() formGroup: FormGroup;
  basicInfo: FormGroup;
  constructor() { }

  ngOnInit(): void {
    this.basicInfo = new FormGroup({
      full_name: new FormControl('Riki maru'),
      dob: new FormControl(''),
    });
    this.formGroup.addControl('basicInfo', this.basicInfo);
  }
}

在您的子窗体组件中,
@Input()formGroup:formGroup;
部分将是Angular 11的父组件的引用,我尝试了上述所有答案,并以不同的组合进行了尝试,但没有什么对我有效。因此,我最终得到了以下解决方案,该解决方案符合我的要求

打字稿

@Component({
  selector: 'fancy-input',
  templateUrl: './fancy-input.component.html',
  styleUrls: ['./fancy-input.component.scss']
})
export class FancyInputComponent implements OnInit {

  valueFormGroup?: FormGroup;
  valueFormControl?: FormControl;

  constructor(
    private formGroupDirective: FormGroupDirective, 
    private formControlNameDirective: FormControlName
  ) {}

  ngOnInit() {
    this.valueFormGroup = this.formGroupDirective.form;
    this.valueFormControl = this.formGroupDirective.getControl(this.formControlNameDirective);
  }

  get controlName() {
    return this.formControlNameDirective.name;
  }

  get enabled() {
    return this.valueFormControl?.enabled
  }

}

HTML


我认为应该从构造函数参数列表中删除
private\u form:FormGroup)