How do I add an unselectable and customizable placeholder to a select box

14,435

Solution 1

We can do this easy by using angular's powerful directive system to extend basic html.

app.directive('select', function($interpolate) {
  return {
    restrict: 'E',
    require: 'ngModel',
    link: function(scope, elem, attrs, ctrl) {
      var defaultOptionTemplate;
      scope.defaultOptionText = attrs.defaultOption || 'Select...';
      defaultOptionTemplate = '<option value="" disabled selected style="display: none;">{{defaultOptionText}}</option>';
      elem.prepend($interpolate(defaultOptionTemplate)(scope));
    }
  };
});

With this, we can now do the following:

<select ng-model="number" 
    ng-options="item.id as item.label for item in values">
</select>

This will create a select box with an unselectable placeholder that says "Select..."

If we want a custom placeholder we can simply do this:

<select ng-model="dog" 
    ng-options="dog.id as dog.label for dog in dogs" 
    default-option="What's your favorite dog?">
</select>

This will create a select box with an unselectable placeholder that says "What's your favorite dog?"

Plunker Example (in coffeescript): http://plnkr.co/edit/zIs0W7AdYnHnuV21UbwK

Plunker Example (in javascript): http://plnkr.co/edit/6VNJ8GUWK50etjUAFfey

Solution 2

You can also do it directly in the html.

<select   ng-model="number"
          ng-options="item.id as item.label for item in values">
          <option value="" disabled selected style="display: none;"> Default Number </option>
></select>
Share:
14,435

Related videos on Youtube

codevinsky
Author by

codevinsky

Updated on September 15, 2022

Comments

  • codevinsky
    codevinsky almost 2 years

    I've got a pretty large app that has many dropdowns. I don't want to have to modify my data to add a blank option and I don't want the placeholder to be selectable. What's the best approach?

  • Mathew Berg
    Mathew Berg over 10 years
    This will not work if default-option is dynamic: plnkr.co/edit/SNMYtCcjTY5OVYup5TxX?p=preview
  • Mathew Berg
    Mathew Berg over 10 years
    No.... it doesn't: plnkr.co/edit/q4Kbymxgw3vY6dcXQW1b?p=preview If defaultOption gets set at a later time then the element will not render the updated option. In my example defaultOption gets set to "TEXT SHOULD BE THIS" but you never see it update because you've already created it.
  • Mathew Berg
    Mathew Berg over 10 years
    Also, did you look at my plunkr? You'll see that the localize filter is not firing
  • codevinsky
    codevinsky over 10 years
    A few things here: 1. Your directive isn't firing because your directive is wrong. It should be a filter. 2. If you look at the select over-ride directive, you'll notice that the defaultOption is being set based on an attribute, not a scoped value. Because of this, it has to be a string. However, because angular is so awesome, you can use an expression there like so: plnkr.co/edit/aWUA2lXEeFqhCmZIdr1d
  • Mathew Berg
    Mathew Berg over 10 years
    As mentioned, look at the latest plunker, if you update the value after the directive is rendered, nothing is changing. Specifically look at the part in the setTimeout.
  • Mathew Berg
    Mathew Berg over 10 years
    Here's my suggestion on a good place to start: plnkr.co/edit/p5bv4jyEpABgKUtVhqOS?p=preview
  • adriendenat
    adriendenat about 10 years
    This doesn't work anymore since Angular 1.2.16. The first option is selected as default.
  • Xinan
    Xinan almost 8 years
    this is the most elegant way I've ever seen