[Fixed] I need to conditionally render an angular component based on users selection

Issue

I need to show the aprs-attachments only when hostSection/environments ‘PCCL (Production)’ is selected. Below is how I have my current code set up. I can’t figure out how to declare the *ngif statement to only show the aprs-attachments when PCCL is selected in the app. Currently if any environment is selected it’s visible. Also I need the aprs_attachments to be removed if the environment is unchecked.

component.ts

export class HostComponent implements ControlValueAccessor {
constructor(private fb: FormBuilder) {}

hostSection = this.fb.group({
tso: '',
environments: '',
businessCase: '',
additionalAccess: '',
});

environments = [
{ label: 'PCCL (Production)' },
{ label: 'PCCLT (Production Training)' },
{ label: 'SPCCL  (Systems Test)' },
{ label: 'TPCCL (IMS Test)' },
{ label: 'VPCCL (IA and MO)' },
];

tsoRegions = [{ label: 'TSO H1' }, { label: 'TSO H2' }];

// ControlValueAccessor implementation
public onTouched: () => void = () => {};
writeValue(val: any): void {
val && this.hostSection.patchValue(val, { emitEvent: false });
}
registerOnChange(fn: any): void {
this.hostSection.valueChanges.subscribe(fn);
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
isDisabled ? this.hostSection.disable() : this.hostSection.enable();
}
}

component.html

<form [formGroup]="hostSection">
<div class="tds-container">
<div class="tds-row">
  <div class="tds-col-md-auto">
    <aprs-checkbox-group
      legendTitle="Environment"
      [checkboxes]="environments"
      formControlName="environments"
    ></aprs-checkbox-group>
  </div>
  <div class="tds-col-md-auto">
    <aprs-checkbox-group legendTitle="TSO" [checkboxes]="tsoRegions" 
formControlName="tso">
    </aprs-checkbox-group>
  </div>
</div>
<div class="tds-row">
  <div class="tds-col-lg-10 tds-col-xl-8">
    <div class="tds-field">
      <label class="tds-field__label"
        >Additional Host Access Details
        <textarea class="aprs-textarea" formControlName="additionalAccess"> 
</textarea>
      </label>
    </div>
    <div class="tds-field">
      <label class="tds-field__label"
        >Business Case
        <textarea class="aprs-textarea" formControlName="businessCase" 
</textarea>
      </label>
      <ng-container>
        <span class="tds-field__label">Manager Approval (required for PROD) 
</span>
        <aprs-attachments
          [showHeading]="false"
          buttonSize="small"
          class="tds-justify-content-center"
          formControlName="approvalAttachment"
        >
        </aprs-attachments>
      </ng-container>
    </div>
  </div>
</div>
</div>
</form>

Solution

When you set your form the control ‘environments is empty. Assuming you want your environments array inside of that control you would do:

hostSection = this.fb.group({
   environment: this.fb.control(this.environments)
})

In your template you would then check

*ngIf="hostSection.get('environment').value[0].label"

The problem with this way is that it is not very dynamic. A better approach would be to instansiate a ‘environments’ as a formArray type like so:

hostSection = this.fb.group({
   environment: this.fb.array([])
})

Then you’d create a method and ngOninit to push each instance onto that array:

pushValuesOfEnvironment() {
let formArray = this.hostSection.get('environment') as FormArray;
this.environments.forEach(value => {
  (this.hostSection.get('environment') as FormArray).push(this.fb.control(value.label))
})}

Use this stackblitz as an example. You’ll see that when the user selects production that string will display:
https://stackblitz.com/edit/angular-ivy-uwucgp?file=src%2Fapp%2Fapp.component.html

Leave a Reply

(*) Required, Your email will not be published