1

I've got some dynamically generated values in select:

<select ng-model="selectedValue" ng-options="o.id as o.name for o in values"></select>

And I have selectedValue that holds the selected value. I want it to be updated to null or undefined when the selectedValue is no longer present in values.

I can clear the selectedValue in $scope.$watch(values) but is there a better solution?

Basically this situation in this plunker is what I want to avoid:

This is what I want to avoid

I want it to be "Selected value: null" or something similar.

2 Answers 2

2

You can create a directive that will make the select behave in the way that you'd like. The HTML would then change to:

<select clearable ng-model="selectedValue" ng-options="o.id as o.name for o in values"></select>

The JS for the directive would be:

app.directive('clearable', ['$parse',function($parse){
  return {
    restrict : 'A',
    scope : {
      'ngModel' : '=',
      'ngOptions' : '@'
    },
    require: ['select','?ngModel'],
    link : function(scope, elem, attr,ctrl){

      // Regex copied from the Angular Source
      var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
      var match = scope.ngOptions.match(NG_OPTIONS_REGEXP);

      var valuesFn = $parse(match[7]),    //Options list
          key = match[1].split('.')[1];   //Property in options list

      scope.$watch(
        function(){
          // Watch for when the options list changes
          return valuesFn(scope.$parent);
        }, 
        function(newList){
          var isFound, i,
              currentModelVal = scope.ngModel;

          // Iterate through the new list to see if the current value is present
          for(i=0;i<newList.length;i++){
            if (newList[i][key] === currentModelVal){
              isFound = true;
              break;
            }
          }

          // If not found, reset the ng-model value to null
          if (!isFound){
            ctrl[1].$setViewValue(null);
          }
        }
      );

    }
  }  
}]);

See the Plunker at http://plnkr.co/edit/yAk9YSoMf88rtTqLXTiI?p=preview

Sign up to request clarification or add additional context in comments.

Comments

0

You can use an option with empty value, and model will be set to empty when no item is selected

check this

<option value="">--select--</option>    

http://plnkr.co/edit/66KN7ae0q2v3IUnw47lx?p=preview

3 Comments

When the selectedValue is not in the values the variable $scope.selectedValue should be cleared/nulled. Your solution is good for showing not selected value but that's not what I want.
In that case, Why cant you check the value exist in array, inside the function randomize()? Is there any other requirement?
I can do it like that and I'm doing it like that right now. But I'd like to have some better (maybe angular out-of-box) solution because my real world "randomize()" function shouldn't be dependent on the selectedValue. Thank you for your participation!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.