4

I want define MySubFormComponent for using many time in others component (like partial form elements) And I try do this but have problem with access to the "formControlGroup" object(subForm) in main component from child component.

I thing this is problem with transmit my parent "formControlGroup" object to child component using annotation @Input() this happend after create object of child component (in View Lavel?) and overwrite my define (subForm) ControlGroup in child component.

My question is how can I get access to the inputed "formControlGroup" object to mySubFormComponent in MainFormComponent (Maybe emmit this object in child component but for which event over the subForm, need to work validations) What I am doing wrong?

Simple Example:

MainComponent

@Component({
      selector: selector,
      templateUrl: tmplUrl,
      directives: [ FORM_DIRECTIVES ]
})
export class MainFormComponent {

    public mainForm: ControlGroup;
    public recipientForm: ControlGroup;
    public recipientData: RecipientModel; //testing variable for use ngModel

    constructor(private fb: FormBuilder, public cdr: ChangeDetectorRef ) {

        this.recipientData = new RecipientModel(); //testing instance variable
        this.recipientForm = new ControlGroup({});    
        this.mainForm = this.fb.group({
             'user_name': ['Test User', Validators.required],
        });
    }

    onSubmit(): void {
        console.log('Submitted value:', this.mainForm.value);
        console.log('Recipient data:', this.recipientForm.value);
      }
}

MainTemplate:

<form [ngFormModel]="mainForm" class="form-inline" (ngSubmit)="onSubmit()">
  <div class="form-group">
    <label>User name:</label> 
    <input type="text" class="form-control" 
        [ngFormControl]="mainForm.controls['user_name']"/>
  </div>
  <form-recipient [subFormData]="recipientData" 
        [subForm]="recipientForm"></form-recipient>
</form>

MainFormComponent

@Component({
  selector: selector,
  templateUrl: tmplUrl,
  directives: [ FORM_DIRECTIVES ]
})
export class FormRecipientComponent {

  @Input() public subForm: ControlGroup;
  @Input() public subFormData: RecipientModel;

  constructor(private fb: FormBuilder,public cdr: ChangeDetectorRef) {
      this.subForm = this.fb.group({
          'recipient_name': ['John Doe', Validators.required],
          'recipient_name_ex': ['', Validators.required],
          'recipient_address': ['Baker Street', Validators.required]
      });
  }


  ngAfterViewInit(){
      // this.cdr.detectChanges();
      console.log('RecipientSubForm', this.subForm.value);
  }

}

export class RecipientModel {
    public recipient_name: string;
    public recipient_name_ex: string;
    public recipient_address: string;
}

SubForm Template

<form [ngFormModel]="subForm" class="form-inline">
  <div>Validate: <span *ngIf="subForm.valid">OK</span></div>
  <div class="form-group">
      <label>Recipient name:</label>
      <input type="text" class="form-control"
            [ngFormControl]="subForm.controls['recipient_name']"
            />
  </div>
  <div class="form-group">
      <label>Recipient cd..</label>
      <input type="text" class="form-control"
            [ngFormControl]="subForm.controls['recipient_name_ex']"
            />
  </div>
  <div class="form-group">
      <label>Recipient address:</label>
      <input type="text" class="form-control"
            [ngFormControl]="subForm.controls['recipient_address']"
            />
  </div>
</form>

My submit result is:

Recipient form: Object {}
Power Web Design
  • 139
  • 1
  • 3
  • 14

1 Answers1

2

I would create a ngModel-compliant component for sub form components. This way you will be able to make them participate into the main form using controls.

Here is a sample:

<form [ngFormModel]="mainForm" class="form-inline"   
                         (ngSubmit)="onSubmit()">
  <div class="form-group">
    <label>Rachunek odbiorcy:</label> 
    <input md-input type="text" class="form-control" 
      [ngFormControl]="mainForm.controls['user_name']"/>
  </div>
  <form-recipient [subFormData]="recipientData" 
    [ngFormControl]="mainForm.controls['recipient']"></form-recipient>
</form>

You main form would be defined this way:

this.mainForm = this.fb.group({
  'user_name': ['Test User', Validators.required],
  'recipient': [{...}, validatorFct],
});

To make the sub component compliant, you need to make it implement a custom value accessor and link the sub form state with this accessor.

For more details you can have a look at these links:

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Thank's a lot, u are realy great. That's what I was looking for, I missed the properties that have a form element input **"value"**. I have to try this solution. @Thierry can u say how should look my "CustomeValueAccessor" in order to use it in many components? Bcs directives "TagsValueAccessor" works only with one component "TagsComponent" – Power Web Design Apr 27 '16 at 13:58