1

There are multiple sibling component with different NgForm (template-driven forms) inside each of them. All of them are wrapped with a parent component. Parent component has validation button. I need to validate certain child NgForm within click event on the button on a parent component.

What approaches to solve this would you propose?

// Parent template
<child id="0"></child>
<child id="1"></child>

// Parent component
validateChild(id: number) {
  // need somehow reach child component NgForm with a particular id
}

// Child Component template
<form #myForm="ngForm">...</form>

// Child Component template
@ViewChild('myForm') 
public myForm: NgForm;

When I am saying validation - I mean referring to following:

Object.keys(form.controls).forEach(key => {
   form.controls[key].markAsTouched();
})

I was thingking about following approach:

// Parent component
stages = [
  {
    validated: false
  },
  {
    validated: false
  },
]
// Parent component view
<child id="0" [validate]="stages[0].validated"></child>
<child id="1" [validate]="stages[1].validated"></child>

// Child component
@Input()
public set validate(value: boolean) {
  if (value === true)
  Object.keys(this.myForm.controls).forEach(key => {
     this.myForm.controls[key].markAsTouched();
  })
}

But I don't really like it..Probably there is a better approach. Because with this one without extra child EventEmitter I can't check whether form is valid or not

Timothy
  • 3,213
  • 2
  • 21
  • 34

2 Answers2

1

If you want to have multiple forms for grouping, but not separate submit, then you could use FormGroup to track a related set of controls.

So you can validate child components like that:

@Component({
  selector: 'my-app',
  template: `
    <form [formGroup]="reactiveFormGroup">
      <input formControlName="foobar" />
      <my-component **[group]="reactiveFormGroup"**></my-comp>
    </form>

    form value: {{ reactiveFormGroup.value | json }}
  `
})
export class AppComponent { 
  reactiveFormGroup = new FormGroup({
    foo: new FormControl('default foobar'),
    bar: new FormControl('default foobar2')
  });
}

Child component code, e.g. my-component

@Component({
  selector: 'my-component',
  template: `
    <div [formGroup]="group">
      <input   [formControlName]="'foobar2'" />
    </div>
  `
})
export class MyComponent { 
  @Input() group: FormGroup;
}
StepUp
  • 36,391
  • 15
  • 88
  • 148
  • 1
    Your answer lead me to https://angular.io/api/forms/NgModelGroup.... Thats actually not a bad idea... Let me check it out – Timothy Jul 17 '19 at 11:50
0

I have faced similar kind of issue, then I am following below approach

Parent Component

  @ViewChild(FirstChidComponent)
  public fChild: FirstChidComponent;

  validateChild(id: number) {
    console.log(this.fChild.myForm);
  }

you can access form values of the childComponent like this.fChild.myForm.

you can also do the validation for the child Form

 form.controls[controlName].markAsTouched();
Ganesh
  • 5,808
  • 2
  • 21
  • 41
  • What I don't like about this approach is that you have to define particular component.. but lets assume there are 20 different components and having @ViewChild(FirstChidComponent for each of them is not a great solution. Read my amendment in the post to check my current setup – Timothy Jul 17 '19 at 11:37
  • I am following this approach for one or two child components, hope I will back with better solution... :) – Ganesh Jul 17 '19 at 11:43