Angular 6 select default value not working

Viewed 8391

I have a select dropdown with a default selected disabled value, and a list of districts that is loaded from backend. My issue is that the dropdown never show the selected value, always show blank.

<form [formGroup]="districtForm">
  District:
  <select formControlName="districtControl" (change)="filterBuildings($event.target.value)" [value]='' class="form-control">
    <option value="" disabled selected>Please select district</option>
    <option *ngFor="let district of districts" [ngValue]="district">
      {{district.districtName}}
    </option>
  </select>
  <div *ngIf="errorMessageDistrict" class="text-danger">District is required
  </div>
</form>

Here is my ts code:

import { Component } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { InfoService } from '../../services/info.service';
import { first } from 'rxjs/operators';
import { District } from '../../models/district';
import { FormGroup, FormControl, FormBuilder } from '@angular/forms';

@Component({
  selector: 'app-school-switch',
  templateUrl: './school-switch.component.html',
  styleUrls: ['./school-switch.component.scss']
})
export class SchoolSwitchComponent {
  districts: District[] = [];
  selectedDistrict: District;
  errorMessageDistrict;
  firstDistrict: any;
  districtForm = new FormGroup({
    districtControl: new FormControl()
  });

  constructor(
    public activeModal: NgbActiveModal,
    private infoService: InfoService,
    private fb: FormBuilder
  ) {}

  ngOnInit() {
    this.infoService
      .getDistricts()
      .pipe(first())
      .subscribe(districts => {
        this.districts = districts;
      });
  }

  filterBuildings(filterVal: any) {
      this.selectedDistrict = this.districtForm.value.districtControl;
      //some more code
  }
3 Answers

Generally I create the FormGroup in the ngOnInit and then define default value in it like this :

import { FormGroup, FormBuilder, Validators } from '@angular/forms';

constructor(private formBuilder: FormBuilder){
}

ngOnInit(){
      this.districtForm = this.formBuilder.group({
        districtControl: ['myDefaultValue', Validators.required]
      });
}

Get rid of [value] and instead use [(ngModel)] with selectedDistrict for select in your Template which would be initialized to 'none' in the TypeScript class. Also add [ngValue] to the Placeholder Option. Something like this:

<form [formGroup]="districtForm">
  District:
  <select 
    formControlName="districtControl" 
    [(ngModel)]="selectedDistrict" 
    class="form-control">
    <option 
      [ngValue]="'none'" 
      disabled 
      selected>
      Please select district
    </option>
    <option 
      *ngFor="let district of districts" 
      [ngValue]="district">
      {{district.districtName}}
    </option>
  </select>
  <div 
    *ngIf="errorMessageDistrict" 
    class="text-danger">
    District is required
  </div>
</form>

Here's a Sample StackBlitz for your reference.

Do not assign any default value in Form Control else your Validators.required will be of no use, instead use one default option in select with value = "" without disabled as shown below:

<form [formGroup]="districtForm">
  District:
  <select formControlName="districtControl" class="form-control">
    <option value="">Select District</option>
    <option *ngFor="let district of districts" [value]="district">
      {{district.districtName}}
    </option>
  </select>
  <div *ngIf="errorMessageDistrict" class="text-danger">District is required
  </div>
</form>

Form Control in Component.ts:

import { FormGroup, FormBuilder, Validators } from '@angular/forms';

constructor(private formBuilder: FormBuilder){
}

districtForm: FormGroup;

ngOnInit(){
      this.createDistrictForm();
}

createDistrictForm(){
    this.districtForm = this.formBuilder.group({
        districtControl: ['', Validators.required]
      });
}

Related