@angular-wave/angular.ts 0.9.3 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (703) hide show
  1. package/@types/angular.d.ts +4 -19
  2. package/@types/animations/animate.d.ts +2 -2
  3. package/@types/animations/animation.d.ts +1 -1
  4. package/@types/core/compile/attributes.d.ts +1 -1
  5. package/@types/core/compile/compile.d.ts +2 -2
  6. package/@types/core/controller/controller.d.ts +1 -1
  7. package/@types/core/controller/interface.d.ts +6 -0
  8. package/@types/core/di/ng-module.d.ts +27 -26
  9. package/@types/core/filter/filter.d.ts +5 -5
  10. package/@types/core/interpolate/interface.d.ts +13 -0
  11. package/@types/core/interpolate/interpolate.d.ts +1 -13
  12. package/@types/core/scope/scope.d.ts +4 -1
  13. package/@types/directive/http/http.d.ts +16 -16
  14. package/@types/directive/http/interface.d.ts +27 -0
  15. package/@types/directive/include/include.d.ts +4 -4
  16. package/@types/directive/inject/inject.d.ts +12 -0
  17. package/@types/directive/model/model.d.ts +1 -1
  18. package/@types/directive/script/script.d.ts +2 -2
  19. package/@types/directive/setter/setter.d.ts +4 -4
  20. package/@types/filters/filter.d.ts +2 -2
  21. package/@types/filters/filters.d.ts +2 -2
  22. package/@types/filters/interface.d.ts +8 -0
  23. package/@types/filters/limit-to.d.ts +2 -2
  24. package/@types/filters/order-by.d.ts +2 -2
  25. package/@types/interface.d.ts +105 -82
  26. package/@types/namespace.d.ts +76 -0
  27. package/@types/router/state/interface.d.ts +8 -8
  28. package/@types/router/state-filters.d.ts +4 -4
  29. package/@types/router/template-factory.d.ts +8 -8
  30. package/@types/router/transition/hook-builder.d.ts +5 -2
  31. package/@types/router/transition/hook-registry.d.ts +11 -2
  32. package/@types/router/transition/transition-service.d.ts +6 -2
  33. package/@types/router/transition/transition.d.ts +2 -2
  34. package/@types/router/view/view.d.ts +1 -8
  35. package/@types/router/view-scroll.d.ts +4 -2
  36. package/@types/services/{anchor-scroll.d.ts → anchor-scroll/anchor-scroll.d.ts} +2 -2
  37. package/@types/services/exception/exception-handler.d.ts +2 -2
  38. package/@types/services/exception/interface.d.ts +1 -1
  39. package/@types/services/http/http.d.ts +40 -2
  40. package/@types/services/http/interface.d.ts +11 -0
  41. package/@types/services/location/location.d.ts +1 -4
  42. package/@types/services/sce/sce.d.ts +3 -4
  43. package/@types/services/template-cache/template-cache.d.ts +4 -4
  44. package/@types/services/template-request/interface.d.ts +22 -0
  45. package/@types/services/{template-request.d.ts → template-request/template-request.d.ts} +4 -7
  46. package/@types/shared/common.d.ts +8 -69
  47. package/@types/shared/hof.d.ts +7 -7
  48. package/dist/angular-ts.esm.js +510 -570
  49. package/dist/angular-ts.umd.js +510 -570
  50. package/dist/angular-ts.umd.min.js +1 -1
  51. package/package.json +8 -1
  52. package/.github/workflows/ci.yml +0 -104
  53. package/.github/workflows/gh-pages.yml +0 -75
  54. package/.husky/pre-commit +0 -5
  55. package/.prettierignore +0 -9
  56. package/@types/services/cookie-reader.d.ts +0 -4
  57. package/@types/services/http-backend/http-backend.d.ts +0 -58
  58. package/@types/services/template-cache/interface.d.ts +0 -10
  59. package/CHANGELOG.md +0 -17667
  60. package/CODE_OF_CONDUCT.md +0 -3
  61. package/CONTRIBUTING.md +0 -247
  62. package/DEVELOPERS.md +0 -499
  63. package/Makefile +0 -60
  64. package/RELEASE.md +0 -86
  65. package/TRIAGING.md +0 -127
  66. package/docs/.cspell.yml +0 -8
  67. package/docs/.github/dependabot.yml +0 -14
  68. package/docs/.nvmrc +0 -1
  69. package/docs/CONTRIBUTING.md +0 -28
  70. package/docs/Dockerfile +0 -4
  71. package/docs/LICENSE +0 -201
  72. package/docs/README.md +0 -217
  73. package/docs/assets/icons/logo.svg +0 -1
  74. package/docs/assets/scss/_variables_project.scss +0 -12
  75. package/docs/assets/scss/_variables_project_after_bs.scss +0 -8
  76. package/docs/assets/scss/index.scss +0 -48
  77. package/docs/config.yaml +0 -15
  78. package/docs/content/_index.md +0 -28
  79. package/docs/content/docs/_index.md +0 -61
  80. package/docs/content/docs/directive/_index.md +0 -4
  81. package/docs/content/docs/directive/app.md +0 -11
  82. package/docs/content/docs/directive/aria.md +0 -0
  83. package/docs/content/docs/directive/bind.md +0 -72
  84. package/docs/content/docs/directive/blur.md +0 -38
  85. package/docs/content/docs/directive/channel.md +0 -37
  86. package/docs/content/docs/directive/class-even.md +0 -47
  87. package/docs/content/docs/directive/class-odd.md +0 -48
  88. package/docs/content/docs/directive/class.md +0 -64
  89. package/docs/content/docs/directive/click.md +0 -41
  90. package/docs/content/docs/directive/cloak.md +0 -74
  91. package/docs/content/docs/directive/copy.md +0 -38
  92. package/docs/content/docs/directive/cut.md +0 -40
  93. package/docs/content/docs/directive/dblclick.md +0 -41
  94. package/docs/content/docs/directive/focus.md +0 -38
  95. package/docs/content/docs/directive/get.md +0 -203
  96. package/docs/content/docs/directive/include.md +0 -7
  97. package/docs/content/docs/directive/keydown.md +0 -38
  98. package/docs/content/docs/directive/keyup.md +0 -38
  99. package/docs/content/docs/directive/load.md +0 -43
  100. package/docs/content/docs/directive/mousedown.md +0 -38
  101. package/docs/content/docs/directive/mouseenter.md +0 -38
  102. package/docs/content/docs/directive/mouseleave.md +0 -38
  103. package/docs/content/docs/directive/mousemove.md +0 -38
  104. package/docs/content/docs/directive/mouseout.md +0 -38
  105. package/docs/content/docs/directive/mouseover.md +0 -38
  106. package/docs/content/docs/directive/mouseup.md +0 -38
  107. package/docs/content/docs/directive/non-bindable.md +0 -28
  108. package/docs/content/docs/filter/_index.md +0 -4
  109. package/docs/content/docs/provider/_index.md +0 -4
  110. package/docs/content/docs/provider/eventBusProvider.md +0 -35
  111. package/docs/content/docs/provider/locationProvider.md +0 -26
  112. package/docs/content/docs/provider/logProvider.md +0 -59
  113. package/docs/content/docs/provider/templateCacheProvider.md +0 -100
  114. package/docs/content/docs/service/_index.md +0 -4
  115. package/docs/content/docs/service/eventBus.md +0 -56
  116. package/docs/content/docs/service/location.md +0 -57
  117. package/docs/content/docs/service/log.md +0 -113
  118. package/docs/content/docs/service/templateCache.md +0 -64
  119. package/docs/content/docs/service/url.md +0 -5
  120. package/docs/docker-compose.yaml +0 -12
  121. package/docs/docsy.work +0 -5
  122. package/docs/docsy.work.sum +0 -0
  123. package/docs/go.mod +0 -5
  124. package/docs/go.sum +0 -6
  125. package/docs/hugo-disabled.toml +0 -220
  126. package/docs/hugo.yaml +0 -200
  127. package/docs/layouts/404.html +0 -13
  128. package/docs/layouts/_markup/render-heading.html +0 -1
  129. package/docs/layouts/partials/hooks/head-end.html +0 -3
  130. package/docs/layouts/shortcodes/showcss.html +0 -2
  131. package/docs/layouts/shortcodes/showhtml.html +0 -2
  132. package/docs/layouts/shortcodes/showjs.html +0 -2
  133. package/docs/layouts/shortcodes/showraw.html +0 -1
  134. package/docs/layouts/shortcodes/version.html +0 -1
  135. package/docs/package-lock.json +0 -2293
  136. package/docs/package.json +0 -53
  137. package/docs/static/examples/counter/counter-test.html +0 -13
  138. package/docs/static/examples/counter/counter.html +0 -5
  139. package/docs/static/examples/counter/counter.test.js +0 -28
  140. package/docs/static/examples/eventbus/eventbus-test.html +0 -15
  141. package/docs/static/examples/eventbus/eventbus.html +0 -13
  142. package/docs/static/examples/eventbus/eventbus.js +0 -15
  143. package/docs/static/examples/eventbus/eventbus.test.js +0 -19
  144. package/docs/static/examples/ng-bind/ng-bind.html +0 -9
  145. package/docs/static/examples/ng-blur/ng-blur.html +0 -9
  146. package/docs/static/examples/ng-channel/ng-channel-test.html +0 -17
  147. package/docs/static/examples/ng-channel/ng-channel.html +0 -24
  148. package/docs/static/examples/ng-channel/ng-channel.test.js +0 -31
  149. package/docs/static/examples/ng-class/ng-class.html +0 -71
  150. package/docs/static/examples/ng-class-even/ng-class-even.html +0 -8
  151. package/docs/static/examples/ng-class-odd/ng-class-odd.html +0 -8
  152. package/docs/static/examples/ng-click/ng-click.html +0 -6
  153. package/docs/static/examples/ng-copy/ng-copy.html +0 -6
  154. package/docs/static/examples/ng-cut/ng-cut.html +0 -6
  155. package/docs/static/examples/ng-dblclick/ng-dblclick.html +0 -10
  156. package/docs/static/examples/ng-focus/ng-focus.html +0 -9
  157. package/docs/static/examples/ng-keydown/ng-keydown.html +0 -9
  158. package/docs/static/examples/ng-keyup/ng-keyup.html +0 -9
  159. package/docs/static/examples/ng-load/ng-load.html +0 -8
  160. package/docs/static/examples/ng-mousedown/ng-mousedown.html +0 -6
  161. package/docs/static/examples/ng-mouseenter/ng-mouseenter.html +0 -4
  162. package/docs/static/examples/ng-mouseleave/ng-mouseleave.html +0 -4
  163. package/docs/static/examples/ng-mousemove/ng-mousemove.html +0 -4
  164. package/docs/static/examples/ng-mouseout/ng-mouseout.html +0 -4
  165. package/docs/static/examples/ng-mouseover/ng-mouseover.html +0 -4
  166. package/docs/static/examples/ng-mouseup/ng-mouseup.html +0 -4
  167. package/docs/static/examples/ng-non-bindable/ng-non-bindable-test.html +0 -13
  168. package/docs/static/examples/ng-non-bindable/ng-non-bindable.html +0 -3
  169. package/docs/static/examples/ng-non-bindable/ng-non-bindable.test.js +0 -11
  170. package/docs/static/typedoc/.nojekyll +0 -1
  171. package/docs/static/typedoc/assets/hierarchy.js +0 -1
  172. package/docs/static/typedoc/assets/highlight.css +0 -78
  173. package/docs/static/typedoc/assets/icons.js +0 -18
  174. package/docs/static/typedoc/assets/icons.svg +0 -1
  175. package/docs/static/typedoc/assets/main.js +0 -60
  176. package/docs/static/typedoc/assets/navigation.js +0 -1
  177. package/docs/static/typedoc/assets/search.js +0 -1
  178. package/docs/static/typedoc/assets/style.css +0 -1633
  179. package/docs/static/typedoc/classes/Location.html +0 -55
  180. package/docs/static/typedoc/classes/LocationProvider.html +0 -20
  181. package/docs/static/typedoc/classes/LogProvider.html +0 -6
  182. package/docs/static/typedoc/classes/PubSub.html +0 -71
  183. package/docs/static/typedoc/classes/PubSubProvider.html +0 -3
  184. package/docs/static/typedoc/classes/TemplateCacheProvider.html +0 -5
  185. package/docs/static/typedoc/hierarchy.html +0 -1
  186. package/docs/static/typedoc/index.html +0 -1
  187. package/docs/static/typedoc/interfaces/ChangesObject.html +0 -6
  188. package/docs/static/typedoc/interfaces/ComponentOptions.html +0 -16
  189. package/docs/static/typedoc/interfaces/Controller.html +0 -12
  190. package/docs/static/typedoc/interfaces/DefaultPorts.html +0 -5
  191. package/docs/static/typedoc/interfaces/Directive.html +0 -37
  192. package/docs/static/typedoc/interfaces/DirectivePrePost.html +0 -4
  193. package/docs/static/typedoc/interfaces/Html5Mode.html +0 -23
  194. package/docs/static/typedoc/interfaces/HttpHeadersGetter.html +0 -1
  195. package/docs/static/typedoc/interfaces/HttpProviderDefaults.html +0 -31
  196. package/docs/static/typedoc/interfaces/HttpRequestConfigHeaders.html +0 -6
  197. package/docs/static/typedoc/interfaces/HttpRequestTransformer.html +0 -1
  198. package/docs/static/typedoc/interfaces/HttpResponse.html +0 -7
  199. package/docs/static/typedoc/interfaces/HttpResponseTransformer.html +0 -1
  200. package/docs/static/typedoc/interfaces/HttpService.html +0 -38
  201. package/docs/static/typedoc/interfaces/LogService.html +0 -12
  202. package/docs/static/typedoc/interfaces/NgModelController.html +0 -30
  203. package/docs/static/typedoc/interfaces/NgModelOptions.html +0 -16
  204. package/docs/static/typedoc/interfaces/Provider.html +0 -34
  205. package/docs/static/typedoc/interfaces/RequestConfig.html +0 -48
  206. package/docs/static/typedoc/interfaces/RequestShortcutConfig.html +0 -38
  207. package/docs/static/typedoc/interfaces/ServiceProvider.html +0 -5
  208. package/docs/static/typedoc/interfaces/TemplateCache.html +0 -7
  209. package/docs/static/typedoc/interfaces/TranscludeFunctionObject.html +0 -8
  210. package/docs/static/typedoc/interfaces/UrlParts.html +0 -9
  211. package/docs/static/typedoc/types/AnnotatedDirectiveFactory.html +0 -1
  212. package/docs/static/typedoc/types/AnnotatedFactory.html +0 -8
  213. package/docs/static/typedoc/types/CloneAttachFunction.html +0 -2
  214. package/docs/static/typedoc/types/ControllerConstructor.html +0 -2
  215. package/docs/static/typedoc/types/DirectiveCompileFn.html +0 -2
  216. package/docs/static/typedoc/types/DirectiveController.html +0 -2
  217. package/docs/static/typedoc/types/DirectiveFactory.html +0 -1
  218. package/docs/static/typedoc/types/DirectiveFactoryFn.html +0 -1
  219. package/docs/static/typedoc/types/DirectiveLinkFn.html +0 -2
  220. package/docs/static/typedoc/types/ExpandoStore.html +0 -2
  221. package/docs/static/typedoc/types/Expression.html +0 -6
  222. package/docs/static/typedoc/types/FilterFactory.html +0 -2
  223. package/docs/static/typedoc/types/FilterFn.html +0 -2
  224. package/docs/static/typedoc/types/HttpPromise.html +0 -1
  225. package/docs/static/typedoc/types/HttpResponseStatus.html +0 -1
  226. package/docs/static/typedoc/types/Injectable.html +0 -4
  227. package/docs/static/typedoc/types/InjectableClass.html +0 -1
  228. package/docs/static/typedoc/types/InjectableFactory.html +0 -1
  229. package/docs/static/typedoc/types/LogCall.html +0 -2
  230. package/docs/static/typedoc/types/LogServiceFactory.html +0 -2
  231. package/docs/static/typedoc/types/OnChangesObject.html +0 -2
  232. package/docs/static/typedoc/types/SwapModeType.html +0 -2
  233. package/docs/static/typedoc/types/TController.html +0 -2
  234. package/docs/static/typedoc/types/UrlChangeListener.html +0 -5
  235. package/docs/static/typedoc/variables/EventBus.html +0 -1
  236. package/docs/static/typedoc/variables/SwapMode.html +0 -11
  237. package/docs/static/version.js +0 -13
  238. package/docs/test-results/.last-run.json +0 -4
  239. package/docs/test-results/static-examples-counter-counter-counter-example/error-context.md +0 -50
  240. package/eslint.config.js +0 -26
  241. package/images/android-chrome-192x192.png +0 -0
  242. package/images/android-chrome-512x512.png +0 -0
  243. package/images/apple-touch-icon.png +0 -0
  244. package/images/favicon-16x16.png +0 -0
  245. package/images/favicon-32x32.png +0 -0
  246. package/images/favicon.ico +0 -0
  247. package/images/site.webmanifest +0 -19
  248. package/index.html +0 -86
  249. package/legacy.d.ts +0 -2599
  250. package/playwright.config.ts +0 -81
  251. package/public/jasmine/boot0.js +0 -66
  252. package/public/jasmine/boot1.js +0 -134
  253. package/public/jasmine/jasmine-html.js +0 -970
  254. package/public/jasmine/jasmine.css +0 -323
  255. package/public/jasmine/jasmine.js +0 -11406
  256. package/public/public/README.md +0 -1
  257. package/public/public/circle.html +0 -1
  258. package/public/public/jasmine-helper.css +0 -9
  259. package/public/public/my_child_directive.html +0 -1
  260. package/public/public/my_directive.html +0 -1
  261. package/public/public/my_other_directive.html +0 -1
  262. package/public/public/test.html +0 -1
  263. package/rollup.config.js +0 -51
  264. package/src/angular.js +0 -293
  265. package/src/angular.spec.js +0 -1191
  266. package/src/animations/animate-cache.js +0 -80
  267. package/src/animations/animate-children-directive.js +0 -32
  268. package/src/animations/animate-children-directive.md +0 -80
  269. package/src/animations/animate-css-driver.js +0 -284
  270. package/src/animations/animate-css.html +0 -58
  271. package/src/animations/animate-css.js +0 -915
  272. package/src/animations/animate-css.md +0 -263
  273. package/src/animations/animate-js-driver.js +0 -60
  274. package/src/animations/animate-js.html +0 -47
  275. package/src/animations/animate-js.js +0 -371
  276. package/src/animations/animate-queue.js +0 -859
  277. package/src/animations/animate-runner.js +0 -193
  278. package/src/animations/animate-swap.js +0 -33
  279. package/src/animations/animate-swap.md +0 -88
  280. package/src/animations/animate.html +0 -19
  281. package/src/animations/animate.js +0 -546
  282. package/src/animations/animate.md +0 -933
  283. package/src/animations/animate.spec.js +0 -490
  284. package/src/animations/animation.js +0 -519
  285. package/src/animations/animations.test.js +0 -10
  286. package/src/animations/interface.ts +0 -19
  287. package/src/animations/raf-scheduler.html +0 -19
  288. package/src/animations/raf-scheduler.js +0 -92
  289. package/src/animations/raf-scheduler.spec.js +0 -98
  290. package/src/animations/shared.js +0 -341
  291. package/src/binding.html +0 -19
  292. package/src/binding.spec.js +0 -474
  293. package/src/binding.test.js +0 -10
  294. package/src/core/compile/attributes.js +0 -337
  295. package/src/core/compile/compile.html +0 -19
  296. package/src/core/compile/compile.js +0 -3270
  297. package/src/core/compile/compile.md +0 -1128
  298. package/src/core/compile/compile.spec.js +0 -15574
  299. package/src/core/compile/compile.test.js +0 -12
  300. package/src/core/controller/controller.html +0 -22
  301. package/src/core/controller/controller.js +0 -189
  302. package/src/core/controller/controller.spec.js +0 -334
  303. package/src/core/controller/controller.test.js +0 -12
  304. package/src/core/core.html +0 -20
  305. package/src/core/core.test.js +0 -12
  306. package/src/core/di/injector.html +0 -19
  307. package/src/core/di/injector.js +0 -307
  308. package/src/core/di/injector.md +0 -740
  309. package/src/core/di/injector.spec.js +0 -2310
  310. package/src/core/di/injector.test.js +0 -12
  311. package/src/core/di/internal-injector.js +0 -284
  312. package/src/core/di/ng-module.html +0 -19
  313. package/src/core/di/ng-module.js +0 -226
  314. package/src/core/di/ng-module.spec.js +0 -263
  315. package/src/core/di/ng-module.test.js +0 -12
  316. package/src/core/filter/filter.html +0 -19
  317. package/src/core/filter/filter.js +0 -55
  318. package/src/core/filter/filter.md +0 -132
  319. package/src/core/filter/filter.spec.js +0 -149
  320. package/src/core/filter/filter.test.js +0 -12
  321. package/src/core/interpolate/interpolate.html +0 -22
  322. package/src/core/interpolate/interpolate.js +0 -408
  323. package/src/core/interpolate/interpolate.spec.js +0 -601
  324. package/src/core/interpolate/interpolate.test.js +0 -12
  325. package/src/core/parse/ast/ast-node.ts +0 -81
  326. package/src/core/parse/ast/ast.html +0 -19
  327. package/src/core/parse/ast/ast.js +0 -574
  328. package/src/core/parse/ast/ast.spec.js +0 -1453
  329. package/src/core/parse/ast/ast.test.js +0 -10
  330. package/src/core/parse/ast-type.js +0 -23
  331. package/src/core/parse/interface.ts +0 -84
  332. package/src/core/parse/interpreter.js +0 -915
  333. package/src/core/parse/lexer/lexer.html +0 -19
  334. package/src/core/parse/lexer/lexer.js +0 -338
  335. package/src/core/parse/lexer/lexer.spec.js +0 -303
  336. package/src/core/parse/lexer/lexer.test.js +0 -10
  337. package/src/core/parse/lexer/token.ts +0 -22
  338. package/src/core/parse/parse.html +0 -19
  339. package/src/core/parse/parse.js +0 -337
  340. package/src/core/parse/parse.md +0 -57
  341. package/src/core/parse/parse.spec.js +0 -2107
  342. package/src/core/parse/parse.test.js +0 -10
  343. package/src/core/parse/parser/parser.html +0 -19
  344. package/src/core/parse/parser/parser.js +0 -64
  345. package/src/core/parse/parser/parser.spec.js +0 -8
  346. package/src/core/parse/parser/parser.test.js +0 -10
  347. package/src/core/prop.spec.js +0 -775
  348. package/src/core/root-element.spec.js +0 -14
  349. package/src/core/sanitize/interface.ts +0 -10
  350. package/src/core/sanitize/sanitize-uri.js +0 -75
  351. package/src/core/sanitize/sanitize-uri.spec.js +0 -249
  352. package/src/core/sanitize/sanitize-uri.test.js +0 -12
  353. package/src/core/sanitize/sanitize.html +0 -22
  354. package/src/core/scope/scope.html +0 -19
  355. package/src/core/scope/scope.js +0 -1249
  356. package/src/core/scope/scope.spec.js +0 -3000
  357. package/src/core/scope/scope.test.js +0 -12
  358. package/src/directive/aria/aria.html +0 -19
  359. package/src/directive/aria/aria.js +0 -382
  360. package/src/directive/aria/aria.md +0 -145
  361. package/src/directive/aria/aria.spec.js +0 -1241
  362. package/src/directive/aria/aria.test.js +0 -12
  363. package/src/directive/attrs/attrs.html +0 -19
  364. package/src/directive/attrs/attrs.js +0 -106
  365. package/src/directive/attrs/attrs.md +0 -224
  366. package/src/directive/attrs/attrs.spec.js +0 -71
  367. package/src/directive/attrs/attrs.test.js +0 -12
  368. package/src/directive/attrs/boolean.html +0 -19
  369. package/src/directive/attrs/boolean.spec.js +0 -137
  370. package/src/directive/attrs/boolean.test.js +0 -12
  371. package/src/directive/attrs/element-style.html +0 -22
  372. package/src/directive/attrs/element-style.spec.js +0 -85
  373. package/src/directive/attrs/element-style.test.js +0 -12
  374. package/src/directive/attrs/src.html +0 -19
  375. package/src/directive/attrs/src.spec.js +0 -163
  376. package/src/directive/attrs/src.test.js +0 -12
  377. package/src/directive/bind/bind-html.spec.js +0 -36
  378. package/src/directive/bind/bind.html +0 -20
  379. package/src/directive/bind/bind.js +0 -78
  380. package/src/directive/bind/bind.md +0 -142
  381. package/src/directive/bind/bind.spec.js +0 -314
  382. package/src/directive/bind/bind.test.js +0 -12
  383. package/src/directive/channel/channel.html +0 -19
  384. package/src/directive/channel/channel.js +0 -30
  385. package/src/directive/channel/channel.spec.js +0 -67
  386. package/src/directive/channel/channel.test.js +0 -10
  387. package/src/directive/class/class-test.html +0 -23
  388. package/src/directive/class/class.html +0 -19
  389. package/src/directive/class/class.js +0 -184
  390. package/src/directive/class/class.spec.js +0 -704
  391. package/src/directive/class/class.test.js +0 -12
  392. package/src/directive/cloak/cloak.html +0 -19
  393. package/src/directive/cloak/cloak.js +0 -11
  394. package/src/directive/cloak/cloak.spec.js +0 -44
  395. package/src/directive/cloak/cloak.test.js +0 -12
  396. package/src/directive/controller/controller.html +0 -22
  397. package/src/directive/controller/controller.js +0 -11
  398. package/src/directive/controller/controller.md +0 -46
  399. package/src/directive/controller/controller.spec.js +0 -175
  400. package/src/directive/controller/controller.test.js +0 -12
  401. package/src/directive/events/click.spec.js +0 -35
  402. package/src/directive/events/event.spec.js +0 -267
  403. package/src/directive/events/events-test.html +0 -36
  404. package/src/directive/events/events.html +0 -20
  405. package/src/directive/events/events.js +0 -65
  406. package/src/directive/events/events.md +0 -125
  407. package/src/directive/events/events.test.js +0 -12
  408. package/src/directive/form/form.html +0 -19
  409. package/src/directive/form/form.js +0 -669
  410. package/src/directive/form/form.spec.js +0 -1515
  411. package/src/directive/form/form.test.js +0 -12
  412. package/src/directive/http/delete.spec.js +0 -26
  413. package/src/directive/http/form-router-test.html +0 -44
  414. package/src/directive/http/form-test.html +0 -18
  415. package/src/directive/http/get.spec.js +0 -488
  416. package/src/directive/http/http.html +0 -22
  417. package/src/directive/http/http.js +0 -342
  418. package/src/directive/http/http.test.js +0 -12
  419. package/src/directive/http/post-example.html +0 -30
  420. package/src/directive/http/post.spec.js +0 -521
  421. package/src/directive/http/put.spec.js +0 -26
  422. package/src/directive/if/if-animate-css.html +0 -57
  423. package/src/directive/if/if-animate-svg.html +0 -25
  424. package/src/directive/if/if.html +0 -19
  425. package/src/directive/if/if.js +0 -72
  426. package/src/directive/if/if.md +0 -76
  427. package/src/directive/if/if.spec.js +0 -293
  428. package/src/directive/if/if.test.js +0 -114
  429. package/src/directive/include/include.html +0 -19
  430. package/src/directive/include/include.js +0 -151
  431. package/src/directive/include/include.md +0 -87
  432. package/src/directive/include/include.spec.js +0 -734
  433. package/src/directive/include/include.test.js +0 -12
  434. package/src/directive/init/init.html +0 -19
  435. package/src/directive/init/init.js +0 -22
  436. package/src/directive/init/init.md +0 -41
  437. package/src/directive/init/init.spec.js +0 -68
  438. package/src/directive/init/init.test.js +0 -12
  439. package/src/directive/input/input-example.html +0 -15
  440. package/src/directive/input/input.html +0 -19
  441. package/src/directive/input/input.js +0 -1078
  442. package/src/directive/input/input.md +0 -706
  443. package/src/directive/input/input.spec.js +0 -3700
  444. package/src/directive/input/input.test.js +0 -12
  445. package/src/directive/messages/messages.html +0 -22
  446. package/src/directive/messages/messages.js +0 -349
  447. package/src/directive/messages/messages.md +0 -543
  448. package/src/directive/messages/messages.spec.js +0 -1083
  449. package/src/directive/messages/messages.test.js +0 -12
  450. package/src/directive/model/change.md +0 -25
  451. package/src/directive/model/model.html +0 -19
  452. package/src/directive/model/model.js +0 -1170
  453. package/src/directive/model/model.spec.js +0 -1976
  454. package/src/directive/model/model.test.js +0 -12
  455. package/src/directive/model-options/model-option.test.js +0 -12
  456. package/src/directive/model-options/model-options.html +0 -22
  457. package/src/directive/model-options/model-options.js +0 -142
  458. package/src/directive/model-options/model-options.md +0 -407
  459. package/src/directive/model-options/model-options.spec.js +0 -1022
  460. package/src/directive/non-bindable/non-bindable.html +0 -22
  461. package/src/directive/non-bindable/non-bindable.js +0 -9
  462. package/src/directive/non-bindable/non-bindable.spec.js +0 -59
  463. package/src/directive/non-bindable/non-bindable.test.js +0 -12
  464. package/src/directive/observe/observe-demo.html +0 -184
  465. package/src/directive/observe/observe.html +0 -19
  466. package/src/directive/observe/observe.js +0 -41
  467. package/src/directive/observe/observe.spec.js +0 -106
  468. package/src/directive/observe/observe.test.js +0 -10
  469. package/src/directive/on/on.html +0 -19
  470. package/src/directive/on/on.spec.js +0 -215
  471. package/src/directive/on/on.test.js +0 -12
  472. package/src/directive/options/options-example.html +0 -17
  473. package/src/directive/options/options.html +0 -22
  474. package/src/directive/options/options.js +0 -542
  475. package/src/directive/options/options.md +0 -179
  476. package/src/directive/options/options.spec.js +0 -3554
  477. package/src/directive/options/options.test.js +0 -12
  478. package/src/directive/ref/href.html +0 -19
  479. package/src/directive/ref/href.spec.js +0 -141
  480. package/src/directive/ref/href.test.js +0 -19
  481. package/src/directive/ref/ref.html +0 -19
  482. package/src/directive/ref/ref.js +0 -89
  483. package/src/directive/ref/ref.spec.js +0 -546
  484. package/src/directive/repeat/repeat.html +0 -19
  485. package/src/directive/repeat/repeat.js +0 -333
  486. package/src/directive/repeat/repeat.md +0 -330
  487. package/src/directive/repeat/repeat.spec.js +0 -1209
  488. package/src/directive/repeat/repeat.test.js +0 -12
  489. package/src/directive/script/script.html +0 -19
  490. package/src/directive/script/script.js +0 -17
  491. package/src/directive/script/script.md +0 -11
  492. package/src/directive/script/script.spec.js +0 -47
  493. package/src/directive/script/script.test.js +0 -12
  494. package/src/directive/select/select.html +0 -19
  495. package/src/directive/select/select.js +0 -594
  496. package/src/directive/select/select.md +0 -74
  497. package/src/directive/select/select.spec.js +0 -2566
  498. package/src/directive/select/select.test.js +0 -12
  499. package/src/directive/setter/setter.html +0 -19
  500. package/src/directive/setter/setter.js +0 -59
  501. package/src/directive/setter/setter.spec.js +0 -100
  502. package/src/directive/setter/setter.test.js +0 -12
  503. package/src/directive/show-hide/show-hide.html +0 -22
  504. package/src/directive/show-hide/show-hide.js +0 -65
  505. package/src/directive/show-hide/show-hide.md +0 -255
  506. package/src/directive/show-hide/show-hide.spec.js +0 -268
  507. package/src/directive/show-hide/show-hide.test.js +0 -12
  508. package/src/directive/style/style.html +0 -19
  509. package/src/directive/style/style.js +0 -27
  510. package/src/directive/style/style.md +0 -23
  511. package/src/directive/style/style.spec.js +0 -183
  512. package/src/directive/style/style.test.js +0 -12
  513. package/src/directive/switch/switch.html +0 -19
  514. package/src/directive/switch/switch.js +0 -133
  515. package/src/directive/switch/switch.md +0 -66
  516. package/src/directive/switch/switch.spec.js +0 -509
  517. package/src/directive/switch/switch.test.js +0 -12
  518. package/src/directive/transclude/transclude.js +0 -122
  519. package/src/directive/validators/validators.html +0 -22
  520. package/src/directive/validators/validators.js +0 -346
  521. package/src/directive/validators/validators.spec.js +0 -740
  522. package/src/directive/validators/validators.test.js +0 -12
  523. package/src/filters/filter.js +0 -213
  524. package/src/filters/filter.md +0 -69
  525. package/src/filters/filter.spec.js +0 -719
  526. package/src/filters/filters.html +0 -22
  527. package/src/filters/filters.js +0 -239
  528. package/src/filters/filters.spec.js +0 -36
  529. package/src/filters/filters.test.js +0 -12
  530. package/src/filters/json.md +0 -16
  531. package/src/filters/limit-to.js +0 -55
  532. package/src/filters/limit-to.md +0 -19
  533. package/src/filters/limit-to.spec.js +0 -252
  534. package/src/filters/order-by.js +0 -181
  535. package/src/filters/order-by.md +0 -83
  536. package/src/filters/order-by.spec.js +0 -883
  537. package/src/index.js +0 -6
  538. package/src/index.spec.js +0 -11
  539. package/src/injection-tokens.js +0 -78
  540. package/src/interface.ts +0 -421
  541. package/src/ng.js +0 -289
  542. package/src/ng.spec.js +0 -33
  543. package/src/router/common/trace.js +0 -240
  544. package/src/router/directives/component-example.html +0 -37
  545. package/src/router/directives/state-directives.html +0 -22
  546. package/src/router/directives/state-directives.js +0 -393
  547. package/src/router/directives/state-directives.md +0 -435
  548. package/src/router/directives/state-directives.spec.js +0 -1091
  549. package/src/router/directives/state-directives.test.js +0 -10
  550. package/src/router/directives/view-directive.js +0 -489
  551. package/src/router/directives/view-directive.spec.js +0 -1937
  552. package/src/router/directives/view-directive.test.js +0 -10
  553. package/src/router/directives/view-directives.html +0 -22
  554. package/src/router/glob/glob.html +0 -19
  555. package/src/router/glob/glob.js +0 -102
  556. package/src/router/glob/glob.spec.js +0 -108
  557. package/src/router/glob/glob.test.js +0 -12
  558. package/src/router/hooks/core-resolvables.js +0 -38
  559. package/src/router/hooks/ignored-transition.js +0 -25
  560. package/src/router/hooks/invalid-transition.js +0 -14
  561. package/src/router/hooks/lazy-load.js +0 -104
  562. package/src/router/hooks/on-enter-exit-retain.js +0 -55
  563. package/src/router/hooks/redirect-to.js +0 -38
  564. package/src/router/hooks/resolve.js +0 -57
  565. package/src/router/hooks/update-globals.js +0 -34
  566. package/src/router/hooks/url.js +0 -34
  567. package/src/router/hooks/views.js +0 -41
  568. package/src/router/params/interface.ts +0 -626
  569. package/src/router/params/param-factory.js +0 -23
  570. package/src/router/params/param-type.js +0 -133
  571. package/src/router/params/param-types.js +0 -153
  572. package/src/router/params/param.js +0 -243
  573. package/src/router/params/state-params.js +0 -36
  574. package/src/router/path/path-node.js +0 -78
  575. package/src/router/path/path-utils.js +0 -207
  576. package/src/router/resolve/interface.ts +0 -208
  577. package/src/router/resolve/resolvable.js +0 -123
  578. package/src/router/resolve/resolve-context.js +0 -190
  579. package/src/router/router-test-hashbang.html +0 -45
  580. package/src/router/router-test.html +0 -41
  581. package/src/router/router.html +0 -22
  582. package/src/router/router.js +0 -54
  583. package/src/router/router.test.js +0 -12
  584. package/src/router/services.spec.js +0 -52
  585. package/src/router/state/README.md +0 -21
  586. package/src/router/state/interface.ts +0 -1007
  587. package/src/router/state/state-builder.js +0 -376
  588. package/src/router/state/state-builder.spec.js +0 -86
  589. package/src/router/state/state-matcher.js +0 -64
  590. package/src/router/state/state-object.js +0 -118
  591. package/src/router/state/state-queue-manager.js +0 -95
  592. package/src/router/state/state-registry.js +0 -257
  593. package/src/router/state/state-service.js +0 -699
  594. package/src/router/state/state.html +0 -23
  595. package/src/router/state/state.spec.js +0 -1002
  596. package/src/router/state/state.test.js +0 -12
  597. package/src/router/state/target-state.js +0 -162
  598. package/src/router/state/views.js +0 -195
  599. package/src/router/state-filter.spec.js +0 -139
  600. package/src/router/state-filters.js +0 -46
  601. package/src/router/template-factory.html +0 -19
  602. package/src/router/template-factory.js +0 -249
  603. package/src/router/template-factory.spec.js +0 -155
  604. package/src/router/template-factory.test.js +0 -12
  605. package/src/router/transition/hook-builder.js +0 -133
  606. package/src/router/transition/hook-registry.js +0 -172
  607. package/src/router/transition/interface.js +0 -18
  608. package/src/router/transition/interface.ts +0 -922
  609. package/src/router/transition/reject-factory.js +0 -122
  610. package/src/router/transition/transition-event-type.js +0 -26
  611. package/src/router/transition/transition-hook.js +0 -199
  612. package/src/router/transition/transition-service.js +0 -302
  613. package/src/router/transition/transition.js +0 -652
  614. package/src/router/url/url-config.js +0 -155
  615. package/src/router/url/url-matcher.js +0 -532
  616. package/src/router/url/url-rule.js +0 -231
  617. package/src/router/url/url-rules.js +0 -350
  618. package/src/router/url/url-service.js +0 -446
  619. package/src/router/url/url-service.spec.js +0 -1288
  620. package/src/router/url/url.html +0 -19
  621. package/src/router/url/url.test.js +0 -12
  622. package/src/router/view/interface.ts +0 -51
  623. package/src/router/view/view.html +0 -19
  624. package/src/router/view/view.js +0 -274
  625. package/src/router/view/view.spec.js +0 -100
  626. package/src/router/view/view.test.js +0 -12
  627. package/src/router/view-hook.spec.js +0 -215
  628. package/src/router/view-scroll.js +0 -33
  629. package/src/router/view-scroll.spec.js +0 -72
  630. package/src/services/anchor-scroll.html +0 -76
  631. package/src/services/anchor-scroll.js +0 -147
  632. package/src/services/cookie-reader.js +0 -48
  633. package/src/services/exception/exception-handler.js +0 -75
  634. package/src/services/exception/interface.ts +0 -7
  635. package/src/services/http/http.html +0 -23
  636. package/src/services/http/http.js +0 -922
  637. package/src/services/http/http.md +0 -413
  638. package/src/services/http/http.spec.js +0 -3941
  639. package/src/services/http/http.test.js +0 -11
  640. package/src/services/http/interface.ts +0 -243
  641. package/src/services/http/template-request.spec.js +0 -220
  642. package/src/services/http-backend/http-backend.html +0 -22
  643. package/src/services/http-backend/http-backend.js +0 -158
  644. package/src/services/http-backend/http-backend.spec.js +0 -389
  645. package/src/services/http-backend/http-backend.test.js +0 -12
  646. package/src/services/location/interface.ts +0 -70
  647. package/src/services/location/location.html +0 -22
  648. package/src/services/location/location.js +0 -1006
  649. package/src/services/location/location.spec.js +0 -3792
  650. package/src/services/location/location.test.js +0 -12
  651. package/src/services/log/interface.ts +0 -39
  652. package/src/services/log/log.html +0 -19
  653. package/src/services/log/log.js +0 -74
  654. package/src/services/log/log.spec.js +0 -64
  655. package/src/services/log/log.test.js +0 -12
  656. package/src/services/pubsub/pubsub.html +0 -19
  657. package/src/services/pubsub/pubsub.js +0 -349
  658. package/src/services/pubsub/pubsub.spec.js +0 -400
  659. package/src/services/pubsub/pubsub.test.js +0 -12
  660. package/src/services/sce/sce.html +0 -19
  661. package/src/services/sce/sce.js +0 -847
  662. package/src/services/sce/sce.md +0 -300
  663. package/src/services/sce/sce.spec.js +0 -617
  664. package/src/services/sce/sce.test.js +0 -12
  665. package/src/services/template-cache/interface.ts +0 -10
  666. package/src/services/template-cache/template-cache.html +0 -22
  667. package/src/services/template-cache/template-cache.js +0 -15
  668. package/src/services/template-cache/template-cache.spec.js +0 -134
  669. package/src/services/template-cache/template-cache.test.js +0 -12
  670. package/src/services/template-request.js +0 -142
  671. package/src/shared/cache.js +0 -7
  672. package/src/shared/common.js +0 -438
  673. package/src/shared/common.spec.js +0 -294
  674. package/src/shared/constants.js +0 -21
  675. package/src/shared/dom.js +0 -716
  676. package/src/shared/hof.js +0 -151
  677. package/src/shared/hof.spec.js +0 -60
  678. package/src/shared/interface.ts +0 -21
  679. package/src/shared/min-err.spec.js +0 -178
  680. package/src/shared/noderef.js +0 -225
  681. package/src/shared/predicates.js +0 -34
  682. package/src/shared/queue.js +0 -105
  683. package/src/shared/queue.spec.js +0 -80
  684. package/src/shared/shared.html +0 -24
  685. package/src/shared/shared.test.js +0 -12
  686. package/src/shared/strings.js +0 -142
  687. package/src/shared/strings.spec.js +0 -40
  688. package/src/shared/test-utils.js +0 -47
  689. package/src/shared/url-utils/interface.ts +0 -54
  690. package/src/shared/url-utils/url-utils.html +0 -22
  691. package/src/shared/url-utils/url-utils.js +0 -122
  692. package/src/shared/url-utils/url-utils.spec.js +0 -148
  693. package/src/shared/url-utils/url-utils.test.js +0 -12
  694. package/src/shared/utils.js +0 -1255
  695. package/src/shared/utils.spec.js +0 -178
  696. package/src/src.html +0 -21
  697. package/src/src.test.js +0 -10
  698. package/tsconfig.json +0 -19
  699. package/tsconfig.types.json +0 -14
  700. package/typedoc.json +0 -8
  701. package/utils/express.js +0 -203
  702. package/utils/version.cjs +0 -23
  703. package/vite.config.js +0 -14
