skip to Main Content

I work with reactive forms in my angular-project and i use mat-country-select for displaying countries in select in my child FormComponent.

<mat-select-country class="full-width"
                            [formControl]="form.controls.country"
                            [required]="true"
                            appearance="outline"
                            [itemsLoadSize]="0"
                            [value]="DEFAULT_COUNTRY"
                            label="Choose country">
          
        </mat-select-country>

I try to make modal dialog window for updating an Player in parent PlayerComponet, that has such structure as below.

export interface Player extends BaseResponse {
  lastName: string;
  firstName: string;
  dateOfBirth: Date;
  country: string;
  height: number;
  weight: number;
  position: string;
  jerseyNumber: number;
  teamName: string;
  teamId?: string | null;
  photoPath?: string | null;
}

in PlayerComponent before open update dialog window, i should initialize and pass form to my FormComponent

export class PlayersComponent implements OnInit {
  countries: Country[] = COUNTRIES;
 playerActionsForm!: FormGroup<PlayerActionsForm>;

fillUpdatePlayerForm(player: Player) {
    this.playerActionsForm.controls.id.setValue(player.id);
    this.playerActionsForm.controls.firstName.setValue(player.firstName);
    this.playerActionsForm.controls.lastName.setValue(player.lastName);
    this.playerActionsForm.controls.birthDay.setValue(player.dateOfBirth);
    const country = this.countries.find(
      (country) => country.name === player.country,
    );
    this.playerActionsForm.controls.country.setValue(country ? country : null);
    this.playerActionsForm.controls.height.setValue(player.height);
    this.playerActionsForm.controls.weight.setValue(player.weight);
    this.selectTeams$
      .pipe(
        map((teams) => teams?.find((team) => team.id === player.teamId)),
        take(1),
        untilDestroyed(this),
      )
      .subscribe((team) => {
        this.playerActionsForm.controls.team.setValue(team ? team : null);
      });
    this.playerActionsForm.controls.jerseyNumber.setValue(player.jerseyNumber);
    this.playerActionsForm.controls.position.setValue(player.position);
    this.playerActionsForm.controls.experiences.setValue([]);
  }

  initializeActionsForm() {
    this.playerActionsForm = new FormGroup<PlayerActionsForm>({
      id: new FormControl(''),
      firstName: new FormControl('', [
        Validators.required,
        Validators.pattern(NAME_PATTERN),
      ]),
      lastName: new FormControl('', [
        Validators.required,
        Validators.pattern(NAME_PATTERN),
      ]),
      birthDay: new FormControl(null, [
        Validators.required,
        dateValidator(moment().subtract(18, 'years').toDate(), 'max'),
      ]),
      country: new FormControl(null, Validators.required),
      height: new FormControl(1.01, [
        Validators.required,
        Validators.min(1.01),
      ]),
      weight: new FormControl(50.01, [
        Validators.required,
        Validators.min(50.01),
      ]),
      team: new FormControl(null),
      position: new FormControl('', Validators.required),
      jerseyNumber: new FormControl(0, [
        Validators.required,
        Validators.min(0),
      ]),
      experiences: new FormArray<FormGroup<PlayerExperienceForm>>([]),
    });
  }

  ngOnInit(): void {
    this.initializeActionsForm();
    
  }

I try to use viewChild in order to get Input property of mat-country-select [Countries] but it does not work. Now i use my predefined array COUNTRIES, that had been manually created. But i need solution, that can easily get a certain country by name without manually created constants

2

Answers


  1. Have you tried using data binding on the mat select?

    Login or Signup to reply.
  2. You can import the countries from country

    After install material-angular/countries

    ng add @angular-material-extensions/select-country
    

    You can in your component

    import {Country,MatSelectCountryComponent,COUNTRIES_DB} 
                          from '@angular-material-extensions/select-country'; 
    
    //or, e.g. if you want the countries in Spanish
    import {Country,MatSelectCountryComponent,COUNTRIES_DB_ES} 
                   from '@angular-material-extensions/select-country'; 
    

    NOTE: If you want to use in your .html you need declare a variable in your .ts

    COUNTRIES=COUNTRIES_DB
    

    Well, when we want to assig to a FormControl a value that it’s not the showed, sometimes we can take the approach of use ngModel

    A simple

    <mat-select-country [ngModel]="form.get('country')?.value"
                        (ngModelChange)="form.get('country')?.setValue($event)"
                        [ngModelOptions]={standalone:true}
    </mat-select-country>
    

    makes the same that a formControl. See that ngModel is the value of the formControl, and when change we makes a setValue

    Well, we want assign to the formControl the whole object. so

    <mat-select-country  [ngModel]="form.get('country')?.value?.name"
                        (ngModelChange)="setValue(form.get('country'),$event)"
                        [ngModelOptions]={standalone:true}
    </mat-select-country>
    
    setValue(control:AbstractControl,countryName:string)
    {
      const country=COUNTRIES.find(x=>x.name==countryName)
      control.setValue(country)  
    }
    

    NOTE: You can use patchValue or setValue to "fill" the formGroup (setValue need all the properties, but patchValue not)

    const country = this.COUNTRIES.find(
      (country) => country.name === player.country,
    );
    this.playerActionsForm.setValue({...player,country:country})
    

    NOTE 2: If only want to asig the countryName to the formControl

    const country = this.COUNTRIES.find(
      (country) => country.name === player.country,
    );
    this.playerActionsFroms.setValue(player)
    this.playerActionsForm.controls.country.setValue(country ? country.name : null);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search