Angular 14: Removing elements from FormArray causes the remaining elements to lose their values

My form includes custom inputs and utilizes the ControlValueAccessor. To view the implementation, visit this link. I encountered an issue where deleting an item from a FormArray would inadvertently clear the values of the other FormGroups still present in the array. An example scenario of this can be seen by adding media queries and deleting one after filling out another one. The code snippet below demonstrates how I have structured everything.

The form

SvgForm : FormGroup<SvgForm> = new FormGroup<SvgForm>({
    title: new FormControl<string>(''),
    graphicId: new FormControl<string>(''),
    svgInput : new FormControl<string>(''),
    viewBox : new FormGroup<ViewBoxParams>({
      x: new FormControl<string>(''),
      y: new FormControl<string>(''),
      width: new FormControl<string>(''),
      height: new FormControl<string>('')
    }),
    styling: new FormGroup<StylingParams>({
      globalStyles: new FormControl<string>(''),
      mediaQueries: new FormArray<FormGroup<MediaQueryParams>>([])
    })
  });

I pass the styling FormGroup into a custom component called styling-input in the template using an @Input() like so

<styling-input [StylingForm]="SvgForm.controls.styling"></styling-input>

This is how the styling-input is set up.

styling-input.component.ts

@Component({
  selector: 'styling-input',
  templateUrl: './styling-input.component.html',
  styleUrls: ['./styling-input.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: StylingInputComponent,
      multi: true
    }
  ]
})
export class StylingInputComponent implements ControlValueAccessor{

  @Input() StylingForm!: FormGroup<StylingParams>;
  
  get MediaQueryList() {
    return this.StylingForm.get('mediaQueries') as FormArray<FormGroup<MediaQueryParams>>;
  }

  writeValue(value: any){ if(value){ this.StylingForm.setValue(value); } }

  registerOnChange(fn: any){ this.StylingForm.valueChanges.subscribe(fn); }

  registerOnTouched(onTouched: Function){}

  private createMediaQueryGroup(): FormGroup<MediaQueryParams> {

    return new FormGroup<MediaQueryParams>({
      selectorParams: new FormGroup<MediaSelectorParams>({
        mediaType: new FormControl<MediaTypeParams>('all'),
        expressions: new FormArray<FormGroup<MediaExpressionGroupParams>>([]),
      }),
      rules: new FormControl<string>('')
    });
  }

  public addMediaQuery():void{
    this.MediaQueryList.push(this.createMediaQueryGroup());
  }

  public removeMediaQuery(item: number): void{
    this.MediaQueryList.removeAt(item);
  }

}

Then in the template, I iterate over the MediaQueryList getter like this

<article formArrayName="mediaQueries">

  <media-query-input *ngFor="let a of MediaQueryList.controls; let i = index"
    [MediaQueryForm]="a"
    [attr.GroupId]="i"
    (RemoveGroup)="removeMediaQuery($any($event))"
  ></media-query-input>

</article>

The MediaQueryForm property is passed into the component as an @Input(), and the i variable is used to determine which group to remove when the delete button is clicked. The removeMediaQuery() function utilizes removeAt() on the MediaQueryList.

I have not explored alternative solutions as the removal from a FormArray is the suggested method. It is possible that interactions with the ControlValueAccessor may be causing issues under the surface. If anyone has insights on why this issue occurs and how to resolve it, I would greatly appreciate it.

Answer №1

Ensure the GroupId input value is passed to the media-query-input component.

Instead of using attribute values, pass the input without the attr prefix.

[attr.GroupId]="i" ===> [GroupId]="i"

styling.input.component

 <media-query-input *ngFor="let a of MediaQueryList.controls; let i = index"
        [MediaQueryForm]="a"
        [GroupId]="i"
        (RemoveGroup)="removeMediaQuery($any($event))" >
 </media-query-input>

Example with Modifications

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

Strict mode error occurs when attempting to assign a value to ngComponentOutlet that is incompatible with the type of the lazy-loaded component

I am attempting to implement lazy loading for a component in Angular 11 (strict mode) using guidance from this tutorial. Dealing with strict mode has been challenging as there are very few resources available that cater to it. The goal is to have a compon ...

Differentiating body classes in Angular 5

I am working on a project with both a login screen and a dashboard screen. The body classes for these screens are different, as shown below: <body class="hold-transition skin-black-light sidebar-mini" > // for dashboard <body class="hold-transi ...

Creating Apache Arrow vectors in TypeScript for writing data to a Table

Currently, I am in the process of creating a method that is designed to take a column of data, referred to as data: any[], and then pack it into an Arrow-typed Array Buffer for insertion into an Arrow table. To illustrate with an example, if we consider T ...

