67
votes

I have run into an issue in pre-selecting values on a dropdown list in Angular 2.

I set an array of colours in the component which I bind successfully to the dropdown list. The issue I'm experiencing is with pre-selecting a value on page init.

The line [selected]="car.color.id == x.id" should be selecting the value which has been set on the car model this.car.color = new Colour(-1,''); however this only works when I set the car colour id to the last item in the list (in this case black) this.car.color = new Colour(4,'');

I am using the latest version of Angular (rc3) and have experienced the same issues in rc1 and rc2.

Here is a plunker showing the issue.

https://plnkr.co/edit/yIVEeLK7PUY4VQFrR48g?p=preview

Another odd aspect is that when looking at the meta data Angular has set the selected value to true.

enter image description here

But the dropdown still appears empty.

enter image description here

It appears to be a seperate issue from these related questions.

Angular 2 Set begin value of select

Binding select element to object in Angular 2

How to use select/option/NgFor on an array of objects in Angular2

Regards

Steve

Component template

   <div>
        <label>Colour</label>
        <div>
            <select [(ngModel)]="car.colour"">
                <option *ngFor="let x of colours" [value]="x.id" [selected]="car.color.id == x.id">{{x.name}}</option>
            </select>
        </div>
    </div>

Component

import { Component, OnInit } from '@angular/core';
import {AbstractControl,FORM_DIRECTIVES } from '@angular/common';

@Component({
    selector:'dropdown',
    templateUrl:'app/components/dropdown/dropdown.component.html',
    directives:[FORM_DIRECTIVES]
})
export class DropdownComponent implements OnInit
{
    car:Car = new Car();
    colours = Array<Colour>();

    ngOnInit(): void {

        this.colours = Array<Colour>();
        this.colours.push(new Colour(-1, 'Please select'));
        this.colours.push(new Colour(1, 'Green'));
        this.colours.push(new Colour(2, 'Pink'));
        this.colours.push(new Colour(3, 'Orange'));
        this.colours.push(new Colour(4, 'Black'));

        this.car = new Car();
        this.car.color = new Colour(-1,'');        
    }
}

export class Car
{
    color:Colour;
}

export class Colour
{
    constructor(id:number, name:string) {
        this.id=id;
        this.name=name;
    }

    id:number;
    name:string;
}
10

10 Answers

59
votes

Setting car.colour to the value you want to have initially selected usually works.

When car.colour is set, you can remove [selected]="car.color.id == x.id".

If the value is not a string [ngValue]="..." must be used. [value]="..." only supports strings.

21
votes

Angular 2 simple dropdown selected value

It may help someone as I need to only show selected value, don't need to declare something in component and etc.

If your status is coming from the database then you can show selected value this way.

<div class="form-group">
    <label for="status">Status</label>
    <select class="form-control" name="status" [(ngModel)]="category.status">
       <option [value]="1" [selected]="category.status ==1">Active</option>
       <option [value]="0" [selected]="category.status ==0">In Active</option>
    </select>
</div>
16
votes

Thanks for the tip Günter, it got me moving in the right direction. There was a mis-matched spelling of 'color' in my solution which was causing issues and I needed to use 'ngValue' not 'value' in the template html.

Here is the complete solution using objects for the ngModel and select list options and avoiding use of the [selected] attribute.

I have updated the Plunker to show the full working solution. https://plnkr.co/edit/yIVEeLK7PUY4VQFrR48g?p=preview

Component template

 <div>
        <label>Colour</label>
        <div *ngIf="car != null">
            <select [(ngModel)]="car.colour">
                <option *ngFor="let x of colours" [ngValue]="x" >{{x.name}}</option>
            </select>
        </div>
    </div>

Component

import { Component, OnInit } from '@angular/core';
import {AbstractControl,FORM_DIRECTIVES } from '@angular/common';

@Component({
    selector:'dropdown',
    templateUrl:'app/components/dropdown/dropdown.component.html',
    directives:[FORM_DIRECTIVES]
})
export class DropdownComponent implements OnInit
{
    car:Car;
    colours: Array<Colour>;

    ngOnInit(): void {

        this.colours = Array<Colour>();
        this.colours.push(new Colour(-1, 'Please select'));
        this.colours.push(new Colour(1, 'Green'));
        this.colours.push(new Colour(2, 'Pink'));

        this.car = new Car();
        this.car.colour = this.colours[1];        
    }
}

