Angular ng-options - Is there a way to add an option when the model contains a value not present in the options list?

纵饮孤独 提交于 2020-01-04 14:39:48

问题


When the model, eyeColorUnknown, contains a value that is not present in the options Angular creates an option with a value of "?" and blank for the visual description as shown below.

<select ng-model="eyeColorUnknown"
    ng-options="option.val as (option.desc + ' - ' + option.val) for option in options | orderBy:'desc'"
    class="ng-pristine ng-valid">
    <option value="?"></option>
    <option value="0">Blue - 001</option>
    <option value="1">Brown - 003</option>
    <option value="2">Green - 002</option>
</select>

Is there a way to either:

1) add an option with a value and a description of "value - description" rather than the ?
For example: Unknown - 999 Blue - 001 Brown - 003 Green - 002

2) Keep the option but show either a "Uknown" or "val - Unknown"? For example:

    <option value="?">Unknown</option>
    or
    <option value="?">Unknown - 999</option>

    <option value="0">Blue - 001</option>
    <option value="1">Brown - 003</option>
    <option value="2">Green - 002</option>
</select>

3) Others?

Here is a sample code to help re-create the scenario. The $scope.options are currently static, but will be retrieved using a service which can filter an option out of the set when the expiration date is in the past which can cause this situation to occur. I understand there are some discussion that should occur on the SOA side of the house, but was interested in what possibilities are available in the presentation layer.

<html ng-app="sampleApp">
<head lang="en">
<meta charset="utf-8">
<title>HTML Select Demonstration</title>
<link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.2.0/css/bootstrap.css" />
</head>
<body>
    <div ng-controller="sampleAppCtrl">
        <h1>DEMO of Select and ng-options</h1>
        <p></p>
        <div>
            <select ng-model="eyeColor"
                ng-options="option.val as (option.desc + ' - ' + option.val) for option in options | orderBy:'desc'"></select>
            <span>&nbsp;&nbsp;Value in the model: [{{eyeColor}}]</span>
        </div>
        <div>
            <select ng-model="eyeColorUnknown"
                ng-options="option.val as (option.desc + ' - ' + option.val) for option in options | orderBy:'desc'"></select>
            <span>&nbsp;&nbsp;Value in the model: [{{eyeColorUnknown}}]</span>
        </div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.min.js"></script>
    <script type="text/javascript" src="sample_app.js"></script>

</body>
</html>

sample.js

var app = angular.module('sampleApp', []);

(function()
{
   angular.module('sampleApp').controller('sampleAppCtrl', SampleAppController);

   function SampleAppController($scope)
   {
  $scope.eyeColor = "001";
  $scope.eyeColorUnknown = "999";

  $scope.options = [ {
     "val": "001",
     "desc": "Blue"
  }, {
     "val": "002",
     "desc": "Green"
  }, {
     "val": "003",
     "desc": "Brown"
  } ];
   }
   ;

})();

UPDATE 2015-02-13: The selectDirective provided in angular.js contains a render() method that inserts a '' when the model value doesn't match a value in the options. The angular code excerpt is shown below modified to shown Unknown instead of nothing. I'm looking for suggestions without having to modify the angular.js code. I hope this clarifies my challenge.

      if (!multiple) {
        if (nullOption || modelValue === null) {
          // insert null option if we have a placeholder, or the model is null
          optionGroups[''].unshift({id:'', label:'', selected:!selectedSet});
        } else if (!selectedSet) {
          // option could not be found, we have to insert the undefined item
          // 
          // WARNING: Modified to show 'Unknown' rather than nothing.
          //  
          optionGroups[''].unshift({id:'?', label:'Unknown', selected:true});
        }
      }

Any assistance would be much appreciated.


回答1:


Based on your replies to comments on your question, you want the default option "Unknown - 999" to be added in addition to dynamically retrieved options.

There are 2 ways to do this.

Alternative 1:

If it is critical to satisfy the requirement that option "Unknown - 999" should have value of "999", then you can add this option to the dynamically retrieved options:

$http.get("service/eyeColors").then(function(result){
   $scope.options = result.data;
   $scope.options.unshift({val: "999", desc: "Unknown"});
});

And just use ng-options as usual:

<select ng-model="eyeColor"
        ng-options="o.val as (o.desc + ' - ' + o.val) for 0 in options">
</select>

The problem here is that if $scope.eyeColor equals a value that does not exist in the list or undefined, then <select> will add a blank option, but it will not use the "Unknown - 999" as the default.

Another potential problem is that Unknown - 999 would be sorted together with other options, and would not be first in line.

Alternative 2:

Add a default option of "Unknown - 999" statically, as per Angular's documentation on <select>:

Optionally, a single hard-coded element, with the value set to an empty string, can be nested into the element. This element will then represent the null or "not selected" option. See example below for demonstration.

<select ng-model="eyeColor"
        ng-options="o.val as (o.desc + ' - ' + o.val) for 0 in options">
   <option value="">Unknown - 999</option>
</select>

The problem here is that the default "Unknown - 999" option will set the model to null and not to "999", but the benefit is that any invalid (or not yet set) value of the model would automatically show "Unknown - 999". You can change null to "999" when you need to save the value to the backend.

plunker




回答2:


I'm doing something a bit similar, I think. I'm using this data structure:

"choices": [
    { "name": "-- Select an item --", "value": "" },
    { "name": "1 - text", "value": "1" },
    { "name": "2 - text", "value": "2" },
    { "name": "3 - text", "value": "3" },
    { "name": "4 - text", "value": "4" },
    { "name": "Other", "value": "_ANY_" }
]

"Select an item" will show when there is no option selected. "Other" will show when the value is something other than null or "". If "other" is selected, a text input appears(when that input is "dirty," a submit button appears).
The way I did it is to create a dummy data field that I calculate on the fly. When a user clicks on "other," I set the input field to visible and disable the data submit to the server. I couldn't figure out an override to angular setting an item that's not in the select list to blank. My solution is tied into a number of other processes - I don't have a clear boiled down example. Let me know if you want more info on this.



来源:https://stackoverflow.com/questions/28373770/angular-ng-options-is-there-a-way-to-add-an-option-when-the-model-contains-a-v

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!