Hide the FormArray in a Reactive Form if it is not populated or cannot be determined

As a newcomer to Angular 4, I've embarked on my first project and started learning the ropes.

I have devised a Reactive Form to showcase a form structure that looks like this:

Form (FormGroup)
  |
  --> aggLevels (FormArray)
       |
       --> aggregationLevelName (FormControl - displayed in a label)
       |
       --> variableDataForLevel (FormArray)
            |
            --> variableDataId (FormControl)
            |
            --> value (FormControl)

The following snippet shows the HTML component for this:

<form [formGroup]="varDataForm" (ngSubmit)="onSubmit()" novalidate>
    <div formArrayName="aggLevels"
         *ngFor="let agLevel of varDataForm.get('aggLevels')?.controls; let aggLevelId = index;">
        <div [formGroupName]="aggLevelId">
            <label>{{agLevel?.get('aggregationLevelName')?.value}}</label>
            <div formArrayName="variableDataForLevel"
                 *ngFor="let vardata of varDataForm.get('aggLevels')?.controls[0]?.get('variableDataForLevel')?.controls; let rowIndex = index;">
                <div [formGroupName]="rowIndex">
                    <select formControlName="variableDataId">
                        <option *ngFor="let gs1 of gs1AIs" [value]="gs1.Id">{{gs1.description}}</option>
                    </select>
                    <input formControlName="value" placeholder="Value">
                    <div class="error" *ngIf="vardata.get('value').hasError('required') && vardata.get('value').touched">
                        Required
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>

The issue arises when there are no elements in the variableDataForLevel FormArray. The error message I encounter is as follows:

ng:///AppModuleShared/VarDataComponent.ngfactory.js:49 ERROR Error: Cannot find control with path: 'aggLevels -> 1 -> variableDataForLevel -> 0'

Despite using the safe navigation operator ?, such as here:

varDataForm.get('aggLevels')?.controls[0]?.get('variableDataForLevel')?.controls

The problem persists. While aggLevels and variableDataForLevel aren't undefined, the error remains unresolved.

How can I prevent displaying the FormArray if it's empty? Being new to Angular, I'm uncertain about fixing this issue.

This TypeScript class corresponds to the component:

(Component details here...)

My suspicion rests on this method:

createVarDataControls(varData: IVarData[]): any[] {
    let array: any[] = [];

    for (let vData of varData) {
        let group: FormGroup;

        group = this.fb.group({
            variableDataId: vData.variableDataId,
            value: vData.value
        });

        array.push(group);
    }

    return array;
}

If varData turns out to be empty, an Any[] gets returned despite my intent not to show anything empty on the form.

I revised the createVarDataControls method to generate a FormGroup instead of an array if varData is empty. Although this workaround enables me to proceed without errors, it doesn't fully address the underlying issue:

(Method adjustment here...)

However, this modification results in displaying two blank controls which isn't ideal. This approach merely serves as a diagnostic tool rather than a solution.

Answer №1

I've discovered the issue and wanted to share my solution in case it benefits others.

While looping through the second FormArray:

<div formArrayName="variableDataForLevel"
                 *ngFor="let vardata of varDataForm.get('aggLevels')?.controls[0]?.get('variableDataForLevel')?.controls; let rowIndex = index;">

The corrected version is:

<div formArrayName="variableDataForLevel"
        *ngFor="let vardata of agLevel.get('variableDataForLevel')?.controls; let rowIndex = index;">

I replaced

varDataForm.get('aggLevels')?.controls[0]?
with agLevel.

Additionally, I updated the createVarDataControls method to return undefined if there is no variable data to display:

createVarDataControls(varData: IVarData[]): any[] | undefined {
    let array: any[] = [];

    if ((varData == null) || (varData.length == 0)) {
        return undefined;
    }
    else {
        for (let vData of varData) {
            let group: FormGroup;

            group = this.fb.group({
                aggregationLevelConfigurationId: vData.aggregationLevelConfigurationId,
                productionOrderId: vData.productionOrderId,
                variableDataId: vData.variableDataId,
                value: vData.value
            });

            array.push(group);
        }

        return array;
    }
}

It's all about trial and error until you find the right solution!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with displaying validation message in Angular Material custom inputs when using mat-stepper

I developed a customized control following the official guidelines using ControlValueAccessor: Check out this guide for creating a custom form field control Here is another helpful resource on Angular custom form controls The main problem I encountered i ...

Mastering the art of shaping state in NGRX for the master-detail pattern

Imagine a scenario where I am developing a compact app for organizing tasks. This app makes use of angular and NGRX to efficiently manage the state. Each day, the user loads tasks in the morning and then travels to different locations to complete them. Th ...

BehaviorSubject Observable continuously notifies unsubscribed Subscription

