@angular-wave/angular.ts 0.7.5 → 0.7.8

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 (174) hide show
  1. package/@types/animations/raf-scheduler.d.ts +2 -2
  2. package/@types/animations/shared.d.ts +0 -1
  3. package/@types/core/compile/attributes.d.ts +3 -3
  4. package/@types/core/compile/compile.d.ts +1 -1
  5. package/@types/core/di/injector.d.ts +0 -1
  6. package/@types/core/di/internal-injector.d.ts +1 -0
  7. package/@types/core/di/ng-module.d.ts +5 -0
  8. package/@types/core/filter/filter.d.ts +11 -13
  9. package/@types/core/sanitize/sanitize-uri.d.ts +3 -6
  10. package/@types/core/scope/scope.d.ts +1 -3
  11. package/@types/directive/attrs/attrs.d.ts +7 -1
  12. package/@types/directive/events/events.d.ts +9 -3
  13. package/@types/directive/http/http.d.ts +6 -2
  14. package/@types/directive/include/include.d.ts +2 -2
  15. package/@types/directive/input/input.d.ts +2 -12
  16. package/@types/directive/messages/messages.d.ts +9 -48
  17. package/@types/directive/model/model.d.ts +3 -3
  18. package/@types/directive/options/options.d.ts +13 -20
  19. package/@types/directive/setter/setter.d.ts +2 -2
  20. package/@types/directive/switch/switch.d.ts +1 -0
  21. package/@types/directive/transclude/transclude.d.ts +10 -6
  22. package/@types/interface.d.ts +54 -18
  23. package/@types/router/common/glob.d.ts +5 -1
  24. package/@types/router/directives/view-directive.d.ts +2 -19
  25. package/@types/router/globals.d.ts +1 -2
  26. package/@types/router/state/state-registry.d.ts +1 -2
  27. package/@types/router/url/url-service.d.ts +7 -9
  28. package/@types/services/anchor-scroll.d.ts +1 -1
  29. package/@types/{core → services/exception}/exception-handler.d.ts +4 -4
  30. package/@types/{core/error-handler.d.ts → services/exception/interface.d.ts} +1 -1
  31. package/@types/services/http/http.d.ts +0 -2
  32. package/@types/services/http/interface.d.ts +2 -2
  33. package/@types/services/http-backend/http-backend.d.ts +13 -21
  34. package/@types/services/location/interface.d.ts +8 -0
  35. package/@types/{core → services}/location/location.d.ts +52 -12
  36. package/@types/{core → services}/sce/sce.d.ts +1 -1
  37. package/@types/services/template-cache/interface.d.ts +8 -2
  38. package/@types/services/template-cache/template-cache.d.ts +1 -1
  39. package/@types/services/template-request.d.ts +1 -1
  40. package/@types/shared/cache.d.ts +0 -2
  41. package/@types/shared/dom.d.ts +6 -0
  42. package/@types/shared/test-utils.d.ts +1 -0
  43. package/@types/shared/url-utils/interface.d.ts +47 -0
  44. package/@types/{core → shared}/url-utils/url-utils.d.ts +26 -13
  45. package/@types/shared/utils.d.ts +23 -0
  46. package/Makefile +3 -2
  47. package/dist/angular-ts.esm.js +1188 -1364
  48. package/dist/angular-ts.umd.js +1188 -1364
  49. package/dist/angular-ts.umd.min.js +1 -1
  50. package/docs/assets/scss/index.scss +12 -0
  51. package/docs/content/_index.md +15 -4
  52. package/docs/content/docs/directive/bind.md +72 -0
  53. package/docs/content/docs/directive/click.md +3 -0
  54. package/docs/content/docs/directive/dblclick.md +3 -0
  55. package/docs/content/docs/directive/get.md +203 -0
  56. package/docs/content/docs/directive/keydown.md +38 -0
  57. package/docs/content/docs/directive/keyup.md +38 -0
  58. package/docs/content/docs/directive/load.md +43 -0
  59. package/docs/content/docs/provider/templateCacheProvider.md +66 -1
  60. package/docs/content/docs/service/templateCache.md +2 -2
  61. package/docs/layouts/partials/hooks/head-end.html +1 -1
  62. package/docs/layouts/shortcodes/showcss.html +2 -0
  63. package/docs/static/examples/ng-bind/ng-bind.html +9 -0
  64. package/docs/static/examples/ng-keydown/ng-keydown.html +9 -0
  65. package/docs/static/examples/ng-keyup/ng-keyup.html +9 -0
  66. package/docs/static/examples/ng-load/ng-load.html +8 -0
  67. package/docs/static/typedoc/assets/hierarchy.js +1 -1
  68. package/docs/static/typedoc/assets/navigation.js +1 -1
  69. package/docs/static/typedoc/assets/search.js +1 -1
  70. package/docs/static/typedoc/classes/NgModule.html +32 -0
  71. package/docs/static/typedoc/classes/TemplateCacheProvider.html +1 -1
  72. package/docs/static/typedoc/hierarchy.html +1 -1
  73. package/docs/static/typedoc/index.html +1 -1
  74. package/docs/static/typedoc/interfaces/Directive.html +5 -4
  75. package/docs/static/typedoc/interfaces/HttpProviderDefaults.html +1 -1
  76. package/docs/static/typedoc/interfaces/HttpResponse.html +2 -3
  77. package/docs/static/typedoc/interfaces/Provider.html +15 -10
  78. package/docs/static/typedoc/interfaces/RequestConfig.html +1 -1
  79. package/docs/static/typedoc/interfaces/RequestShortcutConfig.html +1 -1
  80. package/docs/static/typedoc/interfaces/TemplateCache.html +7 -0
  81. package/docs/static/typedoc/types/AnnotatedDirectiveFactory.html +1 -0
  82. package/docs/static/typedoc/types/DirectiveFactory.html +1 -2
  83. package/docs/static/typedoc/types/DirectiveFactoryFn.html +1 -0
  84. package/docs/static/typedoc/types/HttpResponseStatus.html +1 -0
  85. package/docs/static/typedoc/types/{TemplateCache.html → SwapModeType.html} +1 -1
  86. package/docs/static/typedoc/variables/SwapMode.html +11 -0
  87. package/legacy.d.ts +0 -14
  88. package/package.json +1 -3
  89. package/src/animations/animate-children-directive.js +2 -2
  90. package/src/animations/raf-scheduler.js +1 -1
  91. package/src/animations/shared.js +0 -9
  92. package/src/core/compile/attributes.js +1 -1
  93. package/src/core/compile/compile.js +3 -3
  94. package/src/core/di/injector.js +4 -17
  95. package/src/core/di/internal-injector.js +4 -1
  96. package/src/core/di/ng-module.js +12 -27
  97. package/src/core/filter/filter.js +28 -28
  98. package/src/core/parse/interpreter.js +32 -38
  99. package/src/core/sanitize/sanitize-uri.js +3 -3
  100. package/src/core/scope/scope.js +2 -7
  101. package/src/directive/attrs/attrs.js +7 -4
  102. package/src/directive/bind/bind.js +16 -4
  103. package/src/directive/bind/bind.spec.js +13 -0
  104. package/src/directive/events/events.js +7 -3
  105. package/src/directive/events/events.md +0 -41
  106. package/src/directive/http/delete.spec.js +2 -0
  107. package/src/directive/http/get.spec.js +280 -3
  108. package/src/directive/http/http.js +100 -12
  109. package/src/directive/http/http.test.js +2 -2
  110. package/src/directive/http/post.spec.js +2 -0
  111. package/src/directive/http/put.spec.js +2 -0
  112. package/src/directive/include/include.js +7 -7
  113. package/src/directive/input/input.js +6 -28
  114. package/src/directive/messages/messages.js +5 -1
  115. package/src/directive/model/model.js +1 -1
  116. package/src/directive/options/options.js +454 -464
  117. package/src/directive/repeat/repeat.js +175 -153
  118. package/src/directive/setter/setter.js +13 -15
  119. package/src/directive/setter/setter.spec.js +39 -16
  120. package/src/directive/switch/switch.js +1 -0
  121. package/src/directive/switch/switch.spec.js +1 -1
  122. package/src/directive/transclude/transclude.js +87 -89
  123. package/src/injection-tokens.js +1 -1
  124. package/src/interface.ts +68 -19
  125. package/src/loader.js +4 -9
  126. package/src/public.js +9 -15
  127. package/src/router/common/glob.js +5 -0
  128. package/src/router/directives/state-directives.js +4 -6
  129. package/src/router/directives/state-directives.spec.js +1 -1
  130. package/src/router/directives/view-directive.js +9 -1
  131. package/src/router/globals.js +0 -1
  132. package/src/router/state/state-registry.js +0 -1
  133. package/src/router/state-filters.js +2 -2
  134. package/src/router/url/url-service.js +5 -9
  135. package/src/services/anchor-scroll.html +0 -7
  136. package/src/services/anchor-scroll.js +2 -2
  137. package/src/{core → services/exception}/exception-handler.js +2 -2
  138. package/src/{core/error-handler.ts → services/exception/interface.ts} +1 -1
  139. package/src/services/http/http.js +2 -13
  140. package/src/services/http/interface.ts +2 -2
  141. package/src/services/http-backend/http-backend.js +4 -14
  142. package/src/services/http-backend/http-backend.spec.js +1 -4
  143. package/src/services/location/interface.ts +8 -0
  144. package/src/{core → services}/location/location.html +4 -1
  145. package/src/{core → services}/location/location.js +129 -27
  146. package/src/{core → services}/location/location.spec.js +2 -2
  147. package/src/{core → services}/location/location.test.js +1 -1
  148. package/src/{core → services}/sce/sce.html +1 -1
  149. package/src/{core → services}/sce/sce.js +9 -3
  150. package/src/{core → services}/sce/sce.spec.js +2 -3
  151. package/src/{core → services}/sce/sce.test.js +1 -1
  152. package/src/services/template-cache/interface.ts +8 -2
  153. package/src/services/template-cache/template-cache.js +3 -1
  154. package/src/services/template-cache/template-cache.spec.js +72 -0
  155. package/src/services/template-request.js +2 -1
  156. package/src/shared/cache.js +0 -2
  157. package/src/shared/dom.js +10 -0
  158. package/src/shared/test-utils.js +1 -0
  159. package/src/shared/url-utils/interface.ts +56 -0
  160. package/src/{core → shared}/url-utils/url-utils.html +4 -1
  161. package/src/{core → shared}/url-utils/url-utils.js +26 -23
  162. package/src/{core → shared}/url-utils/url-utils.spec.js +0 -8
  163. package/src/{core → shared}/url-utils/url-utils.test.js +1 -1
  164. package/src/shared/utils.js +47 -1
  165. package/utils/express.js +9 -1
  166. package/@types/core/task-tracker-factory.d.ts +0 -76
  167. package/@types/services/browser.d.ts +0 -101
  168. package/docs/static/typedoc/types/SwapInsertPosition.html +0 -2
  169. package/jsdoc.json +0 -22
  170. package/src/core/task-tracker-factory.js +0 -145
  171. package/src/services/browser.js +0 -212
  172. /package/src/{core → services}/location/location.md +0 -0
  173. /package/src/{core → services}/sce/sce.md +0 -0
  174. /package/src/{core → shared}/url-utils/url-utils.md +0 -0
