5
5
6
6
/***************************************************
7
7
8
- ### TODO - POST RC1 ###
8
+ ### TODO ###
9
9
- [ ] Abstract placement logic in $mdSelect service to $mdMenu service
10
10
11
11
***************************************************/
@@ -32,43 +32,16 @@ angular.module('material.components.select', [
32
32
* @restrict E
33
33
* @module material.components.select
34
34
*
35
- * @description Displays a select box, bound to an ng-model.
35
+ * @description Displays a select box, bound to an `ng-model`. Selectable options are defined using
36
+ * the <a ng-href="/api/directive/mdOption">md-option</a> element directive. Options can be grouped
37
+ * using the <a ng-href="/api/directive/mdOptgroup">md-optgroup</a> element directive.
36
38
*
37
39
* When the select is required and uses a floating label, then the label will automatically contain
38
40
* an asterisk (`*`). This behavior can be disabled by using the `md-no-asterisk` attribute.
39
41
*
40
42
* By default, the select will display with an underline to match other form elements. This can be
41
43
* disabled by applying the `md-no-underline` CSS class.
42
44
*
43
- * ### Option Params
44
- *
45
- * When applied, `md-option-empty` will mark the option as "empty" allowing the option to clear the
46
- * select and put it back in it's default state. You may supply this attribute on any option you
47
- * wish, however, it is automatically applied to an option whose `value` or `ng-value` are not
48
- * defined.
49
- *
50
- * **Automatically Applied**
51
- *
52
- * - `<md-option>`
53
- * - `<md-option value>`
54
- * - `<md-option value="">`
55
- * - `<md-option ng-value>`
56
- * - `<md-option ng-value="">`
57
- *
58
- * **NOT Automatically Applied**
59
- *
60
- * - `<md-option ng-value="1">`
61
- * - `<md-option ng-value="''">`
62
- * - `<md-option ng-value="undefined">`
63
- * - `<md-option value="undefined">` (this evaluates to the string `"undefined"`)
64
- * - <code ng-non-bindable><md-option ng-value="{{someValueThatMightBeUndefined}}"></code>
65
- *
66
- * **Note:** A value of `undefined` ***is considered a valid value*** (and does not auto-apply this
67
- * attribute) since you may wish this to be your "Not Available" or "None" option.
68
- *
69
- * **Note:** Using the `value` attribute (as opposed to `ng-value`) always evaluates to a string, so
70
- * `value="null"` will require the test `ng-if="myValue != 'null'"` rather than `ng-if="!myValue"`.
71
- *
72
45
* @param {expression } ng-model Assignable angular expression to data-bind to.
73
46
* @param {expression= } ng-change Expression to be executed when the model value changes.
74
47
* @param {boolean= } multiple When present, allows for more than one option to be selected.
@@ -115,15 +88,12 @@ angular.module('material.components.select', [
115
88
* </md-input-container>
116
89
* </hljs>
117
90
*
118
- * With a select-header
119
- *
120
- * When a developer needs to put more than just a text label in the
121
- * md-select-menu, they should use the md-select-header.
122
- * The user can put custom HTML inside of the header and style it to their liking.
123
- * One common use case of this would be a sticky search bar.
91
+ * Using the `md-select-header` element directive
124
92
*
125
- * When using the md-select-header the labels that would previously be added to the
126
- * OptGroupDirective are ignored.
93
+ * When a developer needs to put more than just a text label in the `md-select-menu`, they should
94
+ * use one or more `md-select-header`s. These elements can contain custom HTML which can be styled
95
+ * as desired. Use cases for this element include a sticky search bar and custom option group
96
+ * labels.
127
97
*
128
98
* <hljs lang="html">
129
99
* <md-input-container>
@@ -157,22 +127,25 @@ angular.module('material.components.select', [
157
127
* </div>
158
128
* </hljs>
159
129
*
160
- * At first one might expect that the select should be populated with "Bob" as the selected user. However,
161
- * this is not true. To determine whether something is selected,
130
+ * At first one might expect that the select should be populated with "Bob" as the selected user.
131
+ * However, this is not true. To determine whether something is selected,
162
132
* `ngModelController` is looking at whether `$scope.selectedUser == (any user in $scope.users);`;
163
133
*
164
134
* Javascript's `==` operator does not check for deep equality (ie. that all properties
165
135
* on the object are the same), but instead whether the objects are *the same object in memory*.
166
136
* In this case, we have two instances of identical objects, but they exist in memory as unique
167
137
* entities. Because of this, the select will have no value populated for a selected user.
168
138
*
169
- * To get around this, `ngModelController` provides a `track by` option that allows us to specify a different
170
- * expression which will be used for the equality operator. As such, we can update our `html` to
171
- * make use of this by specifying the `ng-model-options="{trackBy: '$value.id'}"` on the `md-select`
172
- * element. This converts our equality expression to be
139
+ * To get around this, `ngModelController` provides a `track by` option that allows us to specify a
140
+ * different expression which will be used for the equality operator. As such, we can update our
141
+ * `html` to make use of this by specifying the `ng-model-options="{trackBy: '$value.id'}"` on the
142
+ * `md-select` element. This converts our equality expression to be
173
143
* `$scope.selectedUser.id == (any id in $scope.users.map(function(u) { return u.id; }));`
174
144
* which results in Bob being selected as desired.
175
145
*
146
+ * **Note:** We do not support AngularJS's `track by` syntax. For instance
147
+ * `ng-options="user in users track by user.id"` will not work with `md-select`.
148
+ *
176
149
* Working HTML:
177
150
* <hljs lang="html">
178
151
* <div ng-controller="MyCtrl">
@@ -925,6 +898,82 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) {
925
898
926
899
}
927
900
901
+ /**
902
+ * @ngdoc directive
903
+ * @name mdOption
904
+ * @restrict E
905
+ * @module material.components.select
906
+ *
907
+ * @description Displays an option in a <a ng-href="/api/directive/mdSelect">md-select</a> box's
908
+ * dropdown menu. Options can be grouped using
909
+ * <a ng-href="/api/directive/mdOptgroup">md-optgroup</a> element directives.
910
+ *
911
+ * ### Option Params
912
+ *
913
+ * When applied, `md-option-empty` will mark the option as "empty" allowing the option to clear the
914
+ * select and put it back in it's default state. You may supply this attribute on any option you
915
+ * wish, however, it is automatically applied to an option whose `value` or `ng-value` are not
916
+ * defined.
917
+ *
918
+ * **Automatically Applied**
919
+ *
920
+ * - `<md-option>`
921
+ * - `<md-option value>`
922
+ * - `<md-option value="">`
923
+ * - `<md-option ng-value>`
924
+ * - `<md-option ng-value="">`
925
+ *
926
+ * **NOT Automatically Applied**
927
+ *
928
+ * - `<md-option ng-value="1">`
929
+ * - `<md-option ng-value="''">`
930
+ * - `<md-option ng-value="undefined">`
931
+ * - `<md-option value="undefined">` (this evaluates to the string `"undefined"`)
932
+ * - <code ng-non-bindable><md-option ng-value="{{someValueThatMightBeUndefined}}"></code>
933
+ *
934
+ * **Note:** A value of `undefined` ***is considered a valid value*** (and does not auto-apply this
935
+ * attribute) since you may wish this to be your "Not Available" or "None" option.
936
+ *
937
+ * **Note:** Using the
938
+ * <a ng-href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option#Attributes">value</a>
939
+ * attribute from the `<option>` element (as opposed to the `<md-option>` element's
940
+ * <a ng-href="https://docs.angularjs.org/api/ng/directive/ngValue">ng-value</a>) always evaluates
941
+ * to a `string`. This means that `value="null"` will cause a check against `myValue != "null"`
942
+ * rather than `!myValue` or `myValue != null`.
943
+ * Importantly, this also applies to `number` values. `value="1"` will not match up with an
944
+ * `ng-model` like `$scope.selectedValue = 1`. Use `ng-value="1"` in this case and other cases where
945
+ * you have values that are not strings.
946
+ *
947
+ * **Note:** Please see our <a ng-href="/api/directive/mdSelect#selects-and-object-equality">docs on
948
+ * using objects with `md-select`</a> for additional guidance on using the `trackBy` option with
949
+ * `ng-model-options`.
950
+ *
951
+ * @param {expression= } ng-value Binds the given expression to the value of the option.
952
+ * @param {string= } value Attribute to set the value of the option.
953
+ * @param {expression= } ng-repeat <a ng-href="https://docs.angularjs.org/api/ng/directive/ngRepeat">
954
+ * AngularJS directive</a> that instantiates a template once per item from a collection.
955
+ * @param {boolean= } md-option-empty If the attribute exists, mark the option as "empty" allowing
956
+ * the option to clear the select and put it back in it's default state. You may supply this
957
+ * attribute on any option you wish, however, it is automatically applied to an option whose `value`
958
+ * or `ng-value` are not defined.
959
+ * @param {number= } tabindex The `tabindex` of the option. Defaults to `0`.
960
+ *
961
+ * @usage
962
+ * <hljs lang="html">
963
+ * <md-select ng-model="currentState" placeholder="Select a state">
964
+ * <md-option ng-value="AL">Alabama</md-option>
965
+ * <md-option ng-value="AK">Alaska</md-option>
966
+ * <md-option ng-value="FL">Florida</md-option>
967
+ * </md-select>
968
+ * </hljs>
969
+ *
970
+ * With `ng-repeat`:
971
+ * <hljs lang="html">
972
+ * <md-select ng-model="currentState" placeholder="Select a state">
973
+ * <md-option ng-value="state" ng-repeat="state in states">{{ state }}</md-option>
974
+ * </md-select>
975
+ * </hljs>
976
+ */
928
977
function OptionDirective ( $mdButtonInkRipple , $mdUtil , $mdTheming ) {
929
978
930
979
return {
@@ -1056,6 +1105,54 @@ function OptionDirective($mdButtonInkRipple, $mdUtil, $mdTheming) {
1056
1105
1057
1106
}
1058
1107
1108
+ /**
1109
+ * @ngdoc directive
1110
+ * @name mdOptgroup
1111
+ * @restrict E
1112
+ * @module material.components.select
1113
+ *
1114
+ * @description Displays a label separating groups of
1115
+ * <a ng-href="/api/directive/mdOption">md-option</a> element directives in a
1116
+ * <a ng-href="/api/directive/mdSelect">md-select</a> box's dropdown menu.
1117
+ *
1118
+ * **Note:** When using `md-select-header` element directives within a `md-select`, the labels that
1119
+ * would normally be added to the <a ng-href="/api/directive/mdOptgroup">md-optgroup</a> directives
1120
+ * are omitted, allowing the `md-select-header` to represent the option group label
1121
+ * (and possibly more).
1122
+ *
1123
+ * @usage
1124
+ * With label attributes
1125
+ * <hljs lang="html">
1126
+ * <md-select ng-model="currentState" placeholder="Select a state">
1127
+ * <md-optgroup label="Southern">
1128
+ * <md-option ng-value="AL">Alabama</md-option>
1129
+ * <md-option ng-value="FL">Florida</md-option>
1130
+ * </md-optgroup>
1131
+ * <md-optgroup label="Northern">
1132
+ * <md-option ng-value="AK">Alaska</md-option>
1133
+ * <md-option ng-value="MA">Massachusetts</md-option>
1134
+ * </md-optgroup>
1135
+ * </md-select>
1136
+ * </hljs>
1137
+ *
1138
+ * With label elements
1139
+ * <hljs lang="html">
1140
+ * <md-select ng-model="currentState" placeholder="Select a state">
1141
+ * <md-optgroup>
1142
+ * <label>Southern</label>
1143
+ * <md-option ng-value="AL">Alabama</md-option>
1144
+ * <md-option ng-value="FL">Florida</md-option>
1145
+ * </md-optgroup>
1146
+ * <md-optgroup>
1147
+ * <label>Northern</label>
1148
+ * <md-option ng-value="AK">Alaska</md-option>
1149
+ * <md-option ng-value="MA">Massachusetts</md-option>
1150
+ * </md-optgroup>
1151
+ * </md-select>
1152
+ * </hljs>
1153
+ *
1154
+ * @param {string= } label The option group's label.
1155
+ */
1059
1156
function OptgroupDirective ( ) {
1060
1157
return {
1061
1158
restrict : 'E' ,
0 commit comments