Executing multiple instances of the cascading dropdown fill method in Angular 7

I am currently working on an Angular app that includes cascading comboboxes for country and state selection. However, I have noticed that the get states() method in my state.component.ts file is taking a long time to run. What could be causing this issue? I would like the method to only run when the country selection is changed. To debug, I have added a debugger statement. You can replicate the bug by opening the developer console with F12. If there is an error in my approach, I am open to completely changing my method.

Try it out on StackBlitz

Answer №1

Using a getter results in multiple calls throughout the lifecycle of the component.

A different approach is necessary. One option is to subscribe to the valueChanges of the form and update the "states" within the subscription, like so:

export class StateComponent  {
  _studentForm; 
  @Input() 
  set studentForm(value)  
  {
     this._studentForm=value;
     this._studentForm.get(this.countryId).valueChanges.subscribe(res=>{
       var val = this._studentForm.controls[this.countryId].value;
       this.states=this.selectService.filterStates(val);
     })
  }
  @Input() id:string;
  @Input() countryId:string;
  states: State[];

  constructor(private selectService: SelectService) { }
}

Your component's HTML should reference _studentForm

<form [formGroup]="_studentForm">
    <select [formControlName]="id" >
      <option [value]="0">--Select--</option>
      <option *ngFor="let state of states " value= {{state.id}}>{{state.name}}</option>
    </select>
</form>

Check out your modified stackblitz here

Update Considering the complexity of the issue, it might be time to create a component that controls both country and states simultaneously. This will involve using viewProviders and FormGroupDirective.

The new component would look something like this:

@Component({
  selector: 'app-country-state',
  viewProviders: [
    {
      provide: ControlContainer,
      useExisting: FormGroupDirective
    }
  ],
  templateUrl: './country-state.component.html',
  styleUrls: ['./country-state.component.css']
})
export class CountryStateComponent implements OnInit, OnDestroy {

  @Input() countryID: string;
  @Input() stateID: string;
  @Input() countryLabel: string;
  @Input() stateLabel: string;

  _countryID: FormControl; 
  _stateID: FormControl;    
  states: any[] = [];
  countries: any[] = [];

  isAlive: boolean = true;
  constructor(private selectService: SelectService,
    private fgd: FormGroupDirective) { }

  ngOnInit() {
    
    this.countries = this.selectService.getCountries();

    this._countryID = (this.fgd.form.get(this.countryID) as FormControl);
    this._stateID = (this.fgd.form.get(this.stateID) as FormControl);
    
    this._countryID.valueChanges.pipe(
      takeWhile(() => this.isAlive)
    ).subscribe(res => {
      this.states = this.selectService.filterStates(this._countryID.value);
    })

  }
  ngOnDestroy() {
    this.isAlive = false;
  }
}

The corresponding .html file:

{{countryLabel}}:<br/>
<select [formControl]="_countryID">
      <option [value]="0">--Select--</option>
      <option *ngFor="let country of countries" [value]="country.id">{{country.name}}</option>
    </select>
    <br/>
{{stateLabel}}:<br/>
    <select [formControl]="_stateID" >
      <option [value]="0">--Select--</option>
      <option *ngFor="let state of states " value= {{state.id}}>{{state.name}}</option>
    </select>

Usage example:

<app-country-state 
    [countryID]="'countryId1'" [countryLabel]="'Student Country'"
    [stateID]="'stateId1'" [stateLabel]="'Student State'">
</app-country-state>

Experience the changes in the updated stackblitz

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

Tips for moving all elements from array2 to array1

I need assistance with a code snippet that involves pushing objects from array2 into array1. array1 = [{name:'first'}, {name:'second'}]; array2 = [{name:'third'}, {name:'fourth'}, {name:'five'}]; // Desir ...

Retrieving the value from the series object and showing it in the tooltip of a high chart with the help of Angular 4

I have successfully implemented the display of x and y values in the tooltip of a Highchart within my Angular 4 application. By utilizing the formatter function of the tooltip, I am able to achieve this functionality. The graphdata array is initially set w ...

Guidelines on encoding query parameters for a tRPC query with the fetch function