Overriding a shared module service in Angular from a separate module: A step-by-step guide

I am working with various modules such as SchoolModule, UniversityModule, and SharedModule The SharedModule includes a BaseService that both the SchoolModule and UniversityModule providers are utilizing as an extension When loading the SchoolModule, I ne ...

The Angular overlay panel remains open consistently

I recently developed an Angular component similar to p-overlaypanel, but I'm facing an issue where it remains open for every item I click. What I actually want is for only one overlay panel to be clicked and shown at a time - if I click on another ove ...

Definition file for Typescript Angular 1.5 component

Encountering a problem with typescript and angular 1.5 - when building, an error pops up saying error TS2339: Property 'component' does not exist on type 'IModule'.. Could it be that I overlooked a definition file containing this proper ...

What is the best approach to develop a React Component Library adorned with Tailwind CSS and enable the main project to easily customize its theme settings?

Currently, I am in the process of developing an internal component library that utilizes Tailwind for styling. However, a question has arisen regarding how the consuming project can incorporate its own unique styles to these components. Although I have th ...

Require users to sign in immediately upon landing on the homepage in Next JS version 13 or 14

I have created a traditional dashboard application using Next.js 13 with a pages router that places all pages behind the /dashboard route, such as /dashboard/users, /dashboard/orders, and so on. I want to ensure that when a user visits the website, a fork ...

Allowing Cross-Origin requests in Spring BootLet's configure the

Every time I attempt to communicate with my backend using my Angular client, I encounter a common error message when trying to perform POST, PUT, and DELETE requests: Access to XMLHttpRequest at 'http://localhost:8087/categories' from origin &ap ...

Complete set of keys within a type

In my TypeScript project, I am working with an API (specifically OData API) to retrieve data. This API allows the selection of specific fields to retrieve. For example, api/some/getbyid(42)?$select=x,y,z can be used to get fields x, y, and z, along with s ...

Eliminate the need to input the complete URL every time when making server calls

Currently, my springbok application has a React-Typescript frontend that is functioning well. I am using the request-promise library to make requests like this: get('http://localhost:8080/api/items/allItems', {json: true}). However, I would like ...

What is the cause of the error message "property 'map' is undefined"?

I am currently working on a service that looks like this: public getUsers() { return this.httpClient.get(environment.BASE_URL + `api/all`); } In my component, I have implemented the ngx-bootstrap table to display the user data. import { Component, OnI ...

Oops! The mighty gulp-clean frowns upon attempts to eradicate files outside its domain

Whenever I execute the command: gulp clean I encounter an error even though I tried using: gulp clean --force but it didn't work. Could someone please clarify what might be causing this issue or what mistake I am making? Your help would be greatly ...

Loading data into the Nuxt store upon application launch

Currently, I'm working on an app using Nuxt where I preload some data at nuxtServerInit and store it successfully. However, as I have multiple projects with similar initial-preload requirements, I thought of creating a reusable module for this logic. ...

Does the value of an Angular reactive form control only reflect what the user inputs?

I am working with a reactive form where I need to extract values and assign them to a variable defined in an interface. The form is populated using the Google Places API, which disables user interaction with all controls except for the initial address inpu ...

Encountering a 404 error with systemjs-angular-loader.js in a production environment

Currently, I am working on the most recent Angular/Quickstart project that utilizes systemjs-angular-loader.js to load app-relative HTML templates without the need for the moduleId property. During development and testing with "npm start" to serve pages, ...

An error was encountered: The CommonModule type does not contain the 'ɵmod' property. This issue is occurring at the getNgModuleDef function in the core.js file

After transferring my project to Amazon Workspace and updating Angular to version 14.2.6, I encountered an issue where I received the error message: "Uncaught Error: Type CommonModule does not have 'ɵmod' property." This error did not occur on m ...

Using a global CSS file in Angular can lead to large module bundles being emitted by Webpack

In our Angular application generated with angular-cli, we are utilizing various global styles and imports defined in the styles.scss file (which begins with /* You can add global styles to this file, and also import other style files */ if that sounds fami ...

Passing a variable from the second child component to its parent using Angular

Need help with passing variables between two child components Parent Component: deposit.component.html <div> <app-new-or-update-deposit [(isOpenedModal)]="isOpenedModal"></app-new-or-update-deposit> </div> Deposit Component ...

Internet Explorer is throwing unexpected routing errors in Angular 2

I have a spring-boot/angular 2 application that is working perfectly fine on Chrome, Safari, Opera, and Edge. However, when accessed through Internet Explorer, the app directly routes to the PageNotFound component. I have tried adding shims for IE in the i ...