1
votes

I am having a reactive form which looks something like this .

@Component({
  selector: 'app-add-problem',
  templateUrl: './add-problem.component.html',
  styleUrls: ['./add-problem.component.css']
})
export class AddProblemComponent implements OnInit {

  public addProblemForm:FormGroup;
  @Input() baseImageUrl;
  @Input() topicId;
  @Input() topicName="Must Select a topic to proceed";

  constructor(private _fb:FormBuilder) { }

  ngOnInit() {
    this.addProblemForm=this._fb.group({
      Name:['',[Validators.required,Validators.minLength(5)]],
      TopicId:[5,[Validators.required]],
      Order:['',Validators.required],
      Description:[''],
      QuestionTag:[''],
      Type:['',Validators.required],
      BaseImageUrl:[this.baseImageUrl,Validators.required],
      ProblemJson: this._fb.group({
        QuestionText:this._fb.array([]),
        Option1Text:this._fb.array([]),
        Option2Text:this._fb.array([]),
        Option3Text:this._fb.array([]),
        Option4Text:this._fb.array([]),
        SolutionText:this._fb.array([]),
        CorrectOption:this._fb.group(
          {
            A:[false],
            B:[false],
            C:[false],
            D:[false]
          }
        )
      })

    });

    this.addProblemJsonControls();
  }

  initQuestionParts(){
    return this._fb.group({
      Type: ['', Validators.required],
      Text:['',Validators.required]
    })
  }

  addProblemJsonControls(){
    const control1 = <FormArray>this.addProblemForm.controls['ProblemJson']['QuestionText'];
    control1.push(this.initQuestionParts());
    const control2 = <FormArray>this.addProblemForm.controls['ProblemJson']['Option1Text'];
    control2.push(this.initQuestionParts());
    const control3 = <FormArray>this.addProblemForm.controls['ProblemJson']['Option2Text'];
    control3.push(this.initQuestionParts());
    const control4 = <FormArray>this.addProblemForm.controls['ProblemJson']['Option3Text'];
    control4.push(this.initQuestionParts());
    const control5 = <FormArray>this.addProblemForm.controls['ProblemJson']['Option4Text'];
    control5.push(this.initQuestionParts());
    const control6 = <FormArray>this.addProblemForm.controls['ProblemJson']['SolutionText'];
    control6.push(this.initQuestionParts());
  }

In addProblemJsonControls() method i am trying to access the different controls of ProblemJson Form Group, but i am getting an error which says

EXCEPTION: Uncaught (in promise): Error: Error in :0:0 caused by: Cannot read property 'push' of undefined
Error: Error in :0:0 caused by: Cannot read property 'push' of undefined

Please help me in accessing the FormGroup correctly. I am new to Reactive Form.

1
what is imports section? - Roman C
const control1 = <FormArray>this.addProblemForm.get('ProblemJson.QuestionText');? - Simon Z.

1 Answers

3
votes

I just resolved this myself after hours of frustration. A couple of ideas:

  • Access the controls like Simon Z. suggested in his comment
  • Ensure the the HTML portion is built correctly too

This example from the Angular docs really helped me.

Accessing controls:

this.addProblemForm = this._fb.group({
     ProblemJson: this._fb.group({
        QuestionText:this._fb.array([]),
        Option1Text:this._fb.array([])
});
const control1 = <FormArray>this.addProblemForm.get('ProblemJson.QuestionText‌​');

HTML side: You really need both the component TS and the HTML parts correct together, or else you could get errors. You didn't post the HTML, but just to add to this, it would look something like:

<form [formGroup]="addProblemForm">
     <div formGroupName="ProblemJson">
          <div formArrayName="QuestionText"></div>
          <div formArrayName="Option1Text"></div>
     </div>
</form>

The key here is the structure/nesting of the FormGroup must match exactly in TypeScript and HTML. You may not care about "ProblemJson" FormGroup in the HTML for example, but you have to declare it. That was my issue, at least.