24

I have simple component that contains only form:

import {Component, FORM_DIRECTIVES, NgFor} from 'angular2/angular2';


@Component({
  selector: 'test-component',
  directives: [FORM_DIRECTIVES, NgFor],
  template: `
    <form class="form-inline" (ng-submit)="onSubmit()" #form="form">
      <div class="form-group">
        <select class="form-control" 
          [(ng-model)]="model.server" 
          ng-control="server" 
          #server="form" 
          required>
          <option selected hidden>placeholder</option>
          <option *ng-for="#server of servers" 
            [value]="server">{{ server | uppercase }}
          </option>
        </select>
      </div>
      <div class="form-group">
        <input class="btn btn-primary" type="submit" value="Load"
          [disabled]="!form.form.valid">
      </div>
    </form>
  `
})
export class TestComponent {
  public model: Model = new Model();
  public servers: string[] = ['a', 'b', 'c'];

  onSubmit(): void {
    // Complicated logic.

    // Reset form.
    this.model.reset();
  }
}

class Model {
  constructor(
    public server: string = ''
  ) { }

  reset(): void {
    this.server = '';
  }
}

I want to create "placeholder" for my select, however ng-model overrides selected property which cause no selected option at all. Any sugestions? I am using angular 2.0.0-alpha.48.

developer033
  • 24,267
  • 8
  • 82
  • 108
Eggy
  • 4,052
  • 7
  • 23
  • 39
  • 2
    In your constructor, try `this.model.server = 'placeholder';`. Here's a [Plunker](http://plnkr.co/edit/OBmaSR2Vm9hBrbLv2s95?p=preview). – Mark Rajcok Dec 10 '15 at 18:56

16 Answers16

23

Angular 5 Solution and with Reactive forms!

<option value="null" disabled="true" [selected]="true">Placeholder text..</option>

:)

ismaestro
  • 7,561
  • 8
  • 37
  • 50
22

I got this to work by doing the following:

enter code here

<div class="form-group">
  <label for="metricsType">metrics type</label>
  <select id="metricsType" class="form-control" required [(ngModel)] ="model.metrics.type">
     <option value="" disabled="true" [selected]="!model.metrics.type">--please select--</option>
     <option *ngFor="let item of metricTypes" [value]="item.value">{{item.label}}</option>
  </select>
 </div>

then using css ng-pristine for styling

select {
 border: 1px solid transparent;
  &.ng-pristine{
    font-style: italic;
    color: darken($white, 50%);
  }
}
Thomas Watson
  • 595
  • 4
  • 8
14
<select class="form-control" [(ngModel)]="mySelect">
<option value="-1">Placeholder text..</option>
<!-- forloop of options heres -->
</select>

Then in your component. this.mySelect = -1;

williamsandonz
  • 15,864
  • 23
  • 100
  • 186
  • Voting this as my Accepted Answer. This is the most eloquent solution -- much easier to handle `-1` than differentiate `0` from `null` (etc). – Cody Aug 24 '17 at 22:54
  • 1
    This works with [(ngModel)] in select.A little modification – tej ethical Sep 10 '17 at 01:46
10

this work for me

<option [ngValue]="undefined" hidden selected> please select </option>


my answer is based on this answer and this answer

izik f
  • 2,387
  • 2
  • 16
  • 17
4

This is how we I do it:

<select class="form-control" name="selectedSignierer" #selectedSignierer="ngModel" [(ngModel)]="suisseIdDetail.selectedSigniererBenutzerId" required>
  <option value="null" disabled selected>Select your option</option>
  <option *ngFor="let item of signiererCatalog.entries;" value="{{ item.id }}" >{{ item.value }}</option>
</select>
<div *ngIf="fb.submitted && showSignDefinition === true && !selectedSignierer.valid" class="validation-error">{{ 'ERROR_FIELD_REQUIRED' | translate:lang }}</div>
Marc Thomann
  • 176
  • 1
  • 1
  • 7
4