@@ -1,2566 +0,0 @@
1
- import { Angular } from "../../angular.js";
2
- import {
3
- createElementFromHTML,
4
- dealoc,
5
- getController,
6
- } from "../../shared/dom.js";
7
- import { hashKey, equals, isNumberNaN } from "../../shared/utils.js";
8
- import { browserTrigger, wait } from "../../shared/test-utils.js";
9
-
10
- describe("select", () => {
11
- let scope;
12
- let formElement;
13
- let element;
14
- let $compile;
15
- let ngModelCtrl;
16
- let selectCtrl;
17
- let renderSpy;
18
- let $rootScope;
19
- const optionAttributesList = [];
20
- let errors = [];
21
-
22
- async function compile(html) {
23
- formElement = createElementFromHTML(`<form name="form">${html}</form>`);
24
- element = formElement.querySelector("select");
25
- $compile(formElement)(scope);
26
- await wait();
27
- ngModelCtrl = getController(element, "ngModel");
28
- }
29
-
30
- function setSelectValue(selectElement, optionIndex) {
31
- const option = selectElement.querySelectorAll("option")[optionIndex];
32
- selectElement.value = option.value;
33
- browserTrigger(element, "change");
34
- }
35
-
36
- function compileRepeatedOptions() {
37
- compile(
38
- '<select ng-model="robot">' +
39
- '<option value="{{item.value}}" ng-repeat="item in robots">{{item.label}}</option>' +
40
- "</select>",
41
- );
42
- }
43
-
44
- function compileGroupedOptions() {
45
- compile(
46
- '<select ng-model="mySelect">' +
47
- '<option ng-repeat="item in values">{{item.name}}</option>' +
48
- '<optgroup ng-repeat="group in groups" label="{{group.name}}">' +
49
- '<option ng-repeat="item in group.values">{{item.name}}</option>' +
50
- "</optgroup>" +
51
- "</select>",
52
- );
53
- }
54
-
55
- function unknownValue(value) {
56
- return `? ${hashKey(value)} ?`;
57
- }
58
-
59
- beforeEach(() => {
60
- dealoc(document.getElementById("app"));
61
- errors = [];
62
- window.angular = new Angular();
63
- window.angular
64
- .module("myModule", ["ng"])
65
- .decorator("$exceptionHandler", function () {
66
- return (exception) => {
67
- errors.push(exception.message);
68
- };
69
- });
70
- let injector = window.angular.bootstrap(document.getElementById("app"), [
71
- "myModule",
72
- ($compileProvider) => {
73
- $compileProvider.directive("spyOnWriteValue", () => ({
74
- require: "select",
75
- link: {
76
- pre(scope, element, attrs, ctrl) {
77
- selectCtrl = ctrl;
78
- renderSpy = jasmine.createSpy("renderSpy");
79
- selectCtrl.ngModelCtrl.$render = renderSpy.and.callFake(
80
- selectCtrl.ngModelCtrl.$render,
81
- );
82
- spyOn(selectCtrl, "writeValue").and.callThrough();
83
- },
84
- },
85
- }));
86
- $compileProvider.directive("myOptions", () => ({
87
- scope: { myOptions: "=" },
88
- replace: true,
89
- template:
90
- '<option value="{{ option.value }}" ng-repeat="option in myOptions">' +
91
- "{{ options.label }}" +
92
- "</option>",
93
- }));
94
-
95
- $compileProvider.directive("exposeAttributes", () => ({
96
- require: "^^select",
97
- link: {
98
- pre(scope, element, attrs, ctrl) {
99
- optionAttributesList.push(attrs);
100
- },
101
- },
102
- }));
103
- },
104
- ]);
105
- injector.invoke((_$rootScope_, _$compile_) => {
106
- scope = _$rootScope_.$new(); // create a child scope because the root scope can't be $destroy-ed
107
- $rootScope = _$rootScope_;
108
- $compile = _$compile_;
109
- formElement = element = null;
110
- });
111
- });
112
-
113
- afterEach(() => {
114
- scope.$destroy(); // disables unknown option work during destruction
115
- dealoc(formElement);
116
- ngModelCtrl = null;
117
- });
118
-
119
- beforeEach(() => {
120
- jasmine.addMatchers({
121
- toEqualSelectWithOptions() {
122
- return {
123
- compare(actual, expected) {
124
- const actualValues = {};
125
- let optionGroup;
126
- let optionValue;
127
- let options = actual.querySelectorAll("option");
128
- for (let i = 0; i < options.length; i++) {
129
- let option = options[i];
130
- optionGroup = option.parentNode.label || "";
131
- actualValues[optionGroup] = actualValues[optionGroup] || [];
132
- // IE9 doesn't populate the label property from the text property like other browsers
133
- optionValue = option.label || option.text;
134
- actualValues[optionGroup].push(
135
- option.selected ? [optionValue] : optionValue,
136
- );
137
- }
138
-
139
- const message = function () {
140
- return `Expected ${toJson(actualValues)} to equal ${toJson(expected)}.`;
141
- };
142
-
143
- return {
144
- pass: equals(expected, actualValues),
145
- message,
146
- };
147
- },
148
- };
149
- },
150
- });
151
- });
152
-
153
- it("should not add options to the select if ngModel is not present", () => {
154
- const scope = $rootScope;
155
- scope.d = "d";
156
- scope.e = "e";
157
- scope.f = "f";
158
-
159
- compile(
160
- "<select>" +
161
- "<option ng-value=\"'a'\">alabel</option>" +
162
- '<option value="b">blabel</option>' +
163
- "<option >c</option>" +
164
- '<option ng-value="d">dlabel</option>' +
165
- '<option value="{{e}}">elabel</option>' +
166
- "<option>{{f}}</option>" +
167
- "</select>",
168
- );
169
-
170
- const selectCtrl = getController(element, "select");
171
-
172
- expect(selectCtrl.hasOption("a")).toBe(false);
173
- expect(selectCtrl.hasOption("b")).toBe(false);
174
- expect(selectCtrl.hasOption("c")).toBe(false);
175
- expect(selectCtrl.hasOption("d")).toBe(false);
176
- expect(selectCtrl.hasOption("e")).toBe(false);
177
- expect(selectCtrl.hasOption("f")).toBe(false);
178
- });
179
-
180
- describe("select-one", () => {
181
- it("should compile children of a select without a ngModel, but not create a model for it", async () => {
182
- compile(
183
- "<select>" +
184
- '<option selected="true">{{a}}</option>' +
185
- '<option value="">{{b}}</option>' +
186
- "<option>C</option>" +
187
- "</select>",
188
- );
189
- scope.a = "foo";
190
- scope.b = "bar";
191
- await wait();
192
- expect(element.textContent).toBe("foobarC");
193
- });
194
-
195
- it("should not interfere with selection via selected attr if ngModel directive is not present", () => {
196
- compile(
197
- "<select>" +
198
- "<option>not me</option>" +
199
- "<option selected>me!</option>" +
200
- "<option>nah</option>" +
201
- "</select>",
202
- );
203
- expect(element.value).toBe("me!");
204
- });
205
-
206
- describe("required state", () => {
207
- it("should set the error if the empty option is selected", async () => {
208
- compile(
209
- '<select name="select" ng-model="selection" required>' +
210
- '<option value=""></option>' +
211
- '<option value="a">A</option>' +
212
- '<option value="b">B</option>' +
213
- "</select>",
214
- );
215
-
216
- scope.selection = "a";
217
- await wait();
218
- expect(element.classList.contains("ng-valid")).toBeTrue();
219
- expect(ngModelCtrl.$error.required).toBeFalsy();
220
-
221
- let options = element.querySelectorAll("option");
222
-
223
- // view -> model
224
- setSelectValue(element, 0);
225
- expect(element.classList.contains("ng-invalid")).toBeTrue();
226
- expect(ngModelCtrl.$error.required).toBeTruthy();
227
-
228
- setSelectValue(element, 1);
229
- expect(element.classList.contains("ng-valid")).toBeTrue();
230
- expect(ngModelCtrl.$error.required).toBeFalsy();
231
-
232
- // // model -> view
233
- scope.$apply("selection = null");
234
- await wait();
235
- options = element.querySelectorAll("option");
236
- expect(options[0].selected).toBe(true);
237
- expect(element.classList.contains("ng-invalid")).toBeTrue();
238
- expect(ngModelCtrl.$error.required).toBeTruthy();
239
- });
240
-
241
- it("should validate with empty option and bound ngRequired", async () => {
242
- compile(
243
- '<select name="select" ng-model="selection" ng-required="required">' +
244
- '<option value=""></option>' +
245
- '<option value="a">A</option>' +
246
- '<option value="b">B</option>' +
247
- "</select>",
248
- );
249
-
250
- scope.required = false;
251
- await wait();
252
- const options = element.querySelectorAll("option");
253
-
254
- setSelectValue(element, 0);
255
- expect(element.classList.contains("ng-valid")).toBeTrue();
256
-
257
- scope.$apply("required = true");
258
- await wait();
259
- expect(element.classList.contains("ng-invalid")).toBeTrue();
260
-
261
- scope.$apply('selection = "a"');
262
- await wait();
263
- expect(element.classList.contains("ng-valid")).toBeTrue();
264
- expect(element.value).toBe("a");
265
-
266
- setSelectValue(element, 0);
267
- expect(element.classList.contains("ng-invalid")).toBeTrue();
268
-
269
- scope.$apply("required = false");
270
- await wait();
271
- expect(element.classList.contains("ng-valid")).toBeTrue();
272
- });
273
-
274
- it("should not be invalid if no required attribute is present", async () => {
275
- compile(
276
- '<select name="select" ng-model="selection">' +
277
- '<option value=""></option>' +
278
- '<option value="c">C</option>' +
279
- "</select>",
280
- );
281
- await wait();
282
- expect(element.classList.contains("ng-valid")).toBeTrue();
283
- expect(element.classList.contains("ng-pristine")).toBeTrue();
284
- });
285
-
286
- it("should NOT set the error if the unknown option is selected", async () => {
287
- compile(
288
- '<select name="select" ng-model="selection" required>' +
289
- '<option value="a">A</option>' +
290
- '<option value="b">B</option>' +
291
- "</select>",
292
- );
293
- scope.selection = "a";
294
- await wait();
295
-
296
- expect(element.classList.contains("ng-valid")).toBeTrue();
297
- expect(ngModelCtrl.$error.required).toBeFalsy();
298
-
299
- scope.$apply('selection = "c"');
300
- await wait();
301
- expect(element.value).toBe(unknownValue("c"));
302
- expect(element.classList.contains("ng-valid")).toBeTrue();
303
- expect(ngModelCtrl.$error.required).toBeFalsy();
304
- });
305
- });
306
-
307
- it("should work with repeated value options", async () => {
308
- scope.robots = ["c3p0", "r2d2"];
309
- scope.robot = "r2d2";
310
- compile(
311
- '<select ng-model="robot">' +
312
- '<option ng-repeat="r in robots">{{r}}</option>' +
313
- "</select>",
314
- );
315
- await wait();
316
- expect(element.value).toBe("r2d2");
317
-
318
- setSelectValue(element, 0);
319
- expect(element.value).toBe("c3p0");
320
- expect(scope.robot).toBe("c3p0");
321
-
322
- scope.robots.unshift("wallee");
323
- await wait();
324
- expect(element.value).toBe("c3p0");
325
- expect(scope.robot).toBe("c3p0");
326
-
327
- scope.robots = ["c3p0+", "r2d2+"];
328
- scope.robot = "r2d2+";
329
- await wait();
330
- expect(element.value).toBe("r2d2+");
331
- expect(scope.robot).toBe("r2d2+");
332
- });
333
-
334
- it("should interpolate select names", async () => {
335
- scope.robots = ["c3p0", "r2d2"];
336
- scope.name = "r2d2";
337
- scope.nameID = 47;
338
- compile(
339
- '<form name="form"><select ng-model="name" name="name{{nameID}}">' +
340
- '<option ng-repeat="r in robots">{{r}}</option>' +
341
- "</select></form>",
342
- );
343
- await wait();
344
- expect(scope.form.name47.$pristine).toBeTruthy();
345
- setSelectValue(element, 0);
346
- expect(scope.form.name47.$dirty).toBeTruthy();
347
- expect(scope.name).toBe("c3p0");
348
- });
349
-
350
- it("should rename select controls in form when interpolated name changes", async () => {
351
- scope.nameID = "A";
352
- compile('<select ng-model="name" name="name{{nameID}}"></select>');
353
- expect(scope.form.nameA.$name).toBe("nameA");
354
- const oldModel = scope.form.nameA;
355
- scope.nameID = "B";
356
- await wait();
357
- expect(scope.form.nameA).toBeUndefined();
358
- expect(scope.form.nameB).toBe(oldModel);
359
- expect(scope.form.nameB.$name).toBe("nameB");
360
- });
361
-
362
- it("should select options in a group when there is a linebreak before an option", async () => {
363
- scope.mySelect = "B";
364
- await wait();
365
-
366
- const select = createElementFromHTML(
367
- '<select ng-model="mySelect">' +
368
- '<optgroup label="first">' +
369
- '<option value="A">A</option>' +
370
- "</optgroup>" +
371
- '<optgroup label="second">\n' +
372
- '<option value="B">B</option>' +
373
- "</optgroup> " +
374
- "</select>",
375
- );
376
-
377
- $compile(select)(scope);
378
- await wait();
379
- expect(select).toEqualSelectWithOptions({
380
- first: ["A"],
381
- second: [["B"]],
382
- });
383
- });
384
-
385
- it("should only call selectCtrl.writeValue after a digest has occurred", async () => {
386
- scope.mySelect = "B";
387
- await wait();
388
- const select = createElementFromHTML(
389
- '<select spy-on-write-value ng-model="mySelect">' +
390
- '<optgroup label="first">' +
391
- '<option value="A">A</option>' +
392
- "</optgroup>" +
393
- '<optgroup label="second">\n' +
394
- '<option value="B">B</option>' +
395
- "</optgroup> " +
396
- "</select>",
397
- );
398
-
399
- $compile(select)(scope);
400
- expect(selectCtrl.writeValue).not.toHaveBeenCalled();
401
- await wait();
402
-
403
- expect(selectCtrl.writeValue).toHaveBeenCalled();
404
- dealoc(select);
405
- });
406
-
407
- it('should remove the "selected" attribute from the previous option when the model changes', async () => {
408
- compile(
409
- '<select name="select" ng-model="selected">' +
410
- '<option value="">--empty--</option>' +
411
- '<option value="a">A</option>' +
412
- '<option value="b">B</option>' +
413
- "</select>",
414
- );
415
- await wait();
416
- let options = element.querySelectorAll("option");
417
- expect(options[0].selected).toBeTrue();
418
- expect(options[1].selected).toBeFalse();
419
- expect(options[2].selected).toBeFalse();
420
-
421
- scope.selected = "a";
422
- await wait();
423
- options = element.querySelectorAll("option");
424
- expect(options.length).toBe(3);
425
- expect(options[0].selected).toBeFalse();
426
- expect(options[1].selected).toBeTrue();
427
- expect(options[2].selected).toBeFalse();
428
-
429
- scope.selected = "b";
430
- await wait();
431
- options = element.querySelectorAll("option");
432
- expect(options[0].selected).toBeFalse();
433
- expect(options[1].selected).toBeFalse();
434
- expect(options[2].selected).toBeTrue();
435
-
436
- // This will select the empty option
437
- scope.selected = null;
438
- await wait();
439
- expect(options[0].selected).toBeTrue();
440
- expect(options[1].selected).toBeFalse();
441
- expect(options[2].selected).toBeFalse();
442
-
443
- // This will add and select the unknown option
444
- scope.selected = "unmatched value";
445
- await wait();
446
- options = element.querySelectorAll("option");
447
-
448
- expect(options[0].selected).toBeTrue();
449
- expect(options[1].selected).toBeFalse();
450
- expect(options[2].selected).toBeFalse();
451
- expect(options[3].selected).toBeFalse();
452
-
453
- // Back to matched value
454
- scope.selected = "b";
455
- await wait();
456
- options = element.querySelectorAll("option");
457
-
458
- expect(options[0].selected).toBeFalse();
459
- expect(options[1].selected).toBeFalse();
460
- expect(options[2].selected).toBeTrue();
461
- });
462
-
463
- describe("empty option", () => {
464
- it("should allow empty option to be added and removed dynamically", async () => {
465
- scope.dynamicOptions = [];
466
- scope.robot = "";
467
- compile(
468
- '<select ng-model="robot">' +
469
- '<option ng-repeat="opt in dynamicOptions" value="{{opt.val}}">{{opt.display}}</option>' +
470
- "</select>",
471
- );
472
- await wait();
473
- expect(element.value).toBe("? string: ?");
474
-
475
- scope.dynamicOptions = [
476
- { val: "", display: "--empty--" },
477
- { val: "x", display: "robot x" },
478
- { val: "y", display: "robot y" },
479
- ];
480
-
481
- await wait();
482
- expect(element.value).toBe("");
483
-
484
- scope.robot = "x";
485
- await wait();
486
- expect(element.value).toBe("x");
487
-
488
- scope.dynamicOptions.shift();
489
- await wait();
490
- expect(element.value).toBe("x");
491
-
492
- scope.robot = undefined;
493
- await wait();
494
-
495
- expect(element.value).toBe("");
496
- });
497
-
498
- it("should cope use a dynamic empty option that is added to a static empty option", async () => {
499
- // We do not make any special provisions for multiple empty options, so this behavior is
500
- // largely untested
501
- scope.dynamicOptions = [];
502
- scope.robot = "x";
503
- compile(
504
- '<select ng-model="robot">' +
505
- '<option value="">--static-select--</option>' +
506
- '<option ng-repeat="opt in dynamicOptions" value="{{opt.val}}">{{opt.display}}</option>' +
507
- "</select>",
508
- );
509
- await wait();
510
- expect(element.value).toBe(unknownValue("x"));
511
-
512
- scope.robot = undefined;
513
- await wait();
514
- expect(element.querySelectorAll("option")[0].selected).toBe(true);
515
- expect(element.querySelectorAll("option")[0].textContent).toBe(
516
- "--static-select--",
517
- );
518
-
519
- scope.dynamicOptions = [
520
- { val: "", display: "--dynamic-select--" },
521
- { val: "x", display: "robot x" },
522
- { val: "y", display: "robot y" },
523
- ];
524
- await wait();
525
- expect(element.value).toBe("");
526
-
527
- scope.dynamicOptions = [];
528
- await wait();
529
- expect(element.value).toBe("");
530
- });
531
-
532
- it("should select the empty option when model is undefined", async () => {
533
- compile(
534
- '<select ng-model="robot">' +
535
- '<option value="">--select--</option>' +
536
- '<option value="x">robot x</option>' +
537
- '<option value="y">robot y</option>' +
538
- "</select>",
539
- );
540
- await wait();
541
- expect(element.value).toBe("");
542
- });
543
-
544
- it("should support defining an empty option anywhere in the option list", async () => {
545
- compile(
546
- '<select ng-model="robot">' +
547
- '<option value="x">robot x</option>' +
548
- '<option value="">--select--</option>' +
549
- '<option value="y">robot y</option>' +
550
- "</select>",
551
- );
552
- await wait();
553
- expect(element.value).toBe("");
554
- });
555
-
556
- it("should set the model to empty string when empty option is selected", async () => {
557
- scope.robot = "x";
558
- compile(
559
- '<select ng-model="robot">' +
560
- '<option value="">--select--</option>' +
561
- '<option value="x">robot x</option>' +
562
- '<option value="y">robot y</option>' +
563
- "</select>",
564
- );
565
- await wait();
566
- expect(element.value).toBe("x");
567
- setSelectValue(element, 0);
568
- await wait();
569
- expect(element.value).toBe("");
570
- expect(scope.robot).toBe("");
571
- });
572
-
573
- it("should remove unknown option when model is undefined", async () => {
574
- scope.robot = "other";
575
- compile(
576
- '<select ng-model="robot">' +
577
- '<option value="">--select--</option>' +
578
- '<option value="x">robot x</option>' +
579
- '<option value="y">robot y</option>' +
580
- "</select>",
581
- );
582
- await wait();
583
- expect(element.value).toBe(unknownValue("other"));
584
-
585
- scope.robot = undefined;
586
- await wait();
587
- expect(element.value).toBe("");
588
- });
589
-
590
- it("should support option without a value attribute", async () => {
591
- compile(
592
- '<select ng-model="robot">' +
593
- "<option>--select--</option>" +
594
- '<option value="x">robot x</option>' +
595
- '<option value="y">robot y</option>' +
596
- "</select>",
597
- );
598
- await wait();
599
- expect(element.value).toBe("? undefined:undefined ?");
600
- });
601
-
602
- it("should support option without a value with other HTML attributes", async () => {
603
- compile(
604
- '<select ng-model="robot">' +
605
- '<option data-foo="bar">--select--</option>' +
606
- '<option value="x">robot x</option>' +
607
- '<option value="y">robot y</option>' +
608
- "</select>",
609
- );
610
- await wait();
611
- expect(element.value).toBe("? undefined:undefined ?");
612
- });
613
-
614
- xdescribe("interactions with repeated options", () => {
615
- it("should select empty option when model is undefined", async () => {
616
- scope.robots = ["c3p0", "r2d2"];
617
- compile(
618
- '<select ng-model="robot">' +
619
- '<option value="">--select--</option>' +
620
- '<option ng-repeat="r in robots">{{r}}</option>' +
621
- "</select>",
622
- );
623
- await wait();
624
- expect(element.value).toBe("");
625
- });
626
-
627
- it("should set model to empty string when selected", async () => {
628
- scope.robots = ["c3p0", "r2d2"];
629
- compile(
630
- '<select ng-model="robot">' +
631
- '<option value="">--select--</option>' +
632
- '<option ng-repeat="r in robots">{{r}}</option>' +
633
- "</select>",
634
- );
635
- await wait();
636
- setSelectValue(element, 1);
637
- expect(element.value).toBe("c3p0");
638
- expect(scope.robot).toBe("c3p0");
639
-
640
- setSelectValue(element, 0);
641
- await wait();
642
- expect(element.value).toBe("");
643
- expect(scope.robot).toBe("");
644
- });
645
-
646
- it("should not break if both the select and repeater models change at once", async () => {
647
- scope.robots = ["c3p0", "r2d2"];
648
- scope.robot = "c3p0";
649
- compile(
650
- '<select ng-model="robot">' +
651
- '<option value="">--select--</option>' +
652
- '<option ng-repeat="r in robots">{{r}}</option>' +
653
- "</select>",
654
- );
655
- await wait();
656
- expect(element.value).toBe("c3p0");
657
-
658
- scope.robots = ["wallee"];
659
- scope.robot = "";
660
- await wait();
661
- expect(element.value).toBe("");
662
- });
663
- });
664
-
665
- it('should add/remove the "selected" attribute when the empty option is selected/unselected', async () => {
666
- compile(
667
- '<select name="select" ng-model="selected">' +
668
- '<option value="">--select--</option>' +
669
- '<option value="a">A</option>' +
670
- '<option value="b">B</option>' +
671
- "</select>",
672
- );
673
- await wait();
674
- let options = element.querySelectorAll("option");
675
- expect(options.length).toBe(3);
676
- expect(options[0].selected).toBeTrue();
677
- expect(options[1].selected).toBeFalse();
678
- expect(options[2].selected).toBeFalse();
679
-
680
- scope.selected = "a";
681
- await wait();
682
- options = element.querySelectorAll("option");
683
- expect(options.length).toBe(3);
684
- expect(options[0].selected).toBeFalse();
685
- expect(options[1].selected).toBeTrue();
686
- expect(options[2].selected).toBeFalse();
687
-
688
- scope.selected = "no match";
689
- await wait();
690
- options = element.querySelectorAll("option");
691
- expect(options[0].selected).toBeTrue();
692
- expect(options[1].selected).toBeFalse();
693
- expect(options[2].selected).toBeFalse();
694
- });
695
- });
696
-
697
- describe("unknown option", () => {
698
- it("should insert&select temporary unknown option when no options-model match", async () => {
699
- compile(
700
- '<select ng-model="robot">' +
701
- "<option>c3p0</option>" +
702
- "<option>r2d2</option>" +
703
- "</select>",
704
- );
705
- await wait();
706
- expect(element.value).toBe(`? undefined:undefined ?`);
707
-
708
- scope.$apply(() => {
709
- scope.robot = "r2d2";
710
- });
711
- await wait();
712
- expect(element.value).toBe("r2d2");
713
-
714
- scope.$apply(() => {
715
- scope.robot = "wallee";
716
- });
717
- await wait();
718
- expect(element.value).toBe(unknownValue("wallee"));
719
- });
720
-
721
- it("should NOT insert temporary unknown option when model is undefined and empty options is present", async () => {
722
- compile(
723
- '<select ng-model="robot">' +
724
- '<option value="">--select--</option>' +
725
- "<option>c3p0</option>" +
726
- "<option>r2d2</option>" +
727
- "</select>",
728
- );
729
- await wait();
730
- expect(element.value).toBe("");
731
- expect(scope.robot).toBeUndefined();
732
-
733
- scope.$apply(() => {
734
- scope.robot = null;
735
- });
736
- await wait();
737
- expect(element.value).toBe("");
738
-
739
- scope.$apply(() => {
740
- scope.robot = "r2d2";
741
- });
742
- await wait();
743
- expect(element.value).toBe("r2d2");
744
-
745
- scope.$apply(() => {
746
- delete scope.robot;
747
- });
748
- await wait();
749
- expect(element.value).toBe("");
750
- });
751
-
752
- it(
753
- "should insert&select temporary unknown option when no options-model match, empty " +
754
- "option is present and model is defined",
755
- async () => {
756
- scope.robot = "wallee";
757
- compile(
758
- '<select ng-model="robot">' +
759
- '<option value="">--select--</option>' +
760
- "<option>c3p0</option>" +
761
- "<option>r2d2</option>" +
762
- "</select>",
763
- );
764
- await wait();
765
- expect(element.value).toBe(unknownValue("wallee"));
766
-
767
- scope.$apply(() => {
768
- scope.robot = "r2d2";
769
- });
770
- await wait();
771
- expect(element.value).toBe("r2d2");
772
- },
773
- );
774
-
775
- describe("interactions with repeated options", () => {
776
- it("should work with repeated options", async () => {
777
- compile(
778
- '<select ng-model="robot">' +
779
- '<option ng-repeat="r in robots">{{r}}</option>' +
780
- "</select>",
781
- );
782
- await wait();
783
- expect(element.value).toBe(`? undefined:undefined ?`);
784
- expect(scope.robot).toBeUndefined();
785
-
786
- scope.$apply(() => {
787
- scope.robot = "r2d2";
788
- });
789
- await wait();
790
- expect(element.value).toBe(unknownValue("r2d2"));
791
- expect(scope.robot).toBe("r2d2");
792
-
793
- scope.$apply(() => {
794
- scope.robots = ["c3p0", "r2d2"];
795
- });
796
- await wait();
797
- expect(element.value).toBe("r2d2");
798
- expect(scope.robot).toBe("r2d2");
799
- });
800
-
801
- it("should work with empty option and repeated options", async () => {
802
- compile(
803
- '<select ng-model="robot">' +
804
- '<option value="">--select--</option>' +
805
- '<option ng-repeat="r in robots">{{r}}</option>' +
806
- "</select>",
807
- );
808
- await wait();
809
- expect(element.value).toBe("");
810
- expect(scope.robot).toBeUndefined();
811
-
812
- scope.$apply(() => {
813
- scope.robot = "r2d2";
814
- });
815
- await wait();
816
- expect(element.value).toBe(unknownValue("r2d2"));
817
- expect(scope.robot).toBe("r2d2");
818
-
819
- scope.$apply(() => {
820
- scope.robots = ["c3p0", "r2d2"];
821
- });
822
- await wait();
823
- expect(element.value).toBe("r2d2");
824
- expect(scope.robot).toBe("r2d2");
825
- });
826
-
827
- it("should insert unknown element when repeater shrinks and selected option is unavailable", async () => {
828
- scope.robots = ["c3p0", "r2d2"];
829
- scope.robot = "r2d2";
830
- compile(
831
- '<select ng-model="robot">' +
832
- '<option ng-repeat="r in robots">{{r}}</option>' +
833
- "</select>",
834
- );
835
- await wait();
836
- expect(element.value).toBe("r2d2");
837
- expect(scope.robot).toBe("r2d2");
838
-
839
- scope.robots = ["c3p0"];
840
- await wait();
841
-
842
- expect(element.value).toBe("c3p0");
843
-
844
- // TODO we can add a mutation observer to trigger the render but it seems like an overkill for this case
845
- // as none of the behavior below is 'expected' when mutating the array of robots.
846
- // expect(scope.robot).toBe(null);
847
-
848
- // scope.$apply(() => {
849
- // scope.robots.unshift("r2d2");
850
- // });
851
- // await wait();
852
- // expect(element.value).toBe("r2d2");
853
- // expect(scope.robot).toBe(null);
854
-
855
- // scope.$apply(() => {
856
- // scope.robot = "r2d2";
857
- // });
858
- // await wait();
859
- // expect(element.value).toBe("r2d2");
860
-
861
- // scope.$apply(() => {
862
- // delete scope.robots;
863
- // });
864
- // await wait();
865
- // expect(element.value).toBe(unknownValue(null));
866
- // expect(scope.robot).toBe(null);
867
- });
868
- });
869
- });
870
-
871
- it("should not break when adding options via a directive with `replace: true` and a structural directive in its template", async () => {
872
- scope.options = [
873
- { value: "1", label: "Option 1" },
874
- { value: "2", label: "Option 2" },
875
- { value: "3", label: "Option 3" },
876
- ];
877
- compile(
878
- '<select ng-model="mySelect"><option my-options="options"></option></select>',
879
- );
880
- await wait();
881
- expect(element.value).toBe("? undefined:undefined ?");
882
- });
883
-
884
- it("should not throw when removing the element and all its children", async () => {
885
- const template =
886
- '<select ng-model="mySelect" ng-if="visible">' +
887
- '<option value="">--- Select ---</option>' +
888
- "</select>";
889
- scope.visible = true;
890
-
891
- compile(template);
892
-
893
- // It should not throw when removing the element
894
- scope.$apply("visible = false");
895
- await wait();
896
- expect(true).toBeTruthy();
897
- });
898
- });
899
-
900
- describe("selectController", () => {
901
- it("should expose .$hasEmptyOption(), .$isEmptyOptionSelected(), and .$isUnknownOptionSelected()", async () => {
902
- compile('<select ng-model="mySelect"></select>');
903
-
904
- const selectCtrl = getController(element, "select");
905
- await wait();
906
- expect(selectCtrl.$hasEmptyOption).toEqual(jasmine.any(Function));
907
- expect(selectCtrl.$isEmptyOptionSelected).toEqual(jasmine.any(Function));
908
- expect(selectCtrl.$isUnknownOptionSelected).toEqual(
909
- jasmine.any(Function),
910
- );
911
- });
912
-
913
- it("should reflect the status of empty and unknown option", async () => {
914
- scope.dynamicOptions = [];
915
- scope.selected = "";
916
- compile(
917
- '<select ng-model="selected">' +
918
- '<option ng-if="empty" value="">--no selection--</option>' +
919
- '<option ng-repeat="opt in dynamicOptions" value="{{opt.val}}">{{opt.display}}</option>' +
920
- "</select>",
921
- );
922
- await wait();
923
- const selectCtrl = getController(element, "select");
924
- expect(element.value).toBe("? string: ?");
925
- expect(selectCtrl.$hasEmptyOption()).toBe(false);
926
- expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
927
-
928
- scope.dynamicOptions = [
929
- { val: "x", display: "robot x" },
930
- { val: "y", display: "robot y" },
931
- ];
932
- scope.empty = true;
933
- await wait();
934
- expect(element.value).toBe("");
935
- expect(selectCtrl.$hasEmptyOption()).toBe(true);
936
- expect(selectCtrl.$isEmptyOptionSelected()).toBe(true);
937
- expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
938
-
939
- // empty -> selection
940
- scope.$apply('selected = "x"');
941
- await wait();
942
- expect(element.value).toBe("x");
943
- expect(selectCtrl.$hasEmptyOption()).toBe(true);
944
- expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
945
- expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
946
-
947
- // // remove empty
948
- // scope.$apply("empty = false");
949
- // await wait();
950
- // expect(element.value).toBe("x");
951
- // expect(selectCtrl.$hasEmptyOption()).toBe(false);
952
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
953
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
954
-
955
- // // selection -> unknown
956
- // scope.$apply('selected = "unmatched"');
957
- // await wait();
958
- // expect(element.value).toBe(unknownValue("unmatched"));
959
- // expect(selectCtrl.$hasEmptyOption()).toBe(false);
960
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
961
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(true);
962
-
963
- // // add empty
964
- // scope.$apply("empty = true");
965
- // await wait();
966
- // expect(element.value).toBe(unknownValue("unmatched"));
967
- // expect(selectCtrl.$hasEmptyOption()).toBe(true);
968
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
969
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(true);
970
-
971
- // // unknown -> empty
972
- // scope.$apply("selected = null");
973
- // await wait();
974
- // expect(element.value).toBe("");
975
- // expect(selectCtrl.$hasEmptyOption()).toBe(true);
976
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(true);
977
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
978
-
979
- // // empty -> unknown
980
- // scope.$apply('selected = "unmatched"');
981
- // await wait();
982
- // expect(element.value).toBe(unknownValue("unmatched"));
983
- // expect(selectCtrl.$hasEmptyOption()).toBe(true);
984
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
985
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(true);
986
-
987
- // // unknown -> selection
988
- // scope.$apply('selected = "y"');
989
- // await wait();
990
- // expect(element.value).toBe("y");
991
- // expect(selectCtrl.$hasEmptyOption()).toBe(true);
992
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
993
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
994
-
995
- // // selection -> empty
996
- // scope.$apply("selected = null");
997
- // await wait();
998
- // expect(element.value).toBe("");
999
- // expect(selectCtrl.$hasEmptyOption()).toBe(true);
1000
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(true);
1001
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
1002
- });
1003
- });
1004
-
1005
- describe("selectController.hasOption", () => {
1006
- describe("flat options", () => {
1007
- it("should return false for options shifted via ngRepeat", async () => {
1008
- scope.robots = [
1009
- { value: 1, label: "c3p0" },
1010
- { value: 2, label: "r2d2" },
1011
- ];
1012
-
1013
- compileRepeatedOptions();
1014
-
1015
- const selectCtrl = getController(element, "select");
1016
-
1017
- scope.$apply(() => {
1018
- scope.robots.shift();
1019
- });
1020
- await wait();
1021
- expect(selectCtrl.hasOption("1")).toBe(false);
1022
- expect(selectCtrl.hasOption("2")).toBe(true);
1023
- });
1024
-
1025
- xit("should return false for options popped via ngRepeat", async () => {
1026
- scope.robots = [
1027
- { value: 1, label: "c3p0" },
1028
- { value: 2, label: "r2d2" },
1029
- ];
1030
-
1031
- compileRepeatedOptions();
1032
- await wait();
1033
- const selectCtrl = getController(element, "select");
1034
-
1035
- scope.$apply(() => {
1036
- scope.robots.pop();
1037
- });
1038
- await wait();
1039
- expect(selectCtrl.hasOption("1")).toBe(true);
1040
- expect(selectCtrl.hasOption("2")).toBe(false);
1041
- });
1042
-
1043
- it("should return true for options added via ngRepeat", async () => {
1044
- scope.robots = [{ value: 2, label: "r2d2" }];
1045
-
1046
- compileRepeatedOptions();
1047
-
1048
- const selectCtrl = getController(element, "select");
1049
-
1050
- scope.$apply(() => {
1051
- scope.robots.unshift({ value: 1, label: "c3p0" });
1052
- });
1053
- await wait();
1054
- expect(selectCtrl.hasOption("1")).toBe(true);
1055
- expect(selectCtrl.hasOption("2")).toBe(true);
1056
- });
1057
-
1058
- it("should keep all the options when changing the model", async () => {
1059
- compile(
1060
- "<select ng-model=\"mySelect\"><option ng-repeat=\"o in ['A','B','C']\">{{o}}</option></select>",
1061
- );
1062
-
1063
- const selectCtrl = getController(element, "select");
1064
-
1065
- scope.$apply(() => {
1066
- scope.mySelect = "C";
1067
- });
1068
- await wait();
1069
- expect(selectCtrl.hasOption("A")).toBe(true);
1070
- expect(selectCtrl.hasOption("B")).toBe(true);
1071
- expect(selectCtrl.hasOption("C")).toBe(true);
1072
- expect(element).toEqualSelectWithOptions({ "": ["A", "B", ["C"]] });
1073
- });
1074
- });
1075
-
1076
- describe("grouped options", () => {
1077
- it("should be able to detect when elements move from a previous group", async () => {
1078
- scope.values = [{ name: "A" }];
1079
- scope.groups = [
1080
- {
1081
- name: "first",
1082
- values: [{ name: "B" }, { name: "C" }, { name: "D" }],
1083
- },
1084
- {
1085
- name: "second",
1086
- values: [{ name: "E" }],
1087
- },
1088
- ];
1089
-
1090
- compileGroupedOptions();
1091
-
1092
- const selectCtrl = getController(element, "select");
1093
-
1094
- scope.$apply(() => {
1095
- const itemD = scope.groups[0].values.pop();
1096
- scope.groups[1].values.unshift(itemD);
1097
- scope.values.shift();
1098
- });
1099
- await wait();
1100
- expect(selectCtrl.hasOption("A")).toBe(false);
1101
- expect(selectCtrl.hasOption("B")).toBe(true);
1102
- expect(selectCtrl.hasOption("C")).toBe(true);
1103
- expect(selectCtrl.hasOption("D")).toBe(true);
1104
- expect(selectCtrl.hasOption("E")).toBe(true);
1105
- expect(element).toEqualSelectWithOptions({
1106
- "": [[""]],
1107
- first: ["B", "C"],
1108
- second: ["D", "E"],
1109
- });
1110
- });
1111
-
1112
- it("should be able to detect when elements move from a following group", async () => {
1113
- scope.values = [{ name: "A" }];
1114
- scope.groups = [
1115
- {
1116
- name: "first",
1117
- values: [{ name: "B" }, { name: "C" }],
1118
- },
1119
- {
1120
- name: "second",
1121
- values: [{ name: "D" }, { name: "E" }],
1122
- },
1123
- ];
1124
-
1125
- compileGroupedOptions();
1126
-
1127
- const selectCtrl = getController(element, "select");
1128
-
1129
- scope.$apply(() => {
1130
- const itemD = scope.groups[1].values.shift();
1131
- scope.groups[0].values.push(itemD);
1132
- scope.values.shift();
1133
- });
1134
- await wait();
1135
- expect(selectCtrl.hasOption("A")).toBe(false);
1136
- expect(selectCtrl.hasOption("B")).toBe(true);
1137
- expect(selectCtrl.hasOption("C")).toBe(true);
1138
- expect(selectCtrl.hasOption("D")).toBe(true);
1139
- expect(selectCtrl.hasOption("E")).toBe(true);
1140
- expect(element).toEqualSelectWithOptions({
1141
- "": [[""]],
1142
- first: ["B", "C", "D"],
1143
- second: ["E"],
1144
- });
1145
- });
1146
-
1147
- it("should be able to detect when an element is replaced with an element from a previous group", async () => {
1148
- scope.values = [{ name: "A" }];
1149
- scope.groups = [
1150
- {
1151
- name: "first",
1152
- values: [{ name: "B" }, { name: "C" }, { name: "D" }],
1153
- },
1154
- {
1155
- name: "second",
1156
- values: [{ name: "E" }, { name: "F" }],
1157
- },
1158
- ];
1159
-
1160
- compileGroupedOptions();
1161
-
1162
- const selectCtrl = getController(element, "select");
1163
-
1164
- scope.$apply(() => {
1165
- const itemD = scope.groups[0].values.pop();
1166
- scope.groups[1].values.unshift(itemD);
1167
- scope.groups[1].values.pop();
1168
- });
1169
- await wait();
1170
- expect(selectCtrl.hasOption("A")).toBe(true);
1171
- expect(selectCtrl.hasOption("B")).toBe(true);
1172
- expect(selectCtrl.hasOption("C")).toBe(true);
1173
- expect(selectCtrl.hasOption("D")).toBe(true);
1174
- expect(selectCtrl.hasOption("E")).toBe(true);
1175
- expect(selectCtrl.hasOption("F")).toBe(false);
1176
- expect(element).toEqualSelectWithOptions({
1177
- "": [[""], "A"],
1178
- first: ["B", "C"],
1179
- second: ["D", "E"],
1180
- });
1181
- });
1182
-
1183
- it("should be able to detect when element is replaced with an element from a following group", async () => {
1184
- scope.values = [{ name: "A" }];
1185
- scope.groups = [
1186
- {
1187
- name: "first",
1188
- values: [{ name: "B" }, { name: "C" }],
1189
- },
1190
- {
1191
- name: "second",
1192
- values: [{ name: "D" }, { name: "E" }],
1193
- },
1194
- ];
1195
-
1196
- compileGroupedOptions();
1197
-
1198
- const selectCtrl = getController(element, "select");
1199
-
1200
- scope.$apply(() => {
1201
- scope.groups[0].values.pop();
1202
- const itemD = scope.groups[1].values.shift();
1203
- scope.groups[0].values.push(itemD);
1204
- });
1205
- await wait();
1206
- expect(selectCtrl.hasOption("A")).toBe(true);
1207
- expect(selectCtrl.hasOption("B")).toBe(true);
1208
- expect(selectCtrl.hasOption("C")).toBe(false);
1209
- expect(selectCtrl.hasOption("D")).toBe(true);
1210
- expect(selectCtrl.hasOption("E")).toBe(true);
1211
- expect(element).toEqualSelectWithOptions({
1212
- "": [[""], "A"],
1213
- first: ["B", "D"],
1214
- second: ["E"],
1215
- });
1216
- });
1217
-
1218
- xit("should be able to detect when an element is removed", async () => {
1219
- scope.values = [{ name: "A" }];
1220
- scope.groups = [
1221
- {
1222
- name: "first",
1223
- values: [{ name: "B" }, { name: "C" }],
1224
- },
1225
- {
1226
- name: "second",
1227
- values: [{ name: "D" }, { name: "E" }],
1228
- },
1229
- ];
1230
-
1231
- compileGroupedOptions();
1232
- await wait();
1233
- const selectCtrl = getController(element, "select");
1234
-
1235
- scope.groups[1].values.shift();
1236
- await wait();
1237
- expect(selectCtrl.hasOption("A")).toBe(true);
1238
- expect(selectCtrl.hasOption("B")).toBe(true);
1239
- expect(selectCtrl.hasOption("C")).toBe(true);
1240
- expect(selectCtrl.hasOption("D")).toBe(false);
1241
- expect(selectCtrl.hasOption("E")).toBe(true);
1242
- expect(element).toEqualSelectWithOptions({
1243
- "": [[""], "A"],
1244
- first: ["B", "C"],
1245
- second: ["E"],
1246
- });
1247
- });
1248
-
1249
- it("should be able to detect when a group is removed", async () => {
1250
- scope.values = [{ name: "A" }];
1251
- scope.groups = [
1252
- {
1253
- name: "first",
1254
- values: [{ name: "B" }, { name: "C" }],
1255
- },
1256
- {
1257
- name: "second",
1258
- values: [{ name: "D" }, { name: "E" }],
1259
- },
1260
- ];
1261
-
1262
- compileGroupedOptions();
1263
-
1264
- const selectCtrl = getController(element, "select");
1265
-
1266
- scope.$apply(() => {
1267
- scope.groups.pop();
1268
- });
1269
- await wait();
1270
- expect(selectCtrl.hasOption("A")).toBe(true);
1271
- expect(selectCtrl.hasOption("B")).toBe(true);
1272
- expect(selectCtrl.hasOption("C")).toBe(true);
1273
- expect(selectCtrl.hasOption("D")).toBe(false);
1274
- expect(selectCtrl.hasOption("E")).toBe(false);
1275
- expect(element).toEqualSelectWithOptions({
1276
- "": [[""], "A"],
1277
- first: ["B", "C"],
1278
- });
1279
- });
1280
- });
1281
- });
1282
-
1283
- describe("select-multiple", () => {
1284
- xit('should support type="select-multiple"', async () => {
1285
- compile(
1286
- '<select ng-model="selection" multiple>' +
1287
- "<option>A</option>" +
1288
- "<option>B</option>" +
1289
- "</select>",
1290
- );
1291
-
1292
- scope.$apply(() => {
1293
- scope.selection = ["A"];
1294
- });
1295
- await wait();
1296
- let optionElements = element.querySelectorAll("option");
1297
-
1298
- expect(element.value).toBe("A");
1299
- expect(optionElements[0].selected).toBeTrue();
1300
- expect(optionElements[1].selected).toBeFalse();
1301
-
1302
- scope.$apply(() => {
1303
- scope.selection.push("B");
1304
- });
1305
- await wait();
1306
- optionElements = element.querySelectorAll("option");
1307
-
1308
- expect(element.value).toBe("A");
1309
- expect(optionElements[0].selected).toBeTrue();
1310
- expect(optionElements[1].selected).toBeTrue();
1311
- });
1312
-
1313
- it("should work with optgroups", async () => {
1314
- compile(
1315
- '<select ng-model="selection" multiple>' +
1316
- '<optgroup label="group1">' +
1317
- "<option>A</option>" +
1318
- "<option>B</option>" +
1319
- "</optgroup>" +
1320
- "</select>",
1321
- );
1322
- await wait();
1323
- expect(element.value).toBe("");
1324
- expect(scope.selection).toBeUndefined();
1325
-
1326
- scope.$apply(() => {
1327
- scope.selection = ["A"];
1328
- });
1329
- await wait();
1330
- expect(element.value).toBe("A");
1331
-
1332
- scope.$apply(() => {
1333
- scope.selection.push("B");
1334
- });
1335
- await wait();
1336
- expect(element.value).toBe("A");
1337
- });
1338
-
1339
- it("should require", async () => {
1340
- compile(
1341
- '<select name="select" ng-model="selection" multiple required>' +
1342
- "<option>A</option>" +
1343
- "<option>B</option>" +
1344
- "</select>",
1345
- );
1346
-
1347
- scope.$apply(() => {
1348
- scope.selection = [];
1349
- });
1350
- await wait();
1351
- expect(scope.form.select.$error.required).toBeTruthy();
1352
- expect(element.classList.contains("ng-invalid")).toBeTrue();
1353
- expect(element.classList.contains("ng-pristine")).toBeTrue();
1354
-
1355
- scope.$apply(() => {
1356
- scope.selection = ["A"];
1357
- });
1358
- await wait();
1359
- expect(element.classList.contains("ng-valid")).toBeTrue();
1360
- expect(element.classList.contains("ng-pristine")).toBeTrue();
1361
-
1362
- element.value = "B";
1363
- browserTrigger(element, "change");
1364
- expect(element.classList.contains("ng-valid")).toBeTrue();
1365
- expect(element.classList.contains("ng-dirty")).toBeTrue();
1366
- });
1367
-
1368
- describe("calls to $render", () => {
1369
- let ngModelCtrl;
1370
-
1371
- beforeEach(() => {
1372
- compile(
1373
- '<select name="select" ng-model="selection" multiple>' +
1374
- "<option>A</option>" +
1375
- "<option>B</option>" +
1376
- "</select>",
1377
- );
1378
-
1379
- ngModelCtrl = getController(element, "ngModel");
1380
- spyOn(ngModelCtrl, "$render").and.callThrough();
1381
- });
1382
-
1383
- xit("should call $render once when the reference to the viewValue changes", async () => {
1384
- scope.$apply(() => {
1385
- scope.selection = ["A"];
1386
- });
1387
- await wait();
1388
- expect(ngModelCtrl.$render).toHaveBeenCalledTimes(1);
1389
-
1390
- scope.$apply(() => {
1391
- scope.selection = ["A", "B"];
1392
- });
1393
- await wait();
1394
- expect(ngModelCtrl.$render).toHaveBeenCalledTimes(2);
1395
-
1396
- scope.$apply(() => {
1397
- scope.selection = [];
1398
- });
1399
- await wait();
1400
- expect(ngModelCtrl.$render).toHaveBeenCalledTimes(3);
1401
- });
1402
-
1403
- xit("should call $render once when the viewValue deep-changes", async () => {
1404
- scope.$apply(() => {
1405
- scope.selection = ["A"];
1406
- });
1407
- await wait();
1408
- expect(ngModelCtrl.$render).toHaveBeenCalledTimes(1);
1409
-
1410
- scope.$apply(() => {
1411
- scope.selection.push("B");
1412
- });
1413
- await wait();
1414
- expect(ngModelCtrl.$render).toHaveBeenCalledTimes(2);
1415
-
1416
- scope.$apply(() => {
1417
- scope.selection.length = 0;
1418
- });
1419
- await wait();
1420
- expect(ngModelCtrl.$render).toHaveBeenCalledTimes(3);
1421
- });
1422
- });
1423
- });
1424
-
1425
- describe("option", () => {
1426
- it("should populate a missing value attribute with the option text", async () => {
1427
- compile('<select ng-model="x"><option selected>abc</option></select>');
1428
- await wait();
1429
- expect(element.value).toBe(`? undefined:undefined ?`);
1430
- });
1431
-
1432
- it("should ignore the option text if the value attribute exists", async () => {
1433
- compile('<select ng-model="x"><option value="abc">xyz</option></select>');
1434
- await wait();
1435
- expect(element.value).toBe(`? undefined:undefined ?`);
1436
- });
1437
-
1438
- it("should set value even if self closing HTML", async () => {
1439
- scope.x = "hello";
1440
- compile('<select ng-model="x"><option>hello</select>');
1441
- await wait();
1442
- expect(element.value).toBe("hello");
1443
- });
1444
-
1445
- it("should add options with interpolated value attributes", async () => {
1446
- scope.option1 = "option1";
1447
- scope.option2 = "option2";
1448
-
1449
- compile(
1450
- '<select ng-model="selected">' +
1451
- '<option value="{{option1}}">Option 1</option>' +
1452
- '<option value="{{option2}}">Option 2</option>' +
1453
- "</select>",
1454
- );
1455
- await wait();
1456
- expect(scope.selected).toBeUndefined();
1457
-
1458
- setSelectValue(element, 0);
1459
- await wait();
1460
- expect(scope.selected).toBe("option1");
1461
-
1462
- scope.selected = "option2";
1463
- await wait();
1464
- expect(element.querySelectorAll("option")[0].selected).toBe(false);
1465
- expect(element.querySelectorAll("option")[0].textContent).toBe(
1466
- "Option 1",
1467
- );
1468
- expect(element.querySelectorAll("option")[1].selected).toBe(true);
1469
- expect(element.querySelectorAll("option")[1].textContent).toBe(
1470
- "Option 2",
1471
- );
1472
- });
1473
-
1474
- it("should update the option when the interpolated value attribute changes", async () => {
1475
- scope.option1 = "option1";
1476
- scope.option2 = "";
1477
-
1478
- compile(
1479
- '<select ng-model="selected">' +
1480
- '<option value="{{option1}}">Option 1</option>' +
1481
- '<option value="{{option2}}">Option 2</option>' +
1482
- "</select>",
1483
- );
1484
- await wait();
1485
- const selectCtrl = getController(element, "select");
1486
- spyOn(selectCtrl, "removeOption").and.callThrough();
1487
-
1488
- expect(scope.selected).toBeUndefined();
1489
- expect(selectCtrl.removeOption).not.toHaveBeenCalled();
1490
-
1491
- // Change value of option2
1492
- scope.option2 = "option2Changed";
1493
- scope.selected = "option2Changed";
1494
- await wait();
1495
- expect(selectCtrl.removeOption).toHaveBeenCalledWith("");
1496
- expect(element.querySelectorAll("option")[0].selected).toBe(false);
1497
- expect(element.querySelectorAll("option")[0].textContent).toBe(
1498
- "Option 1",
1499
- );
1500
- expect(element.querySelectorAll("option")[1].selected).toBe(true);
1501
- expect(element.querySelectorAll("option")[1].textContent).toBe(
1502
- "Option 2",
1503
- );
1504
- });
1505
-
1506
- it("should add options with interpolated text", async () => {
1507
- scope.option1 = "Option 1";
1508
- scope.option2 = "Option 2";
1509
-
1510
- compile(
1511
- '<select ng-model="selected">' +
1512
- "<option>{{option1}}</option>" +
1513
- "<option>{{option2}}</option>" +
1514
- "</select>",
1515
- );
1516
-
1517
- await wait();
1518
- expect(scope.selected).toBeUndefined();
1519
- setSelectValue(element, 0);
1520
- await wait();
1521
- expect(element.querySelectorAll("option")[0].selected).toBe(true);
1522
- expect(element.querySelectorAll("option")[0].textContent).toBe(
1523
- "Option 1",
1524
- );
1525
- expect(scope.selected).toBe("Option 1");
1526
-
1527
- scope.selected = "Option 2";
1528
- await wait();
1529
- expect(element.querySelectorAll("option")[1].selected).toBe(true);
1530
- expect(element.querySelectorAll("option")[1].textContent).toBe(
1531
- "Option 2",
1532
- );
1533
- });
1534
-
1535
- xit("should update options when their interpolated text changes", async () => {
1536
- scope.option1 = "Option 1";
1537
- scope.option2 = "";
1538
-
1539
- compile(
1540
- '<select ng-model="selected">' +
1541
- "<option>{{option1}}</option>" +
1542
- "<option>{{option2}}</option>" +
1543
- "</select>",
1544
- );
1545
- await wait();
1546
- const selectCtrl = getController(element, "select");
1547
- spyOn(selectCtrl, "removeOption").and.callThrough();
1548
-
1549
- expect(scope.selected).toBeUndefined();
1550
- expect(selectCtrl.removeOption).not.toHaveBeenCalled();
1551
-
1552
- // Change value of option2
1553
- scope.option2 = "Option 2 Changed";
1554
- scope.selected = "Option 2 Changed";
1555
- await wait();
1556
- expect(selectCtrl.removeOption).toHaveBeenCalledWith("");
1557
- expect(element.querySelectorAll("option")[1].selected).toBe(true);
1558
- expect(element.querySelectorAll("option")[1].textContent).toBe(
1559
- "Option 2 Changed",
1560
- );
1561
- });
1562
-
1563
- xit("should not blow up when option directive is found inside of a datalist", async () => {
1564
- const element = $compile(
1565
- "<div>" +
1566
- "<datalist><option>some val</option></datalist>" +
1567
- "<span>{{foo}}</span>" +
1568
- "</div>",
1569
- )($rootScope);
1570
-
1571
- $rootScope.foo = "success";
1572
- await wait();
1573
- expect(element.querySelectorAll("span").textContent).toBe("success");
1574
- });
1575
-
1576
- it('should throw an exception if an option value interpolates to "hasOwnProperty"', async () => {
1577
- scope.hasOwnPropertyOption = "hasOwnProperty";
1578
- compile(
1579
- '<select ng-model="x">' +
1580
- "<option>{{hasOwnPropertyOption}}</option>" +
1581
- "</select>",
1582
- );
1583
- expect(errors[0]).toMatch(/badname/);
1584
- });
1585
-
1586
- describe("with ngValue (and non-primitive values)", () => {
1587
- [
1588
- "string",
1589
- undefined,
1590
- 1,
1591
- true,
1592
- null,
1593
- { prop: "value" },
1594
- ["a"],
1595
- NaN,
1596
- ].forEach((prop) => {
1597
- xit("should set the option attribute and select it for value $prop", async () => {
1598
- scope.option1 = prop;
1599
- scope.option2 = "red";
1600
- scope.selected = "NOMATCH";
1601
-
1602
- compile(
1603
- '<select ng-model="selected">' +
1604
- '<option ng-value="option1">{{option1}}</option>' +
1605
- '<option ng-value="option2">{{option2}}</option>' +
1606
- "</select>",
1607
- );
1608
- await wait();
1609
- expect(element.querySelectorAll("option")[0].value).toBe(
1610
- "? string:NOMATCH ?",
1611
- );
1612
-
1613
- scope.selected = prop;
1614
- await wait();
1615
- expect(element.querySelectorAll("option")[0].value).toBe(
1616
- hashKey(prop),
1617
- );
1618
-
1619
- // Reset
1620
- scope.selected = false;
1621
- await wait();
1622
- expect(element.querySelectorAll("option")[0].value).toBe(
1623
- "? boolean:false ?",
1624
- );
1625
-
1626
- setSelectValue(element, 0);
1627
- await wait();
1628
- if (isNumberNaN(prop)) {
1629
- expect(scope.selected).toBeNaN();
1630
- } else {
1631
- expect(scope.selected).toBe(prop);
1632
- }
1633
- });
1634
- });
1635
-
1636
- [
1637
- "string",
1638
- undefined,
1639
- 1,
1640
- true,
1641
- null,
1642
- { prop: "value" },
1643
- ["a"],
1644
- NaN,
1645
- ].forEach((prop) => {
1646
- xit("should update the option attribute and select it for value $prop", async () => {
1647
- scope.option = prop;
1648
- scope.option2 = "red";
1649
- scope.selected = "NOMATCH";
1650
-
1651
- compile(
1652
- '<select ng-model="selected">' +
1653
- '<option ng-value="option">{{option}}</option>' +
1654
- '<option ng-value="option2">{{option2}}</option>' +
1655
- "</select>",
1656
- );
1657
- await wait();
1658
- const selectController = getController(element, "select");
1659
- spyOn(selectController, "removeOption").and.callThrough();
1660
-
1661
- expect(selectController.removeOption).not.toHaveBeenCalled();
1662
- expect(element.querySelectorAll("option")[0].value).toBe(
1663
- "? string:NOMATCH ?",
1664
- );
1665
-
1666
- scope.selected = prop;
1667
- await wait();
1668
- expect(element.querySelectorAll("option")[0].value).toBe(
1669
- hashKey(prop),
1670
- );
1671
- expect(element.selectedIndex).toBe(0);
1672
-
1673
- scope.option = "UPDATEDVALUE";
1674
- await wait();
1675
- expect(selectController.removeOption.calls.count()).toBe(1);
1676
-
1677
- // Updating the option value currently does not update the select model
1678
- if (isNumberNaN(prop)) {
1679
- expect(selectController.removeOption.calls.argsFor(0)[0]).toBeNaN();
1680
- } else {
1681
- expect(selectController.removeOption.calls.argsFor(0)[0]).toBe(
1682
- prop,
1683
- );
1684
- }
1685
-
1686
- expect(scope.selected).toBe(null);
1687
- expect(element.selectedIndex).toBe(0);
1688
- expect(element.querySelectorAll("option").length).toBe(3);
1689
- expect(element.querySelectorAll("option")[0][0].selected).toBe(true);
1690
- expect(element.querySelectorAll("option")[0].value).toBe(
1691
- unknownValue(prop),
1692
- );
1693
- expect(element.querySelectorAll("option")[1].selected).toBe(false);
1694
- expect(element.querySelectorAll("option")[1].value).toBe(
1695
- "string:UPDATEDVALUE",
1696
- );
1697
-
1698
- scope.selected = "UPDATEDVALUE";
1699
- await wait();
1700
- expect(element.selectedIndex).toBe(0);
1701
- expect(element.querySelectorAll("option")[0].value).toBe(
1702
- "string:UPDATEDVALUE",
1703
- );
1704
- });
1705
- });
1706
- it("should interact with custom attribute $observe and $set calls", async () => {
1707
- const log = [];
1708
- let optionAttr;
1709
-
1710
- compile(
1711
- '<select ng-model="selected">' +
1712
- '<option expose-attributes ng-value="option">{{option}}</option>' +
1713
- "</select>",
1714
- );
1715
- await wait();
1716
- optionAttr = optionAttributesList[0];
1717
- optionAttr.$observe("value", (newVal) => {
1718
- log.push(newVal);
1719
- });
1720
-
1721
- scope.option = "init";
1722
- await wait();
1723
- expect(log[0]).toBe("init");
1724
- expect(element.querySelectorAll("option")[1].value).toBe("string:init");
1725
-
1726
- optionAttr.$set("value", "update");
1727
- await wait();
1728
- expect(log[1]).toBe("update");
1729
- expect(element.querySelectorAll("option")[1].value).toBe(
1730
- "string:update",
1731
- );
1732
- });
1733
-
1734
- it("should ignore the option text / value attribute if the ngValue attribute exists", async () => {
1735
- scope.ngvalue = "abc";
1736
- scope.value = "def";
1737
- scope.textvalue = "ghi";
1738
-
1739
- compile(
1740
- '<select ng-model="x"><option ng-value="ngvalue" value="{{value}}">{{textvalue}}</option></select>',
1741
- );
1742
- await wait();
1743
- expect(element.value).toBe(`? undefined:undefined ?`);
1744
- });
1745
-
1746
- it("should ignore option text with multiple interpolations if the ngValue attribute exists", async () => {
1747
- scope.ngvalue = "abc";
1748
- scope.textvalue = "def";
1749
- scope.textvalue2 = "ghi";
1750
-
1751
- compile(
1752
- '<select ng-model="x"><option ng-value="ngvalue">{{textvalue}} {{textvalue2}}</option></select>',
1753
- );
1754
- await wait();
1755
- expect(element.value).toBe(`? undefined:undefined ?`);
1756
- });
1757
-
1758
- it("should select the first option if it is `undefined`", async () => {
1759
- scope.selected = undefined;
1760
-
1761
- scope.option1 = undefined;
1762
- scope.option2 = "red";
1763
-
1764
- compile(
1765
- '<select ng-model="selected">' +
1766
- '<option ng-value="option1">{{option1}}</option>' +
1767
- '<option ng-value="option2">{{option2}}</option>' +
1768
- "</select>",
1769
- );
1770
- await wait();
1771
- expect(element.value).toBe("? undefined:undefined ?");
1772
- });
1773
-
1774
- describe("and select[multiple]", () => {
1775
- xit("should allow multiple selection", async () => {
1776
- scope.options = {
1777
- a: "string",
1778
- b: undefined,
1779
- c: 1,
1780
- d: true,
1781
- e: null,
1782
- f: NaN,
1783
- };
1784
- scope.selected = [];
1785
-
1786
- compile(
1787
- '<select multiple ng-model="selected">' +
1788
- '<option ng-value="options.a">{{options.a}}</option>' +
1789
- '<option ng-value="options.b">{{options.b}}</option>' +
1790
- '<option ng-value="options.c">{{options.c}}</option>' +
1791
- '<option ng-value="options.d">{{options.d}}</option>' +
1792
- '<option ng-value="options.e">{{options.e}}</option>' +
1793
- '<option ng-value="options.f">{{options.f}}</option>' +
1794
- "</select>",
1795
- );
1796
- await wait();
1797
- expect(
1798
- Object.values(element.childNodes)
1799
- .map((x) => x.value)
1800
- .join(""),
1801
- ).toBe(
1802
- [
1803
- "string:string",
1804
- "undefined:undefined",
1805
- "number:1",
1806
- "boolean:true",
1807
- "object:null",
1808
- "number:NaN",
1809
- ].join(""),
1810
- );
1811
-
1812
- scope.selected = ["string", 1];
1813
- await wait();
1814
- expect(element.querySelectorAll("option")[0][0].selected).toBe(true);
1815
- expect(element.querySelectorAll("option")[2][0].selected).toBe(true);
1816
-
1817
- setSelectValue(element, 1);
1818
- await wait();
1819
- expect(scope.selected).toEqual([undefined]);
1820
-
1821
- // reset
1822
- scope.selected = [];
1823
- await wait();
1824
- let elems = element.querySelectorAll("option");
1825
-
1826
- for (let i = 0; i < elems.length; i++) {
1827
- elems[i][0].selected = true;
1828
- }
1829
- browserTrigger(element, "change");
1830
- await wait();
1831
- const arrayVal = ["a"];
1832
- arrayVal.$$hashKey = "object:4";
1833
- await wait();
1834
- expect(scope.selected).toEqual([
1835
- "string",
1836
- undefined,
1837
- 1,
1838
- true,
1839
- null,
1840
- NaN,
1841
- ]);
1842
- });
1843
- });
1844
- });
1845
-
1846
- describe("updating the model and selection when option elements are manipulated", () => {
1847
- ["ngValue", "interpolatedValue", "interpolatedText"].forEach((prop) => {
1848
- xit("should set the model to null when the currently selected option with $prop is removed", async () => {
1849
- const A = { name: "A" };
1850
- const B = { name: "B" };
1851
- const C = { name: "C" };
1852
-
1853
- scope.options = [A, B, C];
1854
- scope.obj = {};
1855
-
1856
- let optionString = "";
1857
-
1858
- switch (prop) {
1859
- case "ngValue":
1860
- optionString =
1861
- '<option ng-repeat="option in options" ng-value="option">{{$index}}</option>';
1862
- break;
1863
- case "interpolatedValue":
1864
- optionString =
1865
- '<option ng-repeat="option in options" value="{{option.name}}">{{$index}}</option>';
1866
- break;
1867
- case "interpolatedText":
1868
- optionString =
1869
- '<option ng-repeat="option in options">{{option.name}}</option>';
1870
- break;
1871
- }
1872
-
1873
- compile(`<select ng-model="obj.value">${optionString}</select>`);
1874
- await wait();
1875
- let optionElements = element.querySelectorAll("option");
1876
- expect(optionElements.length).toEqual(4);
1877
- setSelectValue(optionElements, 0);
1878
- await wait();
1879
- optionElements = element.querySelectorAll("option");
1880
- expect(optionElements.length).toEqual(3);
1881
- expect(scope.obj.value).toBe(prop === "ngValue" ? A : "A");
1882
-
1883
- scope.options.shift();
1884
- await wait();
1885
- optionElements = element.querySelectorAll("option");
1886
- expect(optionElements.length).toEqual(3);
1887
- expect(scope.obj.value).toBe(null);
1888
- expect(element.value).toBe("? object:null ?");
1889
- });
1890
-
1891
- xit("should set the model to null when the currently selected option with $prop changes its value", async () => {
1892
- const A = { name: "A" };
1893
- const B = { name: "B" };
1894
- const C = { name: "C" };
1895
-
1896
- scope.options = [A, B, C];
1897
- scope.obj = {};
1898
-
1899
- let optionString = "";
1900
-
1901
- switch (prop) {
1902
- case "ngValue":
1903
- optionString =
1904
- '<option ng-repeat="option in options" ng-value="option.name">{{$index}}</option>';
1905
- break;
1906
- case "interpolatedValue":
1907
- optionString =
1908
- '<option ng-repeat="option in options" value="{{option.name}}">{{$index}}</option>';
1909
- break;
1910
- case "interpolatedText":
1911
- optionString =
1912
- '<option ng-repeat="option in options">{{option.name}}</option>';
1913
- break;
1914
- }
1915
-
1916
- compile(`<select ng-model="obj.value">${optionString}</select>`);
1917
- await wait();
1918
- let optionElements = element.querySelectorAll("option");
1919
- expect(optionElements.length).toEqual(4);
1920
- setSelectValue(optionElements, 0);
1921
- await wait();
1922
- optionElements = element.querySelectorAll("option");
1923
- expect(optionElements.length).toEqual(3);
1924
- expect(scope.obj.value).toBe("A");
1925
-
1926
- A.name = "X";
1927
- optionElements = element.querySelectorAll("option");
1928
- await wait();
1929
- expect(optionElements.length).toEqual(4);
1930
- expect(scope.obj.value).toBe(null);
1931
- expect(element.value).toBe("? string:A ?");
1932
- });
1933
-
1934
- xit("should set the model to null when the currently selected option with $prop is disabled", async () => {
1935
- const A = { name: "A" };
1936
- const B = { name: "B" };
1937
- const C = { name: "C" };
1938
-
1939
- scope.options = [A, B, C];
1940
- scope.obj = {};
1941
-
1942
- let optionString = "";
1943
-
1944
- switch (prop) {
1945
- case "ngValue":
1946
- optionString =
1947
- '<option ng-repeat="option in options" ng-disabled="option.disabled" ng-value="option.name">{{$index}}</option>';
1948
- break;
1949
- case "interpolatedValue":
1950
- optionString =
1951
- '<option ng-repeat="option in options" ng-disabled="option.disabled" value="{{option.name}}">{{$index}}</option>';
1952
- break;
1953
- case "interpolatedText":
1954
- optionString =
1955
- '<option ng-repeat="option in options" ng-disabled="option.disabled">{{option.name}}</option>';
1956
- break;
1957
- }
1958
-
1959
- compile(`<select ng-model="obj.value">${optionString}</select>`);
1960
- await wait();
1961
- let optionElements = element.querySelectorAll("option");
1962
- expect(optionElements.length).toEqual(4);
1963
- setSelectValue(optionElements, 0);
1964
- await wait();
1965
- optionElements = element.querySelectorAll("option");
1966
- expect(optionElements.length).toEqual(3);
1967
- expect(scope.obj.value).toBe("A");
1968
-
1969
- A.disabled = true;
1970
- optionElements = element.querySelectorAll("option");
1971
- await wait();
1972
- expect(optionElements.length).toEqual(4);
1973
- expect(scope.obj.value).toBe(null);
1974
- expect(element.value).toBe("? object:null ?");
1975
- });
1976
-
1977
- xit("should select a disabled option with $prop when the model is set to the matching value", async () => {
1978
- const A = { name: "A" };
1979
- const B = { name: "B" };
1980
- const C = { name: "C" };
1981
-
1982
- scope.options = [A, B, C];
1983
- scope.obj = {};
1984
-
1985
- let optionString = "";
1986
-
1987
- switch (prop) {
1988
- case "ngValue":
1989
- optionString =
1990
- '<option ng-repeat="option in options" ng-disabled="option.disabled" ng-value="option.name">{{$index}}</option>';
1991
- break;
1992
- case "interpolatedValue":
1993
- optionString =
1994
- '<option ng-repeat="option in options" ng-disabled="option.disabled" value="{{option.name}}">{{$index}}</option>';
1995
- break;
1996
- case "interpolatedText":
1997
- optionString =
1998
- '<option ng-repeat="option in options" ng-disabled="option.disabled">{{option.name}}</option>';
1999
- break;
2000
- }
2001
-
2002
- compile(`<select ng-model="obj.value">${optionString}</select>`);
2003
- await wait();
2004
- let optionElements = element.querySelectorAll("option");
2005
- expect(optionElements.length).toEqual(4);
2006
- expect(optionElements[0].value).toEqual(`? undefined:undefined ?`);
2007
-
2008
- B.disabled = true;
2009
- optionElements = element.querySelectorAll("option");
2010
- await wait();
2011
- expect(optionElements.length).toEqual(4);
2012
- expect(optionElements[0].value).toEqual(`? undefined:undefined ?`);
2013
-
2014
- scope.obj.value = "B";
2015
- optionElements = element.querySelectorAll("option");
2016
- await wait();
2017
- expect(optionElements.length).toEqual(3);
2018
- expect(scope.obj.value).toBe("B");
2019
- // jQuery returns null for val() when the option is disabled, see
2020
- // https://bugs.jquery.com/ticket/13097
2021
- expect(element.value).toBe(prop === "ngValue" ? "string:B" : "B");
2022
- expect(optionElements[1].selected).toBe(true);
2023
- });
2024
-
2025
- xit("should ignore an option with $prop that becomes enabled and does not match the model", async () => {
2026
- const A = { name: "A" };
2027
- const B = { name: "B" };
2028
- const C = { name: "C" };
2029
-
2030
- scope.options = [A, B, C];
2031
- scope.obj = {};
2032
-
2033
- let optionString = "";
2034
-
2035
- switch (prop) {
2036
- case "ngValue":
2037
- optionString =
2038
- '<option ng-repeat="option in options" ng-disabled="option.disabled" ng-value="option.name">{{$index}}</option>';
2039
- break;
2040
- case "interpolatedValue":
2041
- optionString =
2042
- '<option ng-repeat="option in options" ng-disabled="option.disabled" value="{{option.name}}">{{$index}}</option>';
2043
- break;
2044
- case "interpolatedText":
2045
- optionString =
2046
- '<option ng-repeat="option in options" ng-disabled="option.disabled">{{option.name}}</option>';
2047
- break;
2048
- }
2049
-
2050
- compile(`<select ng-model="obj.value">${optionString}</select>`);
2051
- await wait();
2052
- let optionElements = element.querySelectorAll("option");
2053
- expect(optionElements.length).toEqual(4);
2054
- setSelectValue(optionElements, 0);
2055
- await wait();
2056
- optionElements = element.querySelectorAll("option");
2057
- expect(optionElements.length).toEqual(3);
2058
- expect(scope.obj.value).toBe("A");
2059
-
2060
- A.disabled = true;
2061
- optionElements = element.querySelectorAll("option");
2062
- await wait();
2063
- expect(optionElements.length).toEqual(4);
2064
- expect(scope.obj.value).toBe(null);
2065
- expect(element.value).toBe("? object:null ?");
2066
-
2067
- A.disabled = false;
2068
- optionElements = element.querySelectorAll("option");
2069
- await wait();
2070
- expect(optionElements.length).toEqual(4);
2071
- expect(scope.obj.value).toBe(null);
2072
- expect(element.value).toBe("? object:null ?");
2073
- });
2074
-
2075
- xit("should select a newly added option with $prop when it matches the current model", async () => {
2076
- const A = { name: "A" };
2077
- const B = { name: "B" };
2078
- const C = { name: "C" };
2079
-
2080
- scope.options = [A, B];
2081
- scope.obj = {
2082
- value: prop === "ngValue" ? C : "C",
2083
- };
2084
-
2085
- let optionString = "";
2086
-
2087
- switch (prop) {
2088
- case "ngValue":
2089
- optionString =
2090
- '<option ng-repeat="option in options" ng-value="option">{{$index}}</option>';
2091
- break;
2092
- case "interpolatedValue":
2093
- optionString =
2094
- '<option ng-repeat="option in options" value="{{option.name}}">{{$index}}</option>';
2095
- break;
2096
- case "interpolatedText":
2097
- optionString =
2098
- '<option ng-repeat="option in options">{{option.name}}</option>';
2099
- break;
2100
- }
2101
-
2102
- compile(`<select ng-model="obj.value">${optionString}</select>`);
2103
- await wait();
2104
- let optionElements = element.querySelectorAll("option");
2105
- expect(optionElements.length).toEqual(3);
2106
-
2107
- scope.options.push(C);
2108
- await wait();
2109
- optionElements = element.querySelectorAll("option");
2110
- expect(optionElements.length).toEqual(3);
2111
- expect(optionElements[2].selected).toBe(true);
2112
- });
2113
-
2114
- xit("should keep selection and model when repeated options with track by are replaced with equal options", async () => {
2115
- const A = { name: "A" };
2116
- const B = { name: "B" };
2117
- const C = { name: "C" };
2118
-
2119
- scope.options = [A, B, C];
2120
- scope.obj = {
2121
- value: "C",
2122
- };
2123
-
2124
- let optionString = "";
2125
-
2126
- switch (prop) {
2127
- case "ngValue":
2128
- optionString =
2129
- '<option ng-repeat="option in options track by option.name" ng-value="option.name">{{$index}}</option>';
2130
- break;
2131
- case "interpolatedValue":
2132
- optionString =
2133
- '<option ng-repeat="option in options track by option.name" value="{{option.name}}">{{$index}}</option>';
2134
- break;
2135
- case "interpolatedText":
2136
- optionString =
2137
- '<option ng-repeat="option in options track by option.name">{{option.name}}</option>';
2138
- break;
2139
- }
2140
-
2141
- compile(`<select ng-model="obj.value">${optionString}</select>`);
2142
- await wait();
2143
- let optionElements = element.querySelectorAll("option");
2144
- expect(optionElements.length).toEqual(3);
2145
-
2146
- scope.obj.value = "C";
2147
- optionElements = element.querySelectorAll("option");
2148
- await wait();
2149
- expect(element.value).toBe(prop === "ngValue" ? "string:C" : "C");
2150
- expect(optionElements.length).toEqual(3);
2151
- expect(optionElements[2].selected).toBe(true);
2152
- expect(scope.obj.value).toBe("C");
2153
-
2154
- scope.options = [{ name: "A" }, { name: "B" }, { name: "C" }];
2155
- optionElements = element.querySelectorAll("option");
2156
- await wait();
2157
- expect(element.value).toBe(prop === "ngValue" ? "string:C" : "C");
2158
- expect(optionElements.length).toEqual(3);
2159
- expect(optionElements[2].selected).toBe(true);
2160
- expect(scope.obj.value).toBe("C");
2161
- });
2162
- });
2163
-
2164
- describe("when multiple", () => {
2165
- ["ngValue", "interpolatedValue", "interpolatedText"].forEach((prop) => {
2166
- xit("should set the model to null when the currently selected option with $prop is removed", async () => {
2167
- const A = { name: "A" };
2168
- const B = { name: "B" };
2169
- const C = { name: "C" };
2170
-
2171
- scope.options = [A, B, C];
2172
- scope.obj = {};
2173
-
2174
- let optionString = "";
2175
-
2176
- switch (prop) {
2177
- case "ngValue":
2178
- optionString =
2179
- '<option ng-repeat="option in options" ng-value="option">{{$index}}</option>';
2180
- break;
2181
- case "interpolatedValue":
2182
- optionString =
2183
- '<option ng-repeat="option in options" value="{{option.name}}">{{$index}}</option>';
2184
- break;
2185
- case "interpolatedText":
2186
- optionString =
2187
- '<option ng-repeat="option in options">{{option.name}}</option>';
2188
- break;
2189
- }
2190
-
2191
- compile(
2192
- `<select ng-model="obj.value" multiple>${optionString}</select>`,
2193
- );
2194
- await wait();
2195
- const ngModelCtrl = getController(element, "ngModel");
2196
- const ngModelCtrlSpy = spyOn(
2197
- ngModelCtrl,
2198
- "$setViewValue",
2199
- ).and.callThrough();
2200
-
2201
- let optionElements = element.querySelectorAll("option");
2202
- expect(optionElements.length).toEqual(3);
2203
- await wait();
2204
- optionElements[0][0].selected = true;
2205
- optionElements[2][0].selected = true;
2206
- browserTrigger(element);
2207
- await wait();
2208
- optionElements = element.querySelectorAll("option");
2209
- expect(optionElements.length).toEqual(3);
2210
-
2211
- ngModelCtrlSpy.calls.reset();
2212
- scope.options.shift();
2213
- scope.options.pop();
2214
- await wait();
2215
- optionElements = element.querySelectorAll("option");
2216
- expect(optionElements.length).toEqual(1);
2217
- expect(scope.obj.value).toEqual([]);
2218
-
2219
- // Cover both jQuery 3.x ([]) and 2.x (null) behavior.
2220
- let val = element.value;
2221
- if (val === null) {
2222
- val = [];
2223
- }
2224
- expect(val).toEqual([]);
2225
-
2226
- expect(ngModelCtrlSpy).toHaveBeenCalledTimes(1);
2227
- });
2228
-
2229
- xit("should set the model to null when the currently selected option with $prop changes its value", async () => {
2230
- const A = { name: "A" };
2231
- const B = { name: "B" };
2232
- const C = { name: "C" };
2233
-
2234
- scope.options = [A, B, C];
2235
- scope.obj = {};
2236
-
2237
- let optionString = "";
2238
-
2239
- switch (prop) {
2240
- case "ngValue":
2241
- optionString =
2242
- '<option ng-repeat="option in options" ng-value="option.name">{{$index}}</option>';
2243
- break;
2244
- case "interpolatedValue":
2245
- optionString =
2246
- '<option ng-repeat="option in options" value="{{option.name}}">{{$index}}</option>';
2247
- break;
2248
- case "interpolatedText":
2249
- optionString =
2250
- '<option ng-repeat="option in options">{{option.name}}</option>';
2251
- break;
2252
- }
2253
-
2254
- compile(
2255
- `<select ng-model="obj.value" multiple>${optionString}</select>`,
2256
- );
2257
-
2258
- const ngModelCtrl = getController(element, "ngModel");
2259
- const ngModelCtrlSpy = spyOn(
2260
- ngModelCtrl,
2261
- "$setViewValue",
2262
- ).and.callThrough();
2263
- await wait();
2264
- let optionElements = element.querySelectorAll("option");
2265
- expect(optionElements.length).toEqual(3);
2266
-
2267
- optionElements[0][0].selected = true;
2268
- optionElements[2][0].selected = true;
2269
- browserTrigger(element, "change");
2270
- await wait();
2271
- optionElements = element.querySelectorAll("option");
2272
- expect(optionElements.length).toEqual(3);
2273
- expect(scope.obj.value).toEqual(["A", "C"]);
2274
-
2275
- ngModelCtrlSpy.calls.reset();
2276
- A.name = "X";
2277
- C.name = "Z";
2278
- optionElements = element.querySelectorAll("option");
2279
- await wait();
2280
- expect(optionElements.length).toEqual(3);
2281
- expect(scope.obj.value).toEqual([]);
2282
-
2283
- // Cover both jQuery 3.x ([]) and 2.x (null) behavior.
2284
- let val = element.value;
2285
- if (val === null) {
2286
- val = [];
2287
- }
2288
- expect(val).toEqual([]);
2289
-
2290
- expect(ngModelCtrlSpy).toHaveBeenCalledTimes(1);
2291
- });
2292
-
2293
- xit("should set the model to null when the currently selected option with $prop becomes disabled", async () => {
2294
- const A = { name: "A" };
2295
- const B = { name: "B" };
2296
- const C = { name: "C" };
2297
- const D = { name: "D" };
2298
-
2299
- scope.options = [A, B, C, D];
2300
- scope.obj = {};
2301
-
2302
- let optionString = "";
2303
-
2304
- switch (prop) {
2305
- case "ngValue":
2306
- optionString =
2307
- '<option ng-repeat="option in options" ng-disabled="option.disabled" ng-value="option.name">{{$index}}</option>';
2308
- break;
2309
- case "interpolatedValue":
2310
- optionString =
2311
- '<option ng-repeat="option in options" ng-disabled="option.disabled" value="{{option.name}}">{{$index}}</option>';
2312
- break;
2313
- case "interpolatedText":
2314
- optionString =
2315
- '<option ng-repeat="option in options" ng-disabled="option.disabled">{{option.name}}</option>';
2316
- break;
2317
- }
2318
-
2319
- compile(
2320
- `<select ng-model="obj.value" multiple>${optionString}</select>`,
2321
- );
2322
-
2323
- const ngModelCtrl = getController(element, "ngModel");
2324
- const ngModelCtrlSpy = spyOn(
2325
- ngModelCtrl,
2326
- "$setViewValue",
2327
- ).and.callThrough();
2328
- await wait();
2329
- let optionElements = element.querySelectorAll("option");
2330
- expect(optionElements.length).toEqual(4);
2331
-
2332
- optionElements[0][0].selected = true;
2333
- optionElements[2][0].selected = true;
2334
- optionElements.eq(3)[0].selected = true;
2335
- await wait();
2336
- browserTrigger(element, "change");
2337
-
2338
- optionElements = element.querySelectorAll("option");
2339
- expect(optionElements.length).toEqual(4);
2340
- expect(scope.obj.value).toEqual(["A", "C", "D"]);
2341
-
2342
- ngModelCtrlSpy.calls.reset();
2343
- A.disabled = true;
2344
- C.disabled = true;
2345
- await wait();
2346
- optionElements = element.querySelectorAll("option");
2347
- expect(optionElements.length).toEqual(4);
2348
- expect(scope.obj.value).toEqual(["D"]);
2349
- expect(element.value).toEqual(
2350
- prop === "ngValue" ? ["string:D"] : ["D"],
2351
- );
2352
- expect(ngModelCtrlSpy).toHaveBeenCalledTimes(1);
2353
- });
2354
-
2355
- xit("should select disabled options with $prop when the model is set to matching values", async () => {
2356
- const A = { name: "A" };
2357
- const B = { name: "B" };
2358
- const C = { name: "C" };
2359
- const D = { name: "D" };
2360
-
2361
- scope.options = [A, B, C, D];
2362
- scope.obj = {};
2363
-
2364
- let optionString = "";
2365
-
2366
- switch (prop) {
2367
- case "ngValue":
2368
- optionString =
2369
- '<option ng-repeat="option in options" ng-disabled="option.disabled" ng-value="option">{{$index}}</option>';
2370
- break;
2371
- case "interpolatedValue":
2372
- optionString =
2373
- '<option ng-repeat="option in options" ng-disabled="option.disabled" value="{{option.name}}">{{$index}}</option>';
2374
- break;
2375
- case "interpolatedText":
2376
- optionString =
2377
- '<option ng-repeat="option in options" ng-disabled="option.disabled">{{option.name}}</option>';
2378
- break;
2379
- }
2380
-
2381
- compile(
2382
- `<select ng-model="obj.value" multiple>${optionString}</select>`,
2383
- );
2384
- await wait();
2385
- let optionElements = element.querySelectorAll("option");
2386
- expect(optionElements.length).toEqual(4);
2387
- expect(element.value).toBe("");
2388
-
2389
- A.disabled = true;
2390
- D.disabled = true;
2391
- await wait();
2392
- optionElements = element.querySelectorAll("option");
2393
- expect(optionElements.length).toEqual(4);
2394
- expect(element.value).toBe("");
2395
-
2396
- scope.obj.value = prop === "ngValue" ? [A, C, D] : ["A", "C", "D"];
2397
- await wait();
2398
- optionElements = element.querySelectorAll("option");
2399
- expect(optionElements.length).toEqual(4);
2400
- expect(optionElements[0][0].selected).toBe(true);
2401
- expect(optionElements[2][0].selected).toBe(true);
2402
- expect(optionElements.eq(3)[0].selected).toBe(true);
2403
- });
2404
-
2405
- xit("should select a newly added option with $prop when it matches the current model", async () => {
2406
- const A = { name: "A" };
2407
- const B = { name: "B" };
2408
- const C = { name: "C" };
2409
-
2410
- scope.options = [A, B];
2411
- scope.obj = {
2412
- value: prop === "ngValue" ? [B, C] : ["B", "C"],
2413
- };
2414
-
2415
- let optionString = "";
2416
-
2417
- switch (prop) {
2418
- case "ngValue":
2419
- optionString =
2420
- '<option ng-repeat="option in options" ng-value="option">{{$index}}</option>';
2421
- break;
2422
- case "interpolatedValue":
2423
- optionString =
2424
- '<option ng-repeat="option in options" value="{{option.name}}">{{$index}}</option>';
2425
- break;
2426
- case "interpolatedText":
2427
- optionString =
2428
- '<option ng-repeat="option in options">{{option.name}}</option>';
2429
- break;
2430
- }
2431
-
2432
- compile(
2433
- `<select ng-model="obj.value" multiple>${optionString}</select>`,
2434
- );
2435
- await wait();
2436
- let optionElements = element.querySelectorAll("option");
2437
- expect(optionElements.length).toEqual(2);
2438
- expect(optionElements[1].selected).toBe(true);
2439
-
2440
- scope.options.push(C);
2441
- await wait();
2442
- optionElements = element.querySelectorAll("option");
2443
-
2444
- expect(optionElements.length).toEqual(3);
2445
- expect(optionElements[1].selected).toBe(true);
2446
- expect(optionElements[2].selected).toBe(true);
2447
- });
2448
-
2449
- xit("should keep selection and model when a repeated options with track by are replaced with equal options", async () => {
2450
- const A = { name: "A" };
2451
- const B = { name: "B" };
2452
- const C = { name: "C" };
2453
-
2454
- scope.options = [A, B, C];
2455
- scope.obj = {
2456
- value: "C",
2457
- };
2458
-
2459
- let optionString = "";
2460
-
2461
- switch (prop) {
2462
- case "ngValue":
2463
- optionString =
2464
- '<option ng-repeat="option in options track by option.name" ng-value="option.name">{{$index}}</option>';
2465
- break;
2466
- case "interpolatedValue":
2467
- optionString =
2468
- '<option ng-repeat="option in options track by option.name" value="{{option.name}}">{{$index}}</option>';
2469
- break;
2470
- case "interpolatedText":
2471
- optionString =
2472
- '<option ng-repeat="option in options track by option.name">{{option.name}}</option>';
2473
- break;
2474
- }
2475
-
2476
- compile(
2477
- `<select ng-model="obj.value" multiple>${optionString}</select>`,
2478
- );
2479
- await wait();
2480
- let optionElements = element.querySelectorAll("option");
2481
- expect(optionElements.length).toEqual(3);
2482
-
2483
- scope.obj.value = ["B", "C"];
2484
- await wait();
2485
- optionElements = element.querySelectorAll("option");
2486
-
2487
- expect(optionElements.length).toEqual(3);
2488
- expect(optionElements[1].selected).toBe(true);
2489
- expect(optionElements[2].selected).toBe(true);
2490
- expect(scope.obj.value).toEqual(["B", "C"]);
2491
-
2492
- scope.options = [{ name: "A" }, { name: "B" }, { name: "C" }];
2493
- await wait();
2494
- optionElements = element.querySelectorAll("option");
2495
-
2496
- expect(optionElements.length).toEqual(3);
2497
- expect(optionElements[1].selected).toBe(true);
2498
- expect(optionElements[2].selected).toBe(true);
2499
- expect(scope.obj.value).toEqual(["B", "C"]);
2500
- });
2501
- });
2502
- });
2503
-
2504
- it("should keep the ngModel value when the selected option is recreated by ngRepeat", async () => {
2505
- scope.options = [{ name: "A" }, { name: "B" }, { name: "C" }];
2506
- scope.obj = {
2507
- value: "B",
2508
- };
2509
-
2510
- compile(
2511
- '<select ng-model="obj.value">' +
2512
- '<option ng-repeat="option in options" value="{{option.name}}">{{option.name}}</option>' +
2513
- "</select>",
2514
- );
2515
- await wait();
2516
- let optionElements = element.querySelectorAll("option");
2517
- expect(optionElements.length).toEqual(3);
2518
- expect(optionElements[0].value).toBe("A");
2519
- expect(optionElements[1].selected).toBeTrue();
2520
- expect(scope.obj.value).toBe("B");
2521
-
2522
- scope.$apply(() => {
2523
- // Only when new objects are used, ngRepeat re-creates the element from scratch
2524
- scope.options = [{ name: "B" }, { name: "C" }, { name: "D" }];
2525
- });
2526
- await wait();
2527
- const previouslySelectedOptionElement = optionElements[1];
2528
- optionElements = element.querySelectorAll("option");
2529
-
2530
- expect(optionElements.length).toEqual(3);
2531
- expect(optionElements[0].value).toBe("B");
2532
- expect(optionElements[0].selected).toBeTrue();
2533
- expect(scope.obj.value).toBe("B");
2534
- // Ensure the assumption that the element is re-created is true
2535
- expect(previouslySelectedOptionElement).not.toBe(optionElements[0]);
2536
- });
2537
-
2538
- xit("should validate when the options change", async () => {
2539
- scope.values = ["A", "B"];
2540
- scope.selection = "A";
2541
-
2542
- compile(
2543
- '<select ng-model="selection" required>' +
2544
- '<option value="">--select--</option>' +
2545
- '<option ng-repeat="option in values" value="{{option}}">{{option}}</option>' +
2546
- "</select>",
2547
- );
2548
- await wait();
2549
- expect(element.value).toBe("A");
2550
- expect(element.classList.contains("ng-valid")).toBeTrue();
2551
- expect(ngModelCtrl.$error.required).toBeFalsy();
2552
-
2553
- scope.$apply(() => {
2554
- // Only when new objects are used, ngRepeat re-creates the element from scratch
2555
- scope.values = ["B", "C"];
2556
- });
2557
- await wait();
2558
- expect(element.value).toBe("");
2559
- expect(element.classList.contains("ng-invalid")).toBeTrue();
2560
- expect(ngModelCtrl.$error.required).toBeTruthy();
2561
- // ngModel sets undefined for invalid values
2562
- expect(scope.selection).toBeUndefined();
2563
- });
2564
- });
2565
- });
2566
- });