export class Car  
{
    colour:Colour;
}

export class Colour
{
    constructor(id:number, name:string) {
        this.id=id;
        this.name=name;
    }

    id:number;
    name:string;
}
11
votes

This Example solution is for reactive form

 <select formControlName="preferredBankAccountId" class="form-control">
                <option *ngFor="let item of societyAccountDtos" [value]="item.societyAccountId" >
                  {{item.nickName}}
                </option>
              </select>

In the Component:

this.formGroup.patchValue({
        preferredBankAccountId:  object_id_to_be_pre_selected
      });

You can also give this value where you initialize your formGroup or later,depending on your requirement.

You can do this by using [(ngModel)] binding also where you don't have to initialize your formControl.

Example with [(ngModel)] binding

 <select [(ngModel)]="matchedCity" formControlName="city" class="form-control input-sm">
                  <option *ngFor="let city of cities" [ngValue]="city">{{city.cityName}}</option>
                </select>

Here, matchedCity is one of object within cities.

4
votes

This works for me.

<select formControlName="preferredBankAccountId" class="form-control" value="">
    <option value="">Please select</option>    
    <option *ngFor="let item of societyAccountDtos" [value]="item.societyAccountId" >{{item.nickName}}</option>
</select>

Not sure this is valid or not, correct me if it's wrong.
Correct me if this should not be like this.

0
votes

Actually if You use ReactiveForms i found this way much easier to acomplish:

If the form is defined like this:

public formName = new FormGroup({

    fieldName: new FormControl("test") //where "test is field default value"

});

Then thats the way You can change its value:

this.formName.controls.fieldName.setValue("test 2"); //setting field value to "test 2"
0
votes

If your values are coming from the database, show selected values in that way.

<div class="form-group">
    <label for="status">Status</label>
    <select class="form-control" name="status" [(ngModel)]="category.status">
       <option [value]="1" [selected]="category.status ==1">Active</option>
       <option [value]="0" [selected]="category.status ==0">In Active</option>
    </select>
</div>
0
votes

In my case i was returning string value from my api eg: "35" and in my HTML i was using

       <mat-select placeholder="State*" formControlName="states" [(ngModel)]="selectedState" (ngModelChange)="getDistricts()">
            <mat-option *ngFor="let state of formInputs.states" [value]="state.stateId">
              {{ state.stateName }}
            </mat-option>
          </mat-select>

Like others mentioned in the comment value will only accept integer values i guess. So what I did is I converted my string value to integer in my component class like below

          var x = user.state;
          var y: number = +x;

and then assigned it like

  this.EditProfileForm.get('states').setValue(y);

Now the correct values is getting setting by default.

-1
votes

I would like to add, [ngValue]="..." support strings, but you need to add simple quotes if it represents a number, like [ngValue]="'...'". It was to complement the Günter Zöchbauer answer.

-1
votes
 <div class="col-md-3 col-sm-3">
                        <label>Outlet Ready</label>
                            <div>
                                <select class="form-control"  
                                     [(ngModel)]="selectedColor">
                               <option *ngFor="let x of colours" [ngValue]="x" >{{x.name}}</option>
                                </select>
                            </div>    
                    </div>

Compoent.ts

import { Component, OnInit } from '@angular/core';
import {AbstractControl,FORM_DIRECTIVES } from '@angular/common';

@Component({
selector:'dropdown',
 templateUrl:'app/components/dropdown/dropdown.component.html',
directives:[FORM_DIRECTIVES]
})
export class DropdownComponent implements OnInit
 {
  car:Car;
   colours: Array<Colour>;

 ngOnInit(): void {

    this.colours = Array<Colour>();
    this.colours.push(new Colour(-1, 'Please select'));
    this.colours.push(new Colour(1, 'Green'));
    this.colours.push(new Colour(2, 'Pink'));

    this.car = new Car();
    this.car.colour = this.colours[1];        
  }
}

 export class Car  
{
  colour:Colour;
}

 export class Colour
{
   constructor(id:number, name:string) {
    this.id=id;
    this.name=name;
  }

   id:number;
  name:string;

this is working fine...:)