127

In Angular 1 I could select the default option for a drop down box using the following:

<select 
    data-ng-model="carSelection"
    data-ng-options = "x.make for x in cars" data-ng-selected="$first">
</select>

In Angular 2 I have:

<select class="form-control" [(ngModel)]="selectedWorkout" (ngModelChange)="updateWorkout($event)">
    <option *ngFor="#workout of workouts">{{workout.name}}</option>
</select>

How could I select a default option given my option data is:

[{name: 'arm'}, {name: 'back'}, {name:'leg'}] and my value I to default on on is back?

shytikov
  • 9,155
  • 8
  • 56
  • 103
ClickThisNick
  • 5,110
  • 9
  • 44
  • 69

22 Answers22

89

Add a binding to the selected property, like this:

<option *ngFor="#workout of workouts" 
    [selected]="workout.name == 'back'">{{workout.name}}</option>
StepUp
  • 36,391
  • 15
  • 88
  • 148
Douglas
  • 5,017
  • 1
  • 14
  • 28
  • 7
    That doesn't appear to work, looking at my selected option it does not have any sort of selected indication – ClickThisNick Mar 14 '16 at 03:59
  • @ClickThisNick It worked when I tested it. See [this plnkr](https://plnkr.co/edit/vBqCr05sSeL3FWO8SJ1z?p=preview). When it finishes loading, the select dropdown shows "two" even though the normal default would be the first element ("one"). – Douglas Mar 14 '16 at 04:08
  • 2
    The difference with the code in the @Douglas plnr is that is does not have a `[(ngModel)]` binding therefore it listens to the `[selected]` binding in the plnkr and not in the OP's coden (see my answer for a link to a forked plnr that explains this effect) – Matthijs Apr 20 '16 at 09:00
  • 3
    Dynamic Forms use: `selected="workout.name == 'back'"` Reactive Forms use: `[selected]=workout.name == 'back'` – fidev Aug 07 '17 at 14:53
  • @fidev, you have a great answer, and it was exactly what I was looking for. Just have a look that your Reactive forms example are missing the `"`. I used your code with another variable like this `[selected]="workout.name == exercise.name"` – Alfa Bravo Sep 18 '17 at 09:41
52

If you assign the default value to selectedWorkout and use [ngValue] (which allows to use objects as value - otherwise only string is supported) then it should just do what you want:

<select class="form-control" name="sel" 
    [(ngModel)]="selectedWorkout" 
    (ngModelChange)="updateWorkout($event)">
  <option *ngFor="let workout of workouts" [ngValue]="workout">
    {{workout.name}}
  </option>
</select>

Ensure that the value you assign to selectedWorkout is the same instance than the one used in workouts. Another object instance even with the same properties and values won't be recognized. Only object identity is checked.

update

Angular added support for compareWith, that makes it easier to set the default value when [ngValue] is used (for object values)

From the docs https://angular.io/api/forms/SelectControlValueAccessor

<select [compareWith]="compareFn"  [(ngModel)]="selectedCountries">
    <option *ngFor="let country of countries" [ngValue]="country">
        {{country.name}}
    </option>
</select>
compareFn(c1: Country, c2: Country): boolean {
    return c1 && c2 ? c1.id === c2.id : c1 === c2;
}

This way a different (new) object instance can be set as default value and compareFn is used to figure out if they should be considered equal (for example if the id property is the same.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
38

Add this Code at o position of the select list.

<option [ngValue]="undefined" selected>Select</option>

Mahesh
  • 381
  • 3
  • 2
35

just set the value of the model to the default you want like this:

selectedWorkout = 'back'

I created a fork of @Douglas' plnkr here to demonstrate the various ways to get the desired behavior in angular2.

Matthijs
  • 1,484
  • 1
  • 14
  • 13
  • 1
    for this to work for me(in angular 4) I also had to set [ngValue]="val". My itemssource was not an array of objects though but just an array of strings. `` – S. Robijns Apr 11 '17 at 11:29
21

You Can approach this way:

<option *ngFor="let workout of workouts" [value]="workout.name">{{workout.name}}</option>

or this way:

  <option *ngFor="let workout of workouts" [attr.value]="workout.name" [attr.selected]="workout.name == 'leg' ? true : null">{{workout.name}}</option>

or you can set default value this way:

<option [value]="null">Please Select</option>
<option *ngFor="let workout of workouts" [value]="workout.name">{{workout.name}}</option>

or

<option [value]="0">Please Select</option>
<option *ngFor="let workout of workouts" [value]="workout.name">{{workout.name}}</option>
Nadim Hossain Sonet
  • 1,630
  • 1
  • 16
  • 23
Anil Samal
  • 1,343
  • 1
  • 13
  • 30
14

Use index to show the first value as default

<option *ngFor="let workout of workouts; #i = index" [selected]="i == 0">{{workout.name}}</option>
Sajith Mantharath
  • 2,297
  • 2
  • 17
  • 19
6

According to https://angular.io/api/forms/SelectControlValueAccessor you just need the following:

theView.html:

<select [compareWith]="compareFn"  [(ngModel)]="selectedCountries">
    <option *ngFor="let country of countries" [ngValue]="country">
        {{country.name}}
    </option>
</select>

theComponent.ts

import { SelectControlValueAccessor } from '@angular/forms';
    compareFn(c1: Country, c2: Country): boolean {
    return c1 && c2 ? c1.id === c2.id : c1 === c2;
}
IKavanagh
  • 6,089
  • 11
  • 42
  • 47
azatprog
  • 304
  • 2
  • 4
4

Struggled a bit with this one, but ended up with the following solution... maybe it will help someone.

HTML template:

<select (change)="onValueChanged($event.target)">
    <option *ngFor="let option of uifOptions" [value]="option.value" [selected]="option == uifSelected ? true : false">{{option.text}}</option>
</select>

Component:

import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';    
export class UifDropdownComponent implements OnInit {
    @Input() uifOptions: {value: string, text: string}[];
    @Input() uifSelectedValue: string = '';
    @Output() uifSelectedValueChange:EventEmitter<string> = new EventEmitter<string>();
    uifSelected: {value: string, text: string} = {'value':'', 'text':''};

    constructor() { }

    onValueChanged(target: HTMLSelectElement):void {
        this.uifSelectedValue = target.value;
        this.uifSelectedValueChange.emit(this.uifSelectedValue);
    }

    ngOnInit() {
        this.uifSelected = this.uifOptions.filter(o => o.value == 
        this.uifSelectedValue)[0];
    }
}
sevenam
  • 592
  • 1
  • 8
  • 21
3

Fully fleshing out other posts, here is what works in Angular2 quickstart,

To set the DOM default: along with *ngFor, use a conditional statement in the <option>'s selected attribute.

To set the Control's default: use its constructor argument. Otherwise before an onchange when the user re-selects an option, which sets the control's value with the selected option's value attribute, the control value will be null.

script:

import {ControlGroup,Control} from '@angular/common';
...
export class MyComponent{
  myForm: ControlGroup;
  myArray: Array<Object> = [obj1,obj2,obj3];
  myDefault: Object = myArray[1]; //or obj2

  ngOnInit(){ //override
    this.myForm = new ControlGroup({'myDropdown': new Control(this.myDefault)});
  }
  myOnSubmit(){
    console.log(this.myForm.value.myDropdown); //returns the control's value 
  }
}

markup:

<form [ngFormModel]="myForm" (ngSubmit)="myOnSubmit()">
  <select ngControl="myDropdown">
    <option *ngFor="let eachObj of myArray" selected="eachObj==={{myDefault}}"
            value="{{eachObj}}">{{eachObj.myText}}</option>
  </select>
  <br>
  <button type="submit">Save</button>
</form>
Michelle Norris
  • 568
  • 7
  • 14
3

You can Use that [ngModel] instead of [(ngModel)]and it is Ok

<select class="form-control" **[ngModel]="selectedWorkout"** (ngModelChange)="updateWorkout($event)">
   <option *ngFor="#workout of workouts">{{workout.name}}</option>
</select>
Saeed
  • 3,415
  • 3
  • 24
  • 41
3

You can do as above:

<select class="form-control" 
        [(ngModel)]="selectedWorkout" 
        (ngModelChange)="updateWorkout($event)">
    <option *ngFor="#workout of workouts;
                    let itemIndex = index"
            [attr.selected]="itemIndex == 0">
    {{workout.name}}
    </option>
</select>

In above code as you can see, selected attribute of the repeating option is set on checking index of the repeating loop of list. [attr.< html attribute name >] is used for setting html attribute in angular2.

Another approach will be setting model value in typescript file as :

this.selectedWorkout = this.workouts.length > 0
                       ? this.workouts[0].name
                       : 'No data found';//'arm'
Pranav Labhe
  • 1,943
  • 1
  • 19
  • 24
1

Add on to @Matthijs 's answer, please make sure your select element has a name attribute and its name is unique in your html template. Angular 2 is using input name to update changes. Thus, if there are duplicated names or there is no name attached to input element, the binding will fail.

Wei Xu
  • 1,629
  • 2
  • 19
  • 31
1

I faced the same problem while using angular 11. But finally found a solution.

  <option disabled selected value="undefined">Select an Option</option>

complete example with ngFor.

<select name="types" id="types" [(ngModel)]="model.type" #type="ngModel">
  <option class="" disabled selected value="undefined">Select an Option</option>
  <option *ngFor="let item of course_types; let x = index" [ngValue]="type.id">
    {{ item.name }} </option>
</select>
Mohammad Ayoub Khan
  • 2,422
  • 19
  • 24
0

Add binding property selected, but make sure to make it null, for other fields e.g:

<option *ngFor="#workout of workouts" [selected]="workout.name =='back' ? true: null">{{workout.name}}</option>

Now it will work

Jcoder
  • 30
  • 5
0
<select class="form-control" name='someting' [ngModel]="selectedWorkout" (ngModelChange)="updateWorkout($event)">
    <option value="{{workout.name}}" *ngFor="#workout of workouts">{{workout.name}}</option>
</select>

If you are using form there should be name field inside select tag.

All you need to do is just add value to the option tag.

selectedWorkout value should be "back" , and its done.

Vivek Doshi
  • 56,649
  • 12
  • 110
  • 122
0

If you don't want the 2-way binding via [(ngModel)], do this:

<select (change)="selectedAccountName = $event.target.value">
  <option *ngFor="let acct of accountsList" [ngValue]="acct">{{ acct.name }}</option>
</select>

Just tested on my project on Angular 4 and it works! The accountsList is an array of Account objects in which name is a property of Account.

Interesting observation:
[ngValue]="acct" exerts the same result as [ngValue]="acct.name".
Don't know how Angular 4 accomplish it!

Daniel C. Deng
  • 1,573
  • 13
  • 8
0

Step: 1 Create Properties declare class

export class Task {
    title: string;
    priority: Array<any>;
    comment: string;

    constructor() {
        this.title      = '';
        this.priority   = [];
        this.comment    = '';
     }
}

Stem: 2 Your Component Class

import { Task } from './task';

export class TaskComponent implements OnInit {
  priorityList: Array<any> = [
    { value: 0, label: '✪' },
    { value: 1, label: '★' },
    { value: 2, label: '★★' },
    { value: 3, label: '★★★' },
    { value: 4, label: '★★★★' },
    { value: 5, label: '★★★★★' }
  ];
  taskModel: Task           = new Task();

  constructor(private taskService: TaskService) { }
  ngOnInit() {
    this.taskModel.priority     = [3]; // index number
  }
}

Step: 3 View File .html

<select class="form-control" name="priority" [(ngModel)]="taskModel.priority"  required>
    <option *ngFor="let list of priorityList" [value]="list.value">
      {{list.label}}
    </option>
</select>

Output:

enter image description here

Ram Pukar
  • 1,583
  • 15
  • 17
0

You just need to put the ngModel and the value you want selected:

<select id="typeUser" ngModel="Advanced" name="typeUser">
  <option>Basic</option>
  <option>Advanced</option>
  <option>Pro</option>
</select>
0

For me, I define some properties:

disabledFirstOption = true;

get isIEOrEdge(): boolean {
    return /msie\s|trident\/|edge\//i.test(window.navigator.userAgent)
}

Then in the constructor and ngOnInit

constructor() {
    this.disabledFirstOption = false;
}

ngOnInit() {
    setTimeout(() => {
        this.disabledFirstOption = true;
    });
}

And in the template I add this as the first option inside the select element

<option *ngIf="isIEOrEdge" [value]="undefined" [disabled]="disabledFirstOption" selected></option>

If you allow to select the first option you can just remove the usage of the property disabledFirstOption

Tinh Dang
  • 448
  • 4
  • 11
0

In my case, here this.selectedtestSubmitResultView is set with default value based on conditions and an variable testSubmitResultView must be one and same as testSubmitResultView. This indeed worked for me

<select class="form-control" name="testSubmitResultView"  [(ngModel)]="selectedtestSubmitResultView" (ngModelChange)="updatetestSubmitResultView($event)">
    <option *ngFor="let testSubmitResultView of testSubmitResultViewArry" [ngValue]="testSubmitResultView" >
        {{testSubmitResultView.testSubmitResultViewName}}
    </option>
</select>

For More Information,

testSubmitResultViewArry: Array<any> = [];
selectedtestSubmitResultView: string;
    
getTestSubmitResultViewList() {
    try {
        this.examService.getTestSubmitResultViewDetails().subscribe(response => {
            if (response != null && response !== undefined && response.length > 0) {
                response.forEach(x => {
                    if (x.isDeleted === false) {
                        this.testSubmitResultViewArry.push(x);
                    }
                    if (x.isDefault === true) {
                        this.selectedtestSubmitResultView = x;
                    }
                })
            }
        });
    } catch (ex) {
        console.log('Method: getTestSubmitResultViewList' + ex.message);
    }
}
Nɪsʜᴀɴᴛʜ ॐ
  • 2,756
  • 4
  • 33
  • 57
-1

I faced this Issue before and I fixed it with vary simple workaround way

For your Component.html

      <select class="form-control" ngValue="op1" (change)="gotit($event.target.value)">

      <option *ngFor="let workout of workouts" value="{{workout.name}}" name="op1" >{{workout.name}}</option>

     </select>

Then in your component.ts you can detect the selected option by

gotit(name:string) {
//Use it from hare 
console.log(name);
}
Ramy hakam
  • 522
  • 1
  • 6
  • 19
-1

works great as seen below:

<select class="form-control" id="selectTipoDocumento" formControlName="tipoDocumento" [compareWith]="equals"
          [class.is-valid]="this.docForm.controls['tipoDocumento'].valid &&
           (this.docForm.controls['tipoDocumento'].touched ||  this.docForm.controls['tipoDocumento'].dirty)"
          [class.is-invalid]="!this.docForm.controls['tipoDocumento'].valid &&
           (this.docForm.controls['tipoDocumento'].touched ||  this.docForm.controls['tipoDocumento'].dirty)">
            <option value="">Selecione um tipo</option>
            <option *ngFor="let tipo of tiposDocumento" [ngValue]="tipo">{{tipo?.nome}}</option>
          </select>