Below is my solution while using Reactive forms

 <select formControlName="myctrlName">
        <option [disabled]="true" [selected]="true">Select Option</option>
        <option>Option 1</option>
        <option>Option 2</option>
        <option>Option 3</option>
    </select>
rahul
  • 552
  • 6
  • 11
  • Best answer! Worked like a charm. I would like to add, that if you want to show the text "Select option" in the select field without clicking on it, you have to add `value=""`, otherwise it won't show until you click on it. – MikhailRatner Dec 07 '21 at 09:55
3

May be I am somewhat late to this question

As @Thomas Watson answer does not work for angular 4 and upward so this best solution is :

<div class="col-md-4 mb-3">
      <label for="gender">Gender</label>
      <select class="custom-select" name="gender" id="gender" #gender ="ngModel" [(ngModel)]="employee.gender" required>
                <option [ngValue]="null">Select Gender</option>
                <option value="Male">Male</option>
                <option value="Female">Female</option>
       </select>
       <div class="text-danger" *ngIf="gender.invalid && gender.touched">Gender is required</div>
 </div>

Then in the component :

ngOnInit(): void {
    this.employee = new Employee();
    this.employee.gender = null;
}

Note : This also works for required field validation

TanvirArjel
  • 30,049
  • 14
  • 78
  • 114
2

@Thomas's answer above got me almost there, but [selected] is ignored when using [(ngModel)]. @Baconbeastnz's answer can work, but it fails to address form validation.

Here is an answer that I got from piecing together answers from around the internet.

form.html

<select name="stateId" class="state" [(ngModel)]="selectedState.code" required minlength="2">
    <option *ngFor="let state of stateList" [ngValue]="state.code" [disabled]="! state.code">{{state.name}}</option>
</select>

Note: I purposely chose selectedState.code instead of selectedState for form validation purposes.
Note2: I chose to disable the placeholder "State" option. Note2: This may be a hack, but minlength is used for form validation purposes, and checks if the code is a minimum length of 2

stateList.ts

export const STATELIST : US_States[] =[
    {
        "name":"State",
        "code":""
    },
    {
        "name": "Alabama",
        "code": "AL"
    },
    {
        "name": "Alaska",
        "code": "AK"
    }, ...
];

Note: I chose the first entry as the placeholder, as shown below in

form.component.ts

stateList:US_States[] = STATELIST;
public selectedState: US_States = Object.assign({}, this.stateList[0]);

Note: At first, I simply assigned selectedState = this.stateList[0], but what that does is assign by reference, not value. I needed Object.assign to make a copy of the first entry of the stateList value. Otherwise, any selection of other values in the dropdown will perform the operator this.stateList[0] = state.code;

Community
  • 1
  • 1
Jon
  • 7,848
  • 1
  • 40
  • 41
  • Another tip, if you want to hide the option, use the [hidden] property. [disabled] and [hidden] are great ways to make a prompt on a SELECT field. – BillF Sep 26 '16 at 14:44
1

Below is my solution:

export default class AppComponent {
  cityId: number = null
  ...
}

<select #chooceCity="ngModel" class="form-control" name="city [(ngModel)]="cityId" required>
  <option *ngIf="chooceCity.untouched || chooceCity.invalid" value="null" disabled selected>Choose city</option>
  <option *ngFor="let city of cities" [value]="city.id">{{city.name}}</option>
</select>

This code will hide placeholder as soon as correct answer will be selected.

Andrei Belokopytov
  • 1,063
  • 7
  • 17
1
[ngValue]="myObject.myKey"

is what you want.

Stephan Kristyn
  • 15,015
  • 14
  • 88
  • 147
1

I know i'm late , this is how i'm doing ,

initializeSelectOptions(){
 this.optionList = ['..' , '..' , '..'
  ];
 this.optionList.unshift('Select Options')
}

ngOnInit(){
 this.initializeSelectOptions();
}

In my template ,

<select class='select-option' required [(ngModel)]='optionSelected' (ngModelChange)='optionChanged($event)'>
    <option class='option' *ngFor='let option of optionList' [value]="option " [disabled]="option === 'Select Options'">{{option}}</option>