@@ -1,5 +1,12 @@
1
- import { minErr, hashKey, isArrayLike, hasOwn } from "../../shared/utils.js";
2
- import { getBlockNodes } from "../../shared/dom.js";
1
+ import {
2
+ minErr,
3
+ hashKey,
4
+ isArrayLike,
5
+ hasOwn,
6
+ isDefined,
7
+ callBackOnce,
8
+ } from "../../shared/utils.js";
9
+ import { getBlockNodes, removeElement } from "../../shared/dom.js";
3
10
  import { $injectTokens } from "../../injection-tokens.js";
4
11
 
5
12
  const NG_REMOVED = "$$NG_REMOVED";
@@ -78,7 +85,7 @@ export function ngRepeatDirective($animate) {
78
85
  transclude: "element",
79
86
  priority: 1000,
80
87
  terminal: true,
81
- compile: (_$element, $attr) => {
88
+ compile: ($element, $attr) => {
82
89
  const expression = $attr["ngRepeat"];
83
90
  const hasAnimate = !!$attr["animate"];
84
91
 
@@ -126,6 +133,14 @@ export function ngRepeatDirective($animate) {
126
133
 
127
134
  let trackByIdExpFn;
128
135
 
136
+ const swap = callBackOnce(() => {
137
+ if (isDefined($attr["lazy"]) && isDefined($attr["swap"])) {
138
+ document
139
+ .querySelectorAll($attr["swap"])
140
+ .forEach((x) => removeElement(x));
141
+ }
142
+ });
143
+
129
144
  return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {
130
145
  // Store a list of elements from previous run. This is a hash where key is the item from the
131
146
  // iterator, and the value is objects with following properties.
@@ -137,174 +152,181 @@ export function ngRepeatDirective($animate) {
137
152
  // hasOwnProperty.
138
153
  let lastBlockMap = Object.create(null);
139
154
  // watch props
140
- $scope.$watch(rhs, (collection) => {
141
- let index,
142
- length,
143
- previousNode = $element, // node that cloned nodes should be inserted after
144
- // initialized to the comment node anchor
145
- nextNode;
146
- const // Same as lastBlockMap but it has the current state. It will become the
147
- // lastBlockMap on the next iteration.
148
- nextBlockMap = Object.create(null);
149
- let collectionLength,
150
- key,
151
- value, // key/value of iteration
152
- trackById,
153
- trackByIdFn,
154
- collectionKeys,
155
- block, // last object information {scope, element, id}
156
- nextBlockOrder,
157
- elementsToRemove;
155
+ $scope.$watch(
156
+ rhs,
157
+ (collection) => {
158
+ swap();
159
+ let index,
160
+ length,
161
+ previousNode = $element, // node that cloned nodes should be inserted after
162
+ // initialized to the comment node anchor
163
+ nextNode;
164
+ const // Same as lastBlockMap but it has the current state. It will become the
165
+ // lastBlockMap on the next iteration.
166
+ nextBlockMap = Object.create(null);
167
+ let collectionLength,
168
+ key,
169
+ value, // key/value of iteration
170
+ trackById,
171
+ trackByIdFn,
172
+ collectionKeys,
173
+ block, // last object information {scope, element, id}
174
+ nextBlockOrder,
175
+ elementsToRemove;
158
176
 
159
- if (aliasAs) {
160
- $scope[aliasAs] = collection;
161
- }
177
+ if (aliasAs) {
178
+ $scope[aliasAs] = collection;
179
+ }
162
180
 
163
- if (isArrayLike(collection)) {
164
- collectionKeys = collection;
165
- trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
166
- } else {
167
- trackByIdFn = trackByIdExpFn || trackByIdObjFn;
168
- // if object, extract keys, in enumeration order, unsorted
169
- collectionKeys = [];
170
- for (const itemKey in collection) {
171
- if (hasOwn(collection, itemKey) && itemKey.charAt(0) !== "$") {
172
- collectionKeys.push(itemKey);
181
+ if (isArrayLike(collection)) {
182
+ collectionKeys = collection;
183
+ trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
184
+ } else {
185
+ trackByIdFn = trackByIdExpFn || trackByIdObjFn;
186
+ // if object, extract keys, in enumeration order, unsorted
187
+ collectionKeys = [];
188
+ for (const itemKey in collection) {
189
+ if (hasOwn(collection, itemKey) && itemKey.charAt(0) !== "$") {
190
+ collectionKeys.push(itemKey);
191
+ }
173
192
  }
174
193
  }
175
- }
176
194
 
177
- collectionLength = collectionKeys.length;
178
- nextBlockOrder = new Array(collectionLength);
195
+ collectionLength = collectionKeys.length;
196
+ nextBlockOrder = new Array(collectionLength);
179
197
 
180
- // locate existing items
181
- for (index = 0; index < collectionLength; index++) {
182
- key = collection === collectionKeys ? index : collectionKeys[index];
183
- value = collection[key];
184
- trackById = trackByIdFn($scope, key, value);
185
- if (lastBlockMap[trackById]) {
186
- // found previously seen block
187
- block = lastBlockMap[trackById];
188
- delete lastBlockMap[trackById];
189
- nextBlockMap[trackById] = block;
190
- nextBlockOrder[index] = block;
191
- } else if (nextBlockMap[trackById]) {
192
- // if collision detected. restore lastBlockMap and throw an error
193
- Object.values(nextBlockOrder).forEach((block) => {
194
- if (block && block.scope) lastBlockMap[block.id] = block;
195
- });
196
- throw ngRepeatMinErr(
197
- "dupes",
198
- "Duplicates keys in a repeater are not allowed. Repeater: {0}, Duplicate key: {1} for value: {2}",
199
- expression,
200
- trackById,
201
- value,
202
- );
203
- } else {
204
- // new never before seen block
205
- nextBlockOrder[index] = {
206
- id: trackById,
207
- scope: undefined,
208
- clone: undefined,
209
- };
210
- nextBlockMap[trackById] = true;
198
+ // locate existing items
199
+ for (index = 0; index < collectionLength; index++) {
200
+ key =
201
+ collection === collectionKeys ? index : collectionKeys[index];
202
+ value = collection[key];
203
+ trackById = trackByIdFn($scope, key, value);
204
+ if (lastBlockMap[trackById]) {
205
+ // found previously seen block
206
+ block = lastBlockMap[trackById];
207
+ delete lastBlockMap[trackById];
208
+ nextBlockMap[trackById] = block;
209
+ nextBlockOrder[index] = block;
210
+ } else if (nextBlockMap[trackById]) {
211
+ // if collision detected. restore lastBlockMap and throw an error
212
+ Object.values(nextBlockOrder).forEach((block) => {
213
+ if (block && block.scope) lastBlockMap[block.id] = block;
214
+ });
215
+ throw ngRepeatMinErr(
216
+ "dupes",
217
+ "Duplicates keys in a repeater are not allowed. Repeater: {0}, Duplicate key: {1} for value: {2}",
218
+ expression,
219
+ trackById,
220
+ value,
221
+ );
222
+ } else {
223
+ // new never before seen block
224
+ nextBlockOrder[index] = {
225
+ id: trackById,
226
+ scope: undefined,
227
+ clone: undefined,
228
+ };
229
+ nextBlockMap[trackById] = true;
230
+ }
211
231
  }
212
- }
213
232
 
214
- // remove leftover items
215
- for (let blockKey in lastBlockMap) {
216
- block = lastBlockMap[blockKey];
217
- elementsToRemove = block.clone;
218
- if (hasAnimate) {
219
- $animate.leave(elementsToRemove);
220
- } else {
221
- elementsToRemove.remove();
222
- }
223
- if (elementsToRemove.parentNode) {
224
- // if the element was not removed yet because of pending animation, mark it as deleted
225
- // so that we can ignore it later
226
- for (
227
- index = 0, length = elementsToRemove.length;
228
- index < length;
229
- index++
230
- ) {
231
- elementsToRemove[index][NG_REMOVED] = true;
233
+ // remove leftover items
234
+ for (let blockKey in lastBlockMap) {
235
+ block = lastBlockMap[blockKey];
236
+ elementsToRemove = block.clone;
237
+ if (hasAnimate) {
238
+ $animate.leave(elementsToRemove);
239
+ } else {
240
+ elementsToRemove.remove();
232
241
  }
242
+ if (elementsToRemove.parentNode) {
243
+ // if the element was not removed yet because of pending animation, mark it as deleted
244
+ // so that we can ignore it later
245
+ for (
246
+ index = 0, length = elementsToRemove.length;
247
+ index < length;
248
+ index++
249
+ ) {
250
+ elementsToRemove[index][NG_REMOVED] = true;
251
+ }
252
+ }
253
+ block.scope.$destroy();
233
254
  }
234
- block.scope.$destroy();
235
- }
236
255
 
237
- for (index = 0; index < collectionLength; index++) {
238
- key = collection === collectionKeys ? index : collectionKeys[index];
239
- value = collection[key];
240
- block = nextBlockOrder[index];
256
+ for (index = 0; index < collectionLength; index++) {
257
+ key =
258
+ collection === collectionKeys ? index : collectionKeys[index];
259
+ value = collection[key];
260
+ block = nextBlockOrder[index];
241
261
 
242
- if (block.scope) {
243
- // if we have already seen this object, then we need to reuse the
244
- // associated scope/element
262
+ if (block.scope) {
263
+ // if we have already seen this object, then we need to reuse the
264
+ // associated scope/element
245
265
 
246
- nextNode = previousNode;
266
+ nextNode = previousNode;
247
267
 
248
- // skip nodes that are already pending removal via leave animation
249
- do {
250
- nextNode = nextNode.nextSibling;
251
- } while (nextNode && nextNode[NG_REMOVED]);
268
+ // skip nodes that are already pending removal via leave animation
269
+ do {
270
+ nextNode = nextNode.nextSibling;
271
+ } while (nextNode && nextNode[NG_REMOVED]);
252
272
 
253
- if (getBlockStart(block) !== nextNode) {
254
- // existing item which got moved
255
- $animate.move(getBlockNodes(block.clone), null, previousNode);
256
- }
257
- previousNode = getBlockEnd(block);
258
- updateScope(
259
- block.scope,
260
- index,
261
- valueIdentifier,
262
- value,
263
- keyIdentifier,
264
- key,
265
- collectionLength,
266
- );
267
- } else {
268
- // new item which we don't know about
269
- $transclude(
270
- /**
271
- * Clone attach function
272
- * @param {Array<NodeList>} clone
273
- * @param {import("../../core/scope/scope.js").Scope} scope
274
- */
273
+ if (getBlockStart(block) !== nextNode) {
274
+ // existing item which got moved
275
+ $animate.move(getBlockNodes(block.clone), null, previousNode);
276
+ }
277
+ previousNode = getBlockEnd(block);
278
+ updateScope(
279
+ block.scope,
280
+ index,
281
+ valueIdentifier,
282
+ value,
283
+ keyIdentifier,
284
+ key,
285
+ collectionLength,
286
+ );
287
+ } else {
288
+ // new item which we don't know about
289
+ $transclude(
290
+ /**
291
+ * Clone attach function
292
+ * @param {Array<NodeList>} clone
293
+ * @param {import("../../core/scope/scope.js").Scope} scope
294
+ */
275
295
 
276
- (clone, scope) => {
277
- block.scope = scope;
278
- const endNode = clone;
279
- if (hasAnimate) {
280
- $animate.enter(clone, null, previousNode);
281
- } else {
282
- // @ts-ignore
283
- previousNode.after(clone);
284
- }
296
+ (clone, scope) => {
297
+ block.scope = scope;
298
+ const endNode = clone;
299
+ if (hasAnimate) {
300
+ $animate.enter(clone, null, previousNode);
301
+ } else {
302
+ // @ts-ignore
303
+ previousNode.after(clone);
304
+ }
285
305
 
286
- // @ts-ignore
287
- previousNode = endNode;
288
- // Note: We only need the first/last node of the cloned nodes.
289
- // However, we need to keep the reference to the dom wrapper as it might be changed later
290
- // by a directive with templateUrl when its template arrives.
291
- block.clone = clone;
292
- nextBlockMap[block.id] = block;
293
- updateScope(
294
- block.scope,
295
- index,
296
- valueIdentifier,
297
- value,
298
- keyIdentifier,
299
- key,
300
- collectionLength,
301
- );
302
- },
303
- );
306
+ // @ts-ignore
307
+ previousNode = endNode;
308
+ // Note: We only need the first/last node of the cloned nodes.
309
+ // However, we need to keep the reference to the dom wrapper as it might be changed later
310
+ // by a directive with templateUrl when its template arrives.
311
+ block.clone = clone;
312
+ nextBlockMap[block.id] = block;
313
+ updateScope(
314
+ block.scope,
315
+ index,
316
+ valueIdentifier,
317
+ value,
318
+ keyIdentifier,
319
+ key,
320
+ collectionLength,
321
+ );
322
+ },
323
+ );
324
+ }
304
325
  }
305
- }
306
- lastBlockMap = nextBlockMap;
307
- });
326
+ lastBlockMap = nextBlockMap;
327
+ },
328
+ isDefined($attr["lazy"]),
329
+ );
308
330
  };
309
331
  },
310
332
  };
@@ -1,8 +1,11 @@
1
- ngSetterDirective.$inject = ["$parse", "$log"];
1
+ import { $injectTokens as $t } from "../../injection-tokens.js";
2
+
3
+ ngSetterDirective.$inject = [$t.$parse, $t.$log];
4
+
2
5
  /**
3
6
  * @param {import('../../core/parse/interface.ts').ParseService} $parse
4
7
  * @param {import('../../services/log/interface.ts').LogService} $log
5
- * @returns {import('../../interface.ts').Directive}
8
+ * @returns {import('interface.ts').Directive}
6
9
  */
7
10
  export function ngSetterDirective($parse, $log) {
8
11
  return {
@@ -11,19 +14,19 @@ export function ngSetterDirective($parse, $log) {
11
14
  const modelExpression = attrs["ngSetter"];
12
15
 
13
16
  if (!modelExpression) {
14
- $log.warn("ngSetter: Model expression is not provided.");
17
+ $log.warn("ng-setter: expression null");
15
18
  return;
16
19
  }
17
20
 
18
21
  const assignModel = $parse(modelExpression).assign;
19
22
 
20
23
  if (!assignModel) {
21
- $log.warn("ngSetter: Invalid model expression.");
24
+ $log.warn("ng-setter: expression invalid");
22
25
  return;
23
26
  }
24
27
 
25
28
  const updateModel = (value) => {
26
- assignModel(scope, value);
29
+ assignModel(scope, value.trim());
27
30
  };
28
31
 
29
32
  const observer = new MutationObserver((mutationsList) => {
@@ -43,16 +46,11 @@ export function ngSetterDirective($parse, $log) {
43
46
  }
44
47
  });
45
48
 
46
- if (element && element) {
47
- observer.observe(element, {
48
- childList: true,
49
- subtree: true,
50
- characterData: true,
51
- });
52
- } else {
53
- $log.warn("ngSetter: Element is not a valid DOM node.");
54
- return;
55
- }
49
+ observer.observe(element, {
50
+ childList: true,
51
+ subtree: true,
52
+ characterData: true,
53
+ });
56
54
 
57
55
  scope.$on("$destroy", () => observer.disconnect());
58
56
  updateModel(element.innerHTML);
@@ -7,7 +7,7 @@ describe("setter", () => {
7
7
 
8
8
  beforeEach(() => {
9
9
  dealoc(document.getElementById("app"));
10
- window.angular = new Angular();
10
+ let angular = new Angular();
11
11
  angular.module("myModule", []);
12
12
  angular
13
13
  .bootstrap(document.getElementById("app"), ["myModule"])
@@ -44,34 +44,57 @@ describe("setter", () => {
44
44
  expect($rootScope.testModel).toBe("Initial content");
45
45
  });
46
46
 
47
+ it("should handle expression content in the element", async () => {
48
+ $rootScope.testModel = "";
49
+ $compile('<div ng-setter="testModel"> {{ 2 + 2 }} </div>')($rootScope);
50
+ await wait();
51
+
52
+ expect($rootScope.testModel).toBe("4");
53
+ });
54
+
55
+ it("should handle expression and text content in the element", async () => {
56
+ $rootScope.testModel = "";
57
+ $compile('<div ng-setter="testModel"> Res: {{ 2 + 2 }} </div>')($rootScope);
58
+ await wait();
59
+
60
+ expect($rootScope.testModel).toBe("Res: 4");
61
+ });
62
+
63
+ it("should update value if expression changes", async () => {
64
+ $rootScope.a = 2;
65
+ $compile('<div ng-setter="testModel"> {{ a + 2 }} </div>')($rootScope);
66
+ await wait();
67
+ expect($rootScope.testModel).toBe("4");
68
+
69
+ $rootScope.a = 4;
70
+ await wait();
71
+ expect($rootScope.testModel).toBe("6");
72
+ });
73
+
47
74
  it("should warn if no model expression is provided", async () => {
48
75
  spyOn($log, "warn");
49
76
 
50
77
  $compile("<div ng-setter></div>")($rootScope);
51
78
  await wait();
52
79
 
53
- expect($log.warn).toHaveBeenCalledWith(
54
- "ngSetter: Model expression is not provided.",
55
- );
80
+ expect($log.warn).toHaveBeenCalledWith("ng-setter: expression null");
56
81
  });
57
82
 
58
- it("should clean up the MutationObserver on scope destruction", async () => {
59
- spyOn(window, "MutationObserver").and.returnValue(observerSpy);
60
- const element = $compile('<div ng-setter="testModel"></div>')($rootScope);
83
+ it("should warn if invalid model expression is provided", async () => {
84
+ spyOn($log, "warn");
61
85
 
62
- $rootScope.$destroy();
86
+ $compile("<div ng-setter='2+2'></div>")($rootScope);
63
87
  await wait();
64
- expect(observerSpy.disconnect).toHaveBeenCalled();
88
+
89
+ expect($log.warn).toHaveBeenCalledWith("ng-setter: expression invalid");
65
90
  });
66
91
 
67
- it("should gracefully handle invalid DOM elements", async () => {
68
- spyOn(console, "warn");
92
+ it("should clean up the MutationObserver on scope destruction", async () => {
93
+ spyOn(window, "MutationObserver").and.returnValue(observerSpy);
94
+ $compile('<div ng-setter="testModel"></div>')($rootScope);
69
95
 
70
- const element = $compile("<div></div>")($rootScope);
96
+ $rootScope.$destroy();
71
97
  await wait();
72
-
73
- expect(console.warn).not.toHaveBeenCalledWith(
74
- "ngSetter: Element is not a valid DOM node.",
75
- );
98
+ expect(observerSpy.disconnect).toHaveBeenCalled();
76
99
  });
77
100
  });
@@ -4,6 +4,7 @@ import { hasAnimate } from "../../shared/utils.js";
4
4
  ngSwitchDirective.$inject = ["$animate"];
5
5
 
6
6
  /**
7
+ * @param {*} $animate
7
8
  * @returns {import('../../interface.ts').Directive}
8
9
  */
9
10
  export function ngSwitchDirective($animate) {
@@ -209,7 +209,7 @@ describe("ngSwitch", () => {
209
209
 
210
210
  scope.$watch("value", () => {
211
211
  if (scope.value === "bar") {
212
- scope.$evalAsync(() => {
212
+ Promise.resolve().then(() => {
213
213
  scope.value = "baz";
214
214
  });
215
215
  }