As stated in the tRPCs official documentation, the query parameters must adhere to this specific format: myQuery?input=${encodeURIComponent(JSON.stringify(input))} Here is an example of a procedure: hello: publicProcedure .input(z.object({ text: z.s ...

Error in Angular ngFor loop: Type 'OrderItem' is not compatible with type 'Iterable<any>'

In my HTML code, I have the following structure: <div class="grid mb-5" *ngFor="let orderItem of order.orderItems"> <div class="col-2">{{ orderItem.product.name }}</div> <div class="col-2&qu ...

I'm curious about the origins of the "readme" field within the artifact registry file

Within our private npm registry on Azure, we house our own npm package alongside the npmjs packages. One particular package, @typescript-eslint/parser, has caused our pipelines to fail during the npm install task due to a SyntaxError: Unexpected end of JSO ...

What is the process for activating shift key - multi-selection in the PrimeNG pick list?

I'm currently utilizing the prime ng pick list from the PrimeNG API located at: https://www.primefaces.org/primeng/#/picklist An issue I've encountered is that the picklist doesn't support multiple selections. For instance, in this example ...

How does the highlighting feature in Fuse.js includeMatches function operate?

Currently, in my Next JS/Typescript web application, I am using the Fuse.js library. However, I am still uncertain about how the includeMatches option functions for highlighting purposes. Whenever I enable this option, I receive a matches object within the ...

Updating a value in an array in Angular using the same ID

I have an array of buildings that looks like this: const buildings = [ { id: 111, status: false, image: 'Test1' }, { id: 334, status: true, image: 'Test4' }, { id: 243, status: false, image: 'Test7' }, { id: 654, stat ...

Issues with Webpack and TypeScript CommonsChunkPlugin functionality not functioning as expected

Despite following various tutorials on setting up CommonsChunkPlugin, I am unable to get it to work. I have also gone through the existing posts related to this issue without any success. In my project, I have three TypeScript files that require the same ...

Hello everyone, can someone provide guidance on integrating Spring Boot session with an Angular project?

Can anyone provide guidance on utilizing a Spring Boot session in an Angular project? I am looking to send the login and password via POST request in the following image Click here for image description ...

Tips for simulating mouse events in Jasmine tests for Angular 2 or 4

New to Jasmine testing, I'm exploring how to test a directive that handles mouse events such as mouse down, up, and move. My main query is regarding passing mouse coordinates from the Jasmine spec to my directive in order to simulate the mouse events ...

Can a TypeScript generic version of the Y-combinator be successfully executed?

Here is an interesting JavaScript implementation of the Y-combinator: const Y = g => (x => g(x(x)))(x => g(x(x))) //or const Y = f => { const g = x => f(x(x)) return g(g) } I've been thinking, could it be possible to create a TypeS ...

What is the best way to retrieve the Object key for the connected object in angularFire2?

When I search the database using a user key, I check if an associated object exists: let url = ``/userMember/${userKey}``; const userMemberRef = this.af.database.object(url, { preserveSnapshot: true }); userMemberRef.subscribe(data => { if(data.val ...

Filling out form controls with a variety of values

I'm currently working on a form that features multiple select dropdowns generated from data retrieved from an API. Although unsure if I'm approaching this correctly, I've managed to populate the form for the 'appointmentPackages' ...

What type of event does the Input element in material-ui v1 listen for?

I'm currently grappling with material-ui v1 as I search for the appropriate event type for input elements. Take a look at the code snippet below: <Select value={this.numberOfTickets} onChange={this.setNumberOfTickets}> .... Here is the impleme ...

Is it possible to execute TestCafe tests using TypeScript page objects that have not been utilized?

While working with TestCafe, I am implementing tests using the Page Objects pattern. I have already written some page objects in advance, even before their actual usage, as I am familiar with the page and know what to anticipate. However, when attempting ...

I'm really puzzled as to why they would choose to export in this manner in React

I noticed that several files were exported in a similar manner, and I'm unsure why this specific method was chosen. Could there be any advantages or particular reasons for exporting them like this? index.ts export { default } from './Something& ...

Why is it that dependency injection is not functioning properly in my Angular 17 project when I am utilizing esbuild for the build process

I am looking to switch from using "@angular-devkit/build-angular:browser" to "@angular-devkit/build-angular:browser" in order to improve my development speed. However, the issue I am facing is that every time I launch my application, the following error ap ...

Executing unit tests in Angular - launch Chrome upon successful build completion (which may take a while)

There are instances where the Angular app takes longer than the default 2-minute timeout for Chrome started by Karma to capture the content. Is there a method to compel Karma to launch Chrome after the build is completed? In my package.json: { "depende ...

Removing items from an array within an object stored in local storage using an Ionic application

One of my challenges involves an Ionic App that stores data in the localStorage. I need to remove specific items from an array within an object in the localStorage when a user clicks on them. Even though I have the code below, it doesn't seem to be f ...