Q:

Angular 2 - Setting validation later in reactive form array

I'm building a form array correctly via this way:
this.items.forEach(element => {
                    (<FormArray>this.myFormFixtures.get('fixtures')).push(this.fBuilder.group({
                        id: [element.id],
                        name: [element.name, Validators.required],
                        description: [element.description],
                        startDateTime: this.buildTimeDetails(element.startDateTime),
                        venueId: [element.venueId, Validators.required],
                        participants: this.buildParticipants(element.participants)
                    }));
                });
                this.myFormFixtures.valueChanges
                    .subscribe(formData => this.checkFixturesFormValidity(formData));

The "Participants" key is generated into an array with 2 ids with null value like so:
[
{id: null},
{id: null}
]

By default the 2 ids are optional. But I want to set both participant ids formControlNames to be required should one acquire a value.
So far my "checkFixturesFormValidity" function is looking like this, but for some reason the validation isn't being set:
checkFixturesFormValidity(formData)
    {
        console.log(formData);

        const control = <FormArray>this.myFormFixtures.controls['fixtures'];

        for (let i = 0; i < control.length; i++) {

            const participantsControl = (<FormArray>this.myFormFixtures.controls['fixtures']).at(i).get('participants') as FormArray;

                if ((((<any>this.myFormFixtures.controls['fixtures']).at(i).controls['participants'].at(0).get('id').value) != null) || (((<any>this.myFormFixtures.controls['fixtures']).at(i).controls['participants'].at(1).get('id').value) != null))
                {
                    (<any>this.myFormFixtures.controls['fixtures']).at(i).controls['participants'].at(0).get('id').setValidators([Validators.required]);
                    (<any>this.myFormFixtures.controls['fixtures']).at(i).controls['participants'].at(1).get('id').setValidators([Validators.required]);
                }

        }

    }

A:

I have somewhat been able to shorten all those long property paths, since in the iterations, we can pass for example the object you have named in your *ngFor, so that in methods we do not need to start with this.myFormFixtures.controls....
So what we have done here is to set a change event to your select. Since we know that when user makes a selection, if the value is else than null, we set Validators.required.
So content of tbody would look like this (shortened):
<tr *ngFor="let fixture of myFormFixtures.controls.fixtures.controls; 
            let c=index" [formGroupName]="c">
  <td><input type="text" formControlName="name" /></td>
  <td class="teamColumn">
    <div formArrayName="participants">
      <div *ngFor="let thisParticipant of fixture.controls.participants.controls; 
                   let i=index" [formGroupName]="i">
        <!-- We pass the current formgroup and value of dropdown, 
             which is null, 1 or 2 -->
        <select formControlName="id 
           (change)="doSomething(fixture.controls.participants, 
                     thisParticipant.controls.id.value)">
          <option [ngValue]=null>Please select</option>
          <option [ngValue]="1">Team Red</option>
          <option [ngValue]="2">Team Blue</option>
        </select>
      </div>
    </div>
  </td>
</tr>

Then the doSomething() would look like this:
// form array and chosen value
doSomething(formArr, val) {
  for (let x of formArr.controls) {
    x.controls.id.setValidators([Validators.required]);
    x.controls.id.updateValueAndValidity();
  }      
}

Your demo: https://plnkr.co/edit/hovobDwYUgH3C6fbe7eB?p=preview
PS, this doesn't take in consideration if user deselects a value.

