Craig Shearer
Craig Shearer

Reputation: 14531

How to clear the value in an md-select

I'm wanting to have an md-select that the user can clear the selected value. E.g. they select a value but decide they want to clear their selection.

The behavior of md-select is to select the first entry in the options. I'd like to make it return to the state where no selection was made.

I'm imagining I probably need a custom directive for this, so I've implemented a simple directive which listens to the keydown for the DELETE key.

HTML:

<div ng-controller="AppCtrl as ctrl" class="md-padding selectdemoBasicUsage" ng-cloak="" ng-app="MyApp">
  <div>
    <h1 class="md-title">Select a state</h1>
    <span>I want the DELETE key to be able to clear the selected state.</span>
    <div layout="row">

      <md-input-container>
        <label>State</label>
        <md-select ng-model="ctrl.userState" select-clear>
          <md-option ng-repeat="state in ctrl.states" value="{{state.abbrev}}">
            {{state.abbrev}}
          </md-option>
        </md-select>
      </md-input-container>
    </div>
  </div>
</div>

JS:

(function () {
  'use strict';
  angular
      .module('MyApp',['ngMaterial', 'ngMessages'])
      .controller('AppCtrl', function() {
        this.userState = '';
        this.states = ('AL AK AZ AR CA CO CT DE FL GA HI ID IL IN IA KS KY LA ME MD MA MI MN MS ' +
            'MO MT NE NV NH NJ NM NY NC ND OH OK OR PA RI SC SD TN TX UT VT VA WA WV WI ' +
            'WY').split(' ').map(function (state) { return { abbrev: state }; });
      })
  .directive('selectClear', function() {
    return {
        restrict: 'A',
        require: 'ngModel',

        link : function(scope, iElement, iAttrs, ngModelCtrl) {
            iElement.bind('keydown', function(event) {
                if (event.keyCode === 46) {
                    ngModelCtrl.$setViewValue('', event);
                }
            })
        }        
    }    
  });
})();

Here's my code pen:

http://codepen.io/craigsh/pen/GorpVV

But it doesn't work - when the DELETE key is pressed the first options value is selected.

Upvotes: 5

Views: 19664

Answers (7)

Tanya Branagan
Tanya Branagan

Reputation: 571

I'm also late but add a template selection variable in the html:

<button (click)="selectAll(selectField)">Deselect All</button>

 <mat-select #selectField>
   <mat-option
     *ngFor="let option of options | async"
     [value]="option.id">
     {{option.text}}
   </mat-option>
 </mat-select>

and in the ts:

public deselectAll() {
  selectField.value = [];
}

Deselects all checkboxes and resets material select.

Upvotes: 0

Valentin Coudert
Valentin Coudert

Reputation: 1919

I'm late and this might be an evolution in the angular-material lib but there is the possibility of adding the md-option-empty to an md-option to mark it as an equivalent of empty.

<md-option md-option-empty ng-value="undefined">No selection</md-option>

This will be display a "No selection" option in the list, and once selected, will make the input empty (and pass undefined to the ng-model).

Cf doc

Upvotes: 0

Kim T
Kim T

Reputation: 6434

The Angular Material Select demo has a 'State' dropdown which replicates the functionality you need: https://material.angularjs.org/latest/demo/select

The code they use is:

<md-input-container>
    <label>State</label>
    <md-select ng-model="ctrl.userState">
        <md-option><em>None</em></md-option>
        <md-option ng-repeat="state in ctrl.states" ng-value="state.abbrev" ng-disabled="$index === 1">
            {{state.abbrev}}
        </md-option>
    </md-select>
</md-input-container>

Upvotes: 0

Tyrone Wilson
Tyrone Wilson

Reputation: 4628

I made a simple directive to take care of this for me.

angular.module 'app.components'
 .directive 'deleteWhenBlank', ->
   directive =
   restrict: 'A'
   require: ['ngModel']
   scope:
     model: '=ngModel'
   link: ($scope, el, attrs) ->
     $scope.$watch('model', (value) ->
       unless value
         delete $scope.model
     )

I use it like so and it works for the examples shown. As soon as the md-select looses focus the model is set to null.

<md-select ng-model='some.model' delete-when-blank>
    <md-option value=''></md-option>
    <md-option value='{{undefined}}'></md-option>
    <md-option value='{{null}}'></md-option>
</md-select>

Upvotes: 0

Craig Shearer
Craig Shearer

Reputation: 14531

In the end I implemented a directive which works pretty nicely:

  .directive('selectClear', function($parse) {
    return {
        restrict: 'A',
        require: 'ngModel',

        link : function(scope, iElement, iAttrs) {
            iElement.bind('keydown', function(event) {
                if (event.keyCode === 46) {
                  event.preventDefault();
                  event.stopPropagation();

                  scope.$evalAsync(function() {
                    var modelGetter = $parse(iAttrs['ngModel']),
                        modelSetter = modelGetter.assign;
                    modelSetter(scope, '');
                  });
                }
            })
        }        
    }    
  }

Upvotes: 0

alicona
alicona

Reputation: 140

In the Angular-material docs they set the value of your md-select to undefined

 $scope.clearValue = function() {
   $scope.myModel = undefined;
 };

You can check it too in their site https://material.angularjs.org/latest/demo/select see the Validations section

Upvotes: 6

beaver
beaver

Reputation: 17657

I suggest to use a "null" option in addition to the states list:

    <md-select ng-model="ctrl.userState" select-clear>
      <md-option value="{{null}}">
        -- select a state --
      </md-option>
      <md-option ng-repeat="state in ctrl.states" value="{{state.abbrev}}">
        {{state.abbrev}}
      </md-option>
    </md-select>

so the working snippet (adapted from yours) could be:

http://codepen.io/beaver71/pen/LGxqjp

Upvotes: 8

Related Questions