@@ -12,6 +12,12 @@ import {
1212
1313const ngOptionsMinErr = minErr ( "ngOptions" ) ;
1414
15+ /** @type {HTMLOptionElement } */
16+ const optionTemplate = document . createElement ( "option" ) ;
17+
18+ /** @type {HTMLOptGroupElement } */
19+ const optGroupTemplate = document . createElement ( "optgroup" ) ;
20+
1521const NG_OPTIONS_REGEXP =
1622 / ^ \s * ( [ \s \S ] + ?) (?: \s + a s \s + ( [ \s \S ] + ?) ) ? (?: \s + g r o u p \s + b y \s + ( [ \s \S ] + ?) ) ? (?: \s + d i s a b l e \s + w h e n \s + ( [ \s \S ] + ?) ) ? \s + f o r \s + (?: ( [ $ \w ] [ $ \w ] * ) | (?: \( \s * ( [ $ \w ] [ $ \w ] * ) \s * , \s * ( [ $ \w ] [ $ \w ] * ) \s * \) ) ) \s + i n \s + ( [ \s \S ] + ?) (?: \s + t r a c k \s + b y \s + ( [ \s \S ] + ?) ) ? $ / ;
1723// 1: value expression (valueFn)
@@ -34,6 +40,12 @@ export const ngOptionsDirective = [
3440 * @returns
3541 */
3642 function ( $compile , $parse ) {
43+ /**
44+ * @param {import('../../interface.ts').Expression } optionsExp
45+ * @param {HTMLSelectElement } selectElement
46+ * @param {import('../../core/scope/scope.js').Scope } scope
47+ * @returns
48+ */
3749 function parseOptionsExpression ( optionsExp , selectElement , scope ) {
3850 const match = optionsExp . match ( NG_OPTIONS_REGEXP ) ;
3951 if ( ! match ) {
@@ -160,7 +172,9 @@ export const ngOptionsDirective = [
160172 } ) ,
161173
162174 getOptions ( ) {
175+ /** @type {Option[] } */
163176 const optionItems = [ ] ;
177+ /** @type {Object.<string, Option> } */
164178 const selectValueMap = { } ;
165179
166180 // The option values were already computed in the `getWatchables` fn,
@@ -211,23 +225,17 @@ export const ngOptionsDirective = [
211225 } ;
212226 }
213227
214- // Support: IE 9 only
215- // We can't just ('<option>') since JQLite is not smart enough
216- // to create it in <select> and IE barfs otherwise.
217- const optionTemplate = document . createElement ( "option" ) ;
218- const optGroupTemplate = document . createElement ( "optgroup" ) ;
219-
220228 /**
221229 *
222230 * @param {import("../../core/scope/scope.js").Scope } scope
223231 * @param {HTMLSelectElement } selectElement
224- * @param {* } attr
232+ * @param {import("../../core/compile/attributes.js").Attributes } attr
225233 * @param {* } ctrls
226234 */
227235 function ngOptionsPostLink ( scope , selectElement , attr , ctrls ) {
228236 const selectCtrl = ctrls [ 0 ] ;
229237 const ngModelCtrl = ctrls [ 1 ] ;
230- const { multiple } = attr ;
238+ const multiple = attr [ "multiple" ] ;
231239
232240 // The emptyOption allows the application developer to provide their own custom "empty"
233241 // option when the viewValue does not match any of the option values.
@@ -254,7 +262,7 @@ export const ngOptionsDirective = [
254262
255263 let options ;
256264 const ngOptions = parseOptionsExpression (
257- attr . ngOptions ,
265+ attr [ " ngOptions" ] ,
258266 selectElement ,
259267 scope ,
260268 ) ;
@@ -313,14 +321,14 @@ export const ngOptionsDirective = [
313321 // If we are using `track by` then we must watch the tracked value on the model
314322 // since ngModel only watches for object identity change
315323 // FIXME: When a user selects an option, this watch will fire needlessly
316- // if (ngOptions.trackBy) {
317- // scope.$watch(
318- // () => ngOptions.getTrackByValue(ngModelCtrl.$viewValue),
319- // () => {
320- // ngModelCtrl.$render();
321- // },
322- // );
323- // }
324+ if ( ngOptions . trackBy ) {
325+ scope . $watch (
326+ ngOptions . getTrackByValue ( ngModelCtrl . $viewValue ) ,
327+ ( ) => {
328+ ngModelCtrl . $render ( ) ;
329+ } ,
330+ ) ;
331+ }
324332 } else {
325333 selectCtrl . writeValue = function writeNgOptionsMultiple ( values ) {
326334 // The options might not be defined yet when ngModel tries to render
@@ -419,7 +427,12 @@ export const ngOptionsDirective = [
419427 // ------------------------------------------------------------------ //
420428
421429 function addOptionElement ( option , parent ) {
422- const optionElement = optionTemplate . cloneNode ( false ) ;
430+ /**
431+ * @type {HTMLOptionElement }
432+ */
433+ const optionElement = /** @type {HTMLOptionElement } */ (
434+ optionTemplate . cloneNode ( false )
435+ ) ;
423436 parent . appendChild ( optionElement ) ;
424437 updateOptionElement ( option , optionElement ) ;
425438 }
0 commit comments