Utilizing a service called "settings", initial persisted values are read and provided through an observable named "settings$" to components that subscribe to it. Many components rely on this observable to retrieve the initial values and exchange updated va ...

Detecting when Angular2 input values change

Here is the updated code snippet: I am attempting to modify an input field and then submit the form. However, when I retrieve the form data using server-side code, the input has not been updated. <form id="cardsForm" method="post"> <inpu ...

What is the best way to store an audio Blob in the repository file system?

Currently, I have set up a system to record user audio through the device's microphone and can successfully download it on the same device. However, my goal now is to store this audio in my database by making an API call. How can I efficiently send th ...

The Angular Universal client side appears to be inactive

My server-side rendered application is up and running, but I'm encountering an issue where the client-side functionality seems to be missing. Despite the routes rendering properly, none of the click events or console logs are working on the client sid ...

How can we update the form builder or form group in Angular 2 when making changes to the existing data in a table? I'm a bit confused on how to implement router

<tr *ngFor="let row of categories "> <td>{{row.categoryName}}</td> <td>{{row.visible}}</td> <td>{{row.instanceNumber}}</td> <td> <a class="btn btn-info btn-fill " [routerLink]="['/con ...

Using the useStaticQuery hook outside of a function component is not allowed and will result in an invalid hook call error. Remember to only call

I am currently facing an issue while trying to retrieve values using useStaticQuery from my gatsby-config.js file. Below are snippets of my code. Does anyone have any suggestions on how to resolve this problem? Thank you in advance. Repository: https: ...

What is the TypeScript equivalent of the Java interface.class?

Can you write a Java code in TypeScript that achieves the same functionality as the code below: Class<?> meta = Object.class; and meta = Processor.class; // Processor is an interface In TypeScript, what would be the equivalent of .class? Specifica ...

Could someone provide an explanation for the meaning of the phrase "class User extends Model<UserAttribute UserCreationAttribute>"?

View Image of the Issue I am puzzled by why we are utilizing both UserCreationAttribute and UserAttribute in that specific arrow, especially when UserCreationAttribute is created by omitting one field from UserAttribute. Can someone please clarify this fo ...

I seem to be missing some properties in the request body schema. Why am I receiving an incomplete model for

Seeking assistance in grasping the working of models in loopback4. Here's a model I defined: @model() export class ProductViewConfig extends BaseConfig { @property({ type: 'string', id: true, generated: true, }) _id?: strin ...

When using a try-catch block to validate an object, why does the Liskov Substitution Principle (LSP) fail to correctly

function parseAndValidate(obj: unknown): ParsedObj | void { try { // conducting various validations return parsedObj } catch { throw new Error('obj is invalid') } } const parsedObj = parseAndValidate(obj) I ...

Assigning a value to an Angular class variable within the subscribe method of an HTTP

Understanding the inner workings of this process has been a challenge for me. I've come across numerous articles that touch on this topic, but they all seem to emphasize the asynchronous nature of setting the class variable only when the callback is t ...

There seems to be an issue with AppModule in your code. The error message states that it is not recognized as an NgModule and the problem

After upgrading to node 6, angular 4, typescript 2.3.2, and @angular/cli 1.02, I meticulously followed the steps outlined in the Guide for updating @angular/cli. I will include my entire package.json below in case there are any relevant details. The specif ...

What is the best way to utilize angular2 components based on their name using ngFor?

Check out the components I've created: app-widget-resume app-widget-my-courses-learner app-widget-my-courses-teacher app-widget-my-calendar app-widget-virtual-classes I want to populate my dashboard component, called my-dashboard, by util ...

Tips for incorporating ngSwitch into loops

How can I customize the index of the square dots and utilize ngSwitch to link the .form-style div with a list of questions and inputs? The goal is to toggle the visibility of each question by switching between the square dots. Currently, only one question ...

Passing Parent Method to Child Component in React Native

I'm experiencing an issue trying to pass a method from my parent component to a child component. Although I believe my code is correct, I keep getting the error message undefined is not an object(evaluating '_this2.props.updateData'). Despit ...

Ways to access UserProfile in a different Dialogio

For the implementation of a chatbot, I am utilizing Microsoft's Bot Builder framework. However, upon implementing an alternative path to the dialog flow, I noticed that the user's Profile references are getting lost. Here is the code snippet fr ...

What is the contrast between element.getAttribute() value and a String in protractor?

When using protractor and typescript, I need to verify that the text saved in a textbox matches a certain string by comparing it with the resulting value of element.getAttribute("value"). Unfortunately, getText() does not work for this scenario b ...

Uncovering the mystery of retrieving form values from dynamic HTML in Angular 2

As a beginner in Angular 2, I am facing challenges extracting values from Dynamic HTML. My task involves having some Form Inputs and injecting Dynamic HTML within them that contain additional inputs. I followed the example by @Rene Hamburger to create the ...