FormGroup reset() doesn't reset custom form control
  • 27-Apr-2023
Lightrun Team
Author Lightrun Team
Share
FormGroup reset() doesn't reset custom form control

FormGroup reset() doesn’t reset custom form control

Lightrun Team
Lightrun Team
27-Apr-2023

Explanation of the problem

This is a bug report for the issue encountered when using a custom form control in Angular. Specifically, the control does not reset when the form is reset using the FormGroup reset() method. Although the control value does clear, the control properties dirty, pristine, untouched, and touched are not updated as expected.

The expected behavior is for the control properties to reset along with the control value when the form is reset using the FormGroup reset() method. The current behavior is not consistent with the expected behavior.

To reproduce the issue, follow the instructions provided in this link: http://plnkr.co/edit/xeIy7DEg5GwTqe7JgOv9. This should demonstrate the issue.

Troubleshooting with the Lightrun Developer Observability Platform

Getting a sense of what’s actually happening inside a live application is a frustrating experience, one that relies mostly on querying and observing whatever logs were written during development.
Lightrun is a Developer Observability Platform, allowing developers to add telemetry to live applications in real-time, on-demand, and right from the IDE.

  • Instantly add logs to, set metrics in, and take snapshots of live applications
  • Insights delivered straight to your IDE or CLI
  • Works where you do: dev, QA, staging, CI/CD, and production

Start for free today

Problem solution for FormGroup.disable() and FormGroup.enable() do not allow resetting disabled state in Angular Angular

One possible solution is to use a workaround where you go into each control of the form and call the setErrors(null) method. This approach has been reported to work, especially in cases where md-form-field was leaving a red glow on the control after submitting. In this workaround, the reset() method is first called on the formGroup, then markAsUntouched() is used to reset the form control states, and finally setErrors(null) is used to clear any errors on each control.

Another approach that was suggested is to simply call the reset() method on the formGroup. However, it was noted that if the reset() method is called inside the response of a request, the form will clear but the errors may still appear.

Therefore, it’s important to evaluate the specific use case and context when resetting a form in Angular, and to consider whether additional steps like calling markAsUntouched() or setErrors(null) may be necessary.

Other popular problems with Angular

Problem: Change Detection Performance

One of the most common problems with Angular is related to change detection performance. Angular uses a mechanism called change detection to update the view when the component’s data changes. However, if the component has a lot of bindings or the change detection runs too often, the performance can suffer. This can lead to slow rendering times and a poor user experience.

Solution:

One solution to this problem is to use the OnPush strategy for change detection. This strategy only runs change detection when an input property of the component changes, instead of running it for all bindings. To use the OnPush strategy, you need to set the changeDetection property of the component to ChangeDetectionStrategy.OnPush.

@Component({
  selector: 'app-my-component',
  template: '...',
  changeDetection: ChangeDetectionStrategy.OnPush
})

Another solution is to use the async pipe for bindings that are observables. This pipe automatically subscribes to the observable and unsubscribes when the component is destroyed, and also triggers change detection only when the observable emits a new value.

@Component({
  selector: 'app-my-component',
  template: `
    <div *ngFor="let item of items | async"></div>
  `
})
export class MyComponent {
  items: Observable<Item[]> = this.service.getItems();
}

Problem: Memory Leaks

Another common problem with Angular is related to memory leaks. Memory leaks occur when an object is no longer in use but is still being held in memory by other objects. This can happen when a component is not properly unsubscribed from observables or event emitters, or when a component is not properly cleaned up during the destruction process.

Solution:

To avoid memory leaks, it is important to unsubscribe from observables and event emitters when a component is destroyed. One way to do this is to use the ngOnDestroy lifecycle hook. In this hook, you can call the unsubscribe method of the subscription or use takeUntil operator.

export class MyComponent implements OnInit, OnDestroy {
  private unsubscribe$ = new Subject<void>();

  ngOnInit() {
    this.service.getItems()
      .pipe(takeUntil(this.unsubscribe$))
      .subscribe(items => this.items = items);
  }

  ngOnDestroy() {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }
}

Another way to avoid memory leaks is to use the async pipe for observables and event emitters. This pipe automatically unsubscribes when the component is destroyed.

<div *ngFor="let item of items | async"></div>

Problem: Routing and Navigation

Routing and navigation is one of the most important parts of any single-page application, and it’s also one of the most common sources of problems in Angular. Issues can range from routing configuration to navigation events and guards.

Solution:

One solution to this problem is to use the Angular Router module, which provides a powerful and flexible way to handle routing and navigation. This module provides a powerful way to configure routes and navigate between different parts of your application.

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: '**', component: PageNotFoundComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Another solution is to use guards. Guards are classes that can be used to protect access to certain routes. They can be used to prevent a user from navigating to a route or to prompt the user for confirmation before navigating.

@Injectable()
export class CanActivateGuard implements CanActivate {
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    // code to check if the user is allowed to activate the route
    return true;
  }
}

In the routing configuration, the guard can be added to a route to protect it.

const routes: Routes = [
  { path: 'secret', component: SecretComponent, canActivate: [CanActivateGuard] }
];

This way the routing and navigation in the application can be handled properly and also it’s possible to restrict access to certain routes based on certain conditions.

A brief introduction to Angular

Angular is a JavaScript framework for building web applications. It is built on top of the popular JavaScript framework, AngularJS. Angular is a complete rewrite of AngularJS and is designed to be more efficient, modular, and easier to use. It is also built with TypeScript, a superset of JavaScript that provides static typing and other features that make it easier to write and maintain large applications.

Angular uses a component-based architecture, where an application is composed of a tree of components. Each component is responsible for a specific part of the application’s UI and logic. Components can also be nested, allowing for a hierarchical and modular structure. Angular also provides a powerful template language that allows developers to declaratively describe the UI of a component. The template language is tightly integrated with the component’s logic, making it easy to create complex and interactive UIs. Angular also provides a powerful set of directives and pipes that can be used to manipulate the DOM and transform data. The framework also provides a powerful set of services that can be used to share data and logic across the application.

Most popular use cases for Angular

  1. Building Single-Page Applications (SPAs): Angular can be used to build Single-Page Applications (SPAs). SPAs are web applications that load a single HTML page and dynamically update the content as the user interacts with the app. Angular provides a powerful set of tools for building SPAs, including a powerful router for handling client-side routing and navigation, and a powerful template language for describing the UI of the application.
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: '**', component: PageNotFoundComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
  1. Building Progressive Web Applications (PWAs): Angular can be used to build Progressive Web Applications (PWAs). PWAs are web applications that can be installed on the user’s device and run offline. Angular provides a powerful set of tools for building PWAs, including a powerful service worker module that can be used to cache assets and provide offline support.
  2. Building Mobile Applications: Angular can be used to build mobile applications using technologies like Apache Cordova or NativeScript. This allows developers to create mobile apps using web technologies like HTML, CSS, and JavaScript, and then package them for various platforms such as iOS and Android. Angular provides a powerful set of tools for building mobile apps, including a powerful layout system that can be used to adapt the app’s UI to different screen sizes and resolutions.
Share

It’s Really not that Complicated.

You can actually understand what’s going on inside your live applications.

Try Lightrun’s Playground

Lets Talk!

Looking for more information about Lightrun and debugging?
We’d love to hear from you!
Drop us a line and we’ll get back to you shortly.

By submitting this form, I agree to Lightrun’s Privacy Policy and Terms of Use.