@@ -19,10 +19,120 @@ function setOptionSelectedStatus(optionEl, value) {
19
19
/**
20
20
* @ngdoc type
21
21
* @name select.SelectController
22
+ *
22
23
* @description
23
- * The controller for the `<select>` directive. This provides support for reading
24
- * and writing the selected value(s) of the control and also coordinates dynamically
25
- * added `<option>` elements, perhaps by an `ngRepeat` directive.
24
+ * The controller for the {@link ng.select select} directive. The controller exposes
25
+ * a few utility methods that can be used to augment the behavior of a regular or an
26
+ * {@link ng.ngOptions ngOptions} select element.
27
+ *
28
+ * @example
29
+ * ### Set a custom error when the unknown option is selected
30
+ *
31
+ * This example sets a custom error "unknownValue" on the ngModelController
32
+ * when the select element's unknown option is selected, i.e. when the model is set to a value
33
+ * that is not matched by any option.
34
+ *
35
+ * <example name="select-unknown-value-error" module="staticSelect">
36
+ * <file name="index.html">
37
+ * <div ng-controller="ExampleController">
38
+ * <form name="myForm">
39
+ * <label for="testSelect"> Single select: </label><br>
40
+ * <select name="testSelect" ng-model="selected" unknown-value-error>
41
+ * <option value="option-1">Option 1</option>
42
+ * <option value="option-2">Option 2</option>
43
+ * </select><br>
44
+ * <span ng-if="myForm.testSelect.$error.unknownValue">Error: The current model doesn't match any option</span>
45
+ *
46
+ * <button ng-click="forceUnknownOption()">Force unknown option</button><br>
47
+ * </form>
48
+ * </div>
49
+ * </file>
50
+ * <file name="app.js">
51
+ * angular.module('staticSelect', [])
52
+ * .controller('ExampleController', ['$scope', function($scope) {
53
+ * $scope.selected = null;
54
+ *
55
+ * $scope.forceUnknownOption = function() {
56
+ * $scope.selected = 'nonsense';
57
+ * };
58
+ * }])
59
+ * .directive('unknownValueError', function() {
60
+ * return {
61
+ * require: ['ngModel', 'select'],
62
+ * link: function(scope, element, attrs, ctrls) {
63
+ * var ngModelCtrl = ctrls[0];
64
+ * var selectCtrl = ctrls[1];
65
+ *
66
+ * ngModelCtrl.$validators.unknownValue = function(modelValue, viewValue) {
67
+ * if (selectCtrl.$isUnknownOptionSelected()) {
68
+ * return false;
69
+ * }
70
+ *
71
+ * return true;
72
+ * };
73
+ * }
74
+ *
75
+ * };
76
+ * });
77
+ * </file>
78
+ *</example>
79
+ *
80
+ *
81
+ * @example
82
+ * ### Set the "required" error when the unknown option is selected.
83
+ *
84
+ * By default, the "required" error on the ngModelController is only set on a required select
85
+ * when the empty option is selected. This example adds a custom directive that also sets the
86
+ * error when the unknown option is selected.
87
+ *
88
+ * <example name="select-unknown-value-required" module="staticSelect">
89
+ * <file name="index.html">
90
+ * <div ng-controller="ExampleController">
91
+ * <form name="myForm">
92
+ * <label for="testSelect"> Select: </label><br>
93
+ * <select name="testSelect" ng-model="selected" unknown-value-required>
94
+ * <option value="option-1">Option 1</option>
95
+ * <option value="option-2">Option 2</option>
96
+ * </select><br>
97
+ * <span ng-if="myForm.testSelect.$error.required">Error: Please select a value</span><br>
98
+ *
99
+ * <button ng-click="forceUnknownOption()">Force unknown option</button><br>
100
+ * </form>
101
+ * </div>
102
+ * </file>
103
+ * <file name="app.js">
104
+ * angular.module('staticSelect', [])
105
+ * .controller('ExampleController', ['$scope', function($scope) {
106
+ * $scope.selected = null;
107
+ *
108
+ * $scope.forceUnknownOption = function() {
109
+ * $scope.selected = 'nonsense';
110
+ * };
111
+ * }])
112
+ * .directive('unknownValueRequired', function() {
113
+ * return {
114
+ * priority: 1, // This directive must run after the required directive has added its validator
115
+ * require: ['ngModel', 'select'],
116
+ * link: function(scope, element, attrs, ctrls) {
117
+ * var ngModelCtrl = ctrls[0];
118
+ * var selectCtrl = ctrls[1];
119
+ *
120
+ * var originalRequiredValidator = ngModelCtrl.$validators.required;
121
+ *
122
+ * ngModelCtrl.$validators.required = function() {
123
+ * if (attrs.required && selectCtrl.$isUnknownOptionSelected()) {
124
+ * return false;
125
+ * }
126
+ *
127
+ * return originalRequiredValidator.apply(this, arguments);
128
+ * };
129
+ * }
130
+ * };
131
+ * });
132
+ * </file>
133
+ *</example>
134
+ *
135
+ *
26
136
*/
27
137
var SelectController =
28
138
[ '$element' , '$scope' , /** @this */ function ( $element , $scope ) {
@@ -172,6 +282,49 @@ var SelectController =
172
282
return ! ! optionsMap . get ( value ) ;
173
283
} ;
174
284
285
+ /**
286
+ * @ngdoc method
287
+ * @name select.SelectController#$hasEmptyOption
288
+ *
289
+ * @description
290
+ *
291
+ * Returns `true` if the select element currently has an empty option
292
+ * element, i.e. an option that signifies that the select is empty / the selection is null.
293
+ *
294
+ */
295
+ self . $hasEmptyOption = function ( ) {
296
+ return self . hasEmptyOption ;
297
+ } ;
298
+
299
+ /**
300
+ * @ngdoc method
301
+ * @name select.SelectController#$isUnknownOptionSelected
302
+ *
303
+ * @description
304
+ *
305
+ * Returns `true` if the select element's unknown option is selected. The unknown option is added
306
+ * and automatically selected whenever the select model doesn't match any option.
307
+ *
308
+ */
309
+ self . $isUnknownOptionSelected = function ( ) {
310
+ // Presence of the unknown option means it is selected
311
+ return $element [ 0 ] . options [ 0 ] === self . unknownOption [ 0 ] ;
312
+ } ;
313
+
314
+ /**
315
+ * @ngdoc method
316
+ * @name select.SelectController#$isEmptyOptionSelected
317
+ *
318
+ * @description
319
+ *
320
+ * Returns `true` if the select element has an empty option and this empty option is currently
321
+ * selected. Returns `false` if the select element has no empty option or it is not selected.
322
+ *
323
+ */
324
+ self . $isEmptyOptionSelected = function ( ) {
325
+ return self . hasEmptyOption && $element [ 0 ] . options [ $element [ 0 ] . selectedIndex ] === self . emptyOption [ 0 ] ;
326
+ } ;
327
+
175
328
self . selectUnknownOrEmptyOption = function ( value ) {
176
329
if ( value == null && self . emptyOption ) {
177
330
self . removeUnknownOption ( ) ;
@@ -330,6 +483,9 @@ var SelectController =
330
483
* the content of the `value` attribute or the textContent of the `<option>`, if the value attribute is missing.
331
484
* Value and textContent can be interpolated.
332
485
*
486
+ * The {@link select.selectController select controller} exposes utility functions that can be used
487
+ * to manipulate the select's behavior.
488
+ *
333
489
* ## Matching model and option values
334
490
*
335
491
* In general, the match between the model and an option is evaluated by strictly comparing the model
0 commit comments