javascriptangularautocompleteangular-materialmat-autocomplete

How to update mat-autocomplete options from another component?


I have two components called Employee and Form in my application. There are 2 mat-autocomplete: State and City lists in EmployeeComponent. I fill and pass these mat-autocomplete controls to the FormComponent using "formData" parameter:

Employee Component:

html

<form #form [formData]="formControls"></app-form>

ts

formControls = [];
states: StateDto[] = [];
cities: CityDto[] = [];

// fill employee list
getStates() {
    this.demoService.getStates().subscribe((data: StateDto) => {
      this.states = data;
    });
}

getCities() {
    this.demoService.getCities().subscribe((data: CityDto) => {
      this.cities = data;
    });
}

// create for data array
this.formData = [
  {
    id: 'states',
    type: 'custom-autocomplete',
  },
  {
    id: 'cities',
    type: 'custom-autocomplete',
  }
]


// set form control's list data
this.formControls = this.formData.map(item => {
  if (item.id === 'states') {
    item.options = this.states;
  }
  else if (item.id === 'cities') {
    item.options = this.cities;
  }
  return item;
});

Form Component:

html

@Input() formData = [];
options = {};

ngOnInit() {
    //code omitted for brevity
    this.autocompleteControl.forEach(item => {
        // here I set each autocomplete's options
        this.options[item.id] = item.options;
    });
}

At this point, when I select a state I want the cities list is cleared and the filled by the cities of the selected state. So, where should I manage this? On EmployeeComponent or on FormComponent? And hoca should I set the cities list options with an elegant solution?


Solution

  • First of all, you use 2 mat-autocomplete. That means the same functionality and behavior. In this situation, I prefer to use a reusable component for that part.

    html in parent component

    @Component({
      selector: 'app-custom',
      template: "<div *ngFor='let a of data'>{{a}}</div>",
    })
    export class CustomComponent {
      @Input() data: string[] = [];
    }
    

    html in parent component

    <div>
      <h1>City</h1>
      <app-custom [data]="city"></app-custom>
    </div>
    
    <div>
      <h1>State</h1>
      <app-custom [data]="state"></app-custom>
    </div>
    

    ts in parent component

    export class AppComponent {
      city: string[] = ['A', 'B', 'C'];
      state: string[] = ['AAA', 'BBB', 'CSS'];
    }
    

    Code