Skip to content

Commit 2d79681

Browse files
committed
Additional options tests
1 parent c925a8b commit 2d79681

File tree

4 files changed

+204
-107
lines changed

4 files changed

+204
-107
lines changed

@types/directive/options/options.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const ngOptionsDirective: (
1212
post: (
1313
scope: import("../../core/scope/scope.js").Scope,
1414
selectElement: HTMLSelectElement,
15-
attr: any,
15+
attr: import("../../core/compile/attributes.js").Attributes,
1616
ctrls: any,
1717
) => void;
1818
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>AngularTS</title>
6+
<link rel="shortcut icon" type="image/png" href="images/favicon.ico" />
7+
<script
8+
type="module"
9+
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.32/angular.min.js"
10+
></script>
11+
</head>
12+
<body ng-app>
13+
<section ng-init='values = [{ name: "A" }, { name: "B" }, { name: "C" }]'>
14+
<select
15+
ng-model="selected"
16+
ng-options="value.name for value in values"
17+
></select>
18+
{{ selected.name }}
19+
<button ng-click="selected = values[0]">Select A</button>
20+
<button ng-click="selected = values[1]">Select B</button>
21+
<button ng-click="selected = values[2]">Select C</button>
22+
</section>
23+
24+
<section ng-init='values1 = { 0: "X", 1: "Y", 2: "Z", a: "A", length: 3 }'>
25+
<select
26+
ng-model="selected1"
27+
ng-options="value for value in values1"
28+
></select>
29+
{{ selected1 }}
30+
<button ng-click="selected1 = values1[0]">Select X</button>
31+
<button ng-click="selected1 = values1[1]">Select Y</button>
32+
<button ng-click="selected1 = values1[2]">Select Z</button>
33+
</section>
34+
</body>
35+
</html>

src/directive/options/options.js

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ import {
1212

1313
const ngOptionsMinErr = minErr("ngOptions");
1414

15+
/** @type {HTMLOptionElement} */
16+
const optionTemplate = document.createElement("option");
17+
18+
/** @type {HTMLOptGroupElement} */
19+
const optGroupTemplate = document.createElement("optgroup");
20+
1521
const NG_OPTIONS_REGEXP =
1622
/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\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]+?))?$/;
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

Comments
 (0)