</select>
CruelEngine
  • 2,701
  • 4
  • 23
  • 44
1
<select name="selectName" [ngModel]="someModelObject">
  <option [ngValue]="undefined" disabled hidden>Select item</option>
  <option *ngFor="let item of items" [ngValue]="item">item</option>
</select>

Works for me.

Dzmitry Vasilevsky
  • 1,295
  • 2
  • 14
  • 25
1

This worked for me in Angular 5 using reactive forms, for a dropdown that's a FormControl. The key is:

  • initialise value of the dropdown control to [null] in the TypeScript
  • use [ngValue]="null" on the placeholder option

(or you could use 0 or a negative number instead of null)

.ts

this.myReactiveForm = this.formBuilder.group({
  myDropdown: [null]
})

html

    <form [formGroup]="myReactiveForm ">
      <div class="form-group">
        <select formControlName="myDropdown" class="form-control" (change)="doSomething($event.target.value))">
            // DO THIS:
            <option [ngValue]="null" disabled>Please Select Option</option>
            <option *ngFor="let myItem of myCollection" [value]="myItem.id">{{ myItem.label }}</option>
        </select>
      </div>  
    </form>

From https://netbasal.com/angular-quick-tip-how-to-show-a-placeholder-in-select-control-bab688f98b98

Chris Halcrow
  • 28,994
  • 18
  • 176
  • 206
1
<select class = "form-control"name="searchByRegion" [(ngModel)] = searchByRegion>
    <option [ngValue]="undefined" disabled>searchByRegion</option>
    <option >All</option>
    <option >Asia</option>
    <option >Europe</option>
    <option >Africa</option>
    <option >Australia</option>
</select>

this [ngValue]="undefined" is very important in 2nd line
jasraj
  • 51
  • 2
0

I could not get any of the above answers working for me on Chrome 60.0.3112.113. Mainly, using value="null", or value="" on the placeholder option left the option blank in the select box. In my attempts, the value needed to me the text of the placeholder for it to show up.

component:

import {Component, NgModule, VERSION, OnInit } from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  templateUrl: 'app.html',
  providers: [App]
})
export class App {
  selectPlaceholder = '--select--';
  serverName: string = '';
  servers: Array = [
    {id: 1, name: 'Server 1'},
    {id: 2, name: 'Server 2'},
    {id: 3, name: 'Server 3'}
    ]
  constructor() { }

  ngOnInit() {
    this.serverName = this.selectPlaceholder;
  }

  updateServer(selection) {
    this.serverName = selection;
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule {}

html:

<div class="form-group">
  <label for="name">Server Name</label>
  <select
    (change)="updateServer(selection.value)"
    type="text"
    id="name"
    name="serverName"
    class="form-control"
    #selection>
    <option
      value="{{ selectPlaceholder }}"
      selected="true"
      disabled
      hidden>{{ selectPlaceholder }}</option>
    <option 
      *ngFor="let server of servers"
      value="{{ server.name }}">{{ server.name }}</option>
  </select>
</div>
<button
  class="btn btn-primary"
  [disabled]="serverName === selectPlaceholder">Update Server
</button>

Plunker here: https://plnkr.co/edit/VPj86UTw1X2NK5LLrb8W

The action button is disabled until the selected value is not equal to the default placeholder text value.

*I was getting errors using ngModel (plunker only), so I used a (change) function on the select to update the selected value.

0

This works with Angular 13+, bootstrap 5.2

                        <label class="form-label">Categoría *</label>
                        <select class="form-select" name="categoriaCupon" [(ngModel)]="cupon.categoriaCupon" aria-label="Default select" [required]="true">
                          <option [ngValue]="undefined" hidden selected>Seleccionar</option>
                          <option value="One">One</option>
                          <option value="Two">Two</option>
                          <option value="Three">Three</option>
                        </select>
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Sumit Sharma May 23 '22 at 06:58