@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.
- package/@types/animations/raf-scheduler.d.ts +2 -2
- package/@types/animations/shared.d.ts +0 -1
- package/@types/core/compile/attributes.d.ts +3 -3
- package/@types/core/compile/compile.d.ts +1 -1
- package/@types/core/di/injector.d.ts +0 -1
- package/@types/core/di/internal-injector.d.ts +1 -0
- package/@types/core/di/ng-module.d.ts +5 -0
- package/@types/core/filter/filter.d.ts +11 -13
- package/@types/core/sanitize/sanitize-uri.d.ts +3 -6
- package/@types/core/scope/scope.d.ts +1 -3
- package/@types/directive/attrs/attrs.d.ts +7 -1
- package/@types/directive/events/events.d.ts +9 -3
- package/@types/directive/http/http.d.ts +6 -2
- package/@types/directive/include/include.d.ts +2 -2
- package/@types/directive/input/input.d.ts +2 -12
- package/@types/directive/messages/messages.d.ts +9 -48
- package/@types/directive/model/model.d.ts +3 -3
- package/@types/directive/options/options.d.ts +13 -20
- package/@types/directive/setter/setter.d.ts +2 -2
- package/@types/directive/switch/switch.d.ts +1 -0
- package/@types/directive/transclude/transclude.d.ts +10 -6
- package/@types/interface.d.ts +54 -18
- package/@types/router/common/glob.d.ts +5 -1
- package/@types/router/directives/view-directive.d.ts +2 -19
- package/@types/router/globals.d.ts +1 -2
- package/@types/router/state/state-registry.d.ts +1 -2
- package/@types/router/url/url-service.d.ts +7 -9
- package/@types/services/anchor-scroll.d.ts +1 -1
- package/@types/{core → services/exception}/exception-handler.d.ts +4 -4
- package/@types/{core/error-handler.d.ts → services/exception/interface.d.ts} +1 -1
- package/@types/services/http/http.d.ts +0 -2
- package/@types/services/http/interface.d.ts +2 -2
- package/@types/services/http-backend/http-backend.d.ts +13 -21
- package/@types/services/location/interface.d.ts +8 -0
- package/@types/{core → services}/location/location.d.ts +52 -12
- package/@types/{core → services}/sce/sce.d.ts +1 -1
- package/@types/services/template-cache/interface.d.ts +8 -2
- package/@types/services/template-cache/template-cache.d.ts +1 -1
- package/@types/services/template-request.d.ts +1 -1
- package/@types/shared/cache.d.ts +0 -2
- package/@types/shared/dom.d.ts +6 -0
- package/@types/shared/test-utils.d.ts +1 -0
- package/@types/shared/url-utils/interface.d.ts +47 -0
- package/@types/{core → shared}/url-utils/url-utils.d.ts +26 -13
- package/@types/shared/utils.d.ts +23 -0
- package/Makefile +3 -2
- package/dist/angular-ts.esm.js +1188 -1364
- package/dist/angular-ts.umd.js +1188 -1364
- package/dist/angular-ts.umd.min.js +1 -1
- package/docs/assets/scss/index.scss +12 -0
- package/docs/content/_index.md +15 -4
- package/docs/content/docs/directive/bind.md +72 -0
- package/docs/content/docs/directive/click.md +3 -0
- package/docs/content/docs/directive/dblclick.md +3 -0
- package/docs/content/docs/directive/get.md +203 -0
- package/docs/content/docs/directive/keydown.md +38 -0
- package/docs/content/docs/directive/keyup.md +38 -0
- package/docs/content/docs/directive/load.md +43 -0
- package/docs/content/docs/provider/templateCacheProvider.md +66 -1
- package/docs/content/docs/service/templateCache.md +2 -2
- package/docs/layouts/partials/hooks/head-end.html +1 -1
- package/docs/layouts/shortcodes/showcss.html +2 -0
- package/docs/static/examples/ng-bind/ng-bind.html +9 -0
- package/docs/static/examples/ng-keydown/ng-keydown.html +9 -0
- package/docs/static/examples/ng-keyup/ng-keyup.html +9 -0
- package/docs/static/examples/ng-load/ng-load.html +8 -0
- package/docs/static/typedoc/assets/hierarchy.js +1 -1
- package/docs/static/typedoc/assets/navigation.js +1 -1
- package/docs/static/typedoc/assets/search.js +1 -1
- package/docs/static/typedoc/classes/NgModule.html +32 -0
- package/docs/static/typedoc/classes/TemplateCacheProvider.html +1 -1
- package/docs/static/typedoc/hierarchy.html +1 -1
- package/docs/static/typedoc/index.html +1 -1
- package/docs/static/typedoc/interfaces/Directive.html +5 -4
- package/docs/static/typedoc/interfaces/HttpProviderDefaults.html +1 -1
- package/docs/static/typedoc/interfaces/HttpResponse.html +2 -3
- package/docs/static/typedoc/interfaces/Provider.html +15 -10
- package/docs/static/typedoc/interfaces/RequestConfig.html +1 -1
- package/docs/static/typedoc/interfaces/RequestShortcutConfig.html +1 -1
- package/docs/static/typedoc/interfaces/TemplateCache.html +7 -0
- package/docs/static/typedoc/types/AnnotatedDirectiveFactory.html +1 -0
- package/docs/static/typedoc/types/DirectiveFactory.html +1 -2
- package/docs/static/typedoc/types/DirectiveFactoryFn.html +1 -0
- package/docs/static/typedoc/types/HttpResponseStatus.html +1 -0
- package/docs/static/typedoc/types/{TemplateCache.html → SwapModeType.html} +1 -1
- package/docs/static/typedoc/variables/SwapMode.html +11 -0
- package/legacy.d.ts +0 -14
- package/package.json +1 -3
- package/src/animations/animate-children-directive.js +2 -2
- package/src/animations/raf-scheduler.js +1 -1
- package/src/animations/shared.js +0 -9
- package/src/core/compile/attributes.js +1 -1
- package/src/core/compile/compile.js +3 -3
- package/src/core/di/injector.js +4 -17
- package/src/core/di/internal-injector.js +4 -1
- package/src/core/di/ng-module.js +12 -27
- package/src/core/filter/filter.js +28 -28
- package/src/core/parse/interpreter.js +32 -38
- package/src/core/sanitize/sanitize-uri.js +3 -3
- package/src/core/scope/scope.js +2 -7
- package/src/directive/attrs/attrs.js +7 -4
- package/src/directive/bind/bind.js +16 -4
- package/src/directive/bind/bind.spec.js +13 -0
- package/src/directive/events/events.js +7 -3
- package/src/directive/events/events.md +0 -41
- package/src/directive/http/delete.spec.js +2 -0
- package/src/directive/http/get.spec.js +280 -3
- package/src/directive/http/http.js +100 -12
- package/src/directive/http/http.test.js +2 -2
- package/src/directive/http/post.spec.js +2 -0
- package/src/directive/http/put.spec.js +2 -0
- package/src/directive/include/include.js +7 -7
- package/src/directive/input/input.js +6 -28
- package/src/directive/messages/messages.js +5 -1
- package/src/directive/model/model.js +1 -1
- package/src/directive/options/options.js +454 -464
- package/src/directive/repeat/repeat.js +175 -153
- package/src/directive/setter/setter.js +13 -15
- package/src/directive/setter/setter.spec.js +39 -16
- package/src/directive/switch/switch.js +1 -0
- package/src/directive/switch/switch.spec.js +1 -1
- package/src/directive/transclude/transclude.js +87 -89
- package/src/injection-tokens.js +1 -1
- package/src/interface.ts +68 -19
- package/src/loader.js +4 -9
- package/src/public.js +9 -15
- package/src/router/common/glob.js +5 -0
- package/src/router/directives/state-directives.js +4 -6
- package/src/router/directives/state-directives.spec.js +1 -1
- package/src/router/directives/view-directive.js +9 -1
- package/src/router/globals.js +0 -1
- package/src/router/state/state-registry.js +0 -1
- package/src/router/state-filters.js +2 -2
- package/src/router/url/url-service.js +5 -9
- package/src/services/anchor-scroll.html +0 -7
- package/src/services/anchor-scroll.js +2 -2
- package/src/{core → services/exception}/exception-handler.js +2 -2
- package/src/{core/error-handler.ts → services/exception/interface.ts} +1 -1
- package/src/services/http/http.js +2 -13
- package/src/services/http/interface.ts +2 -2
- package/src/services/http-backend/http-backend.js +4 -14
- package/src/services/http-backend/http-backend.spec.js +1 -4
- package/src/services/location/interface.ts +8 -0
- package/src/{core → services}/location/location.html +4 -1
- package/src/{core → services}/location/location.js +129 -27
- package/src/{core → services}/location/location.spec.js +2 -2
- package/src/{core → services}/location/location.test.js +1 -1
- package/src/{core → services}/sce/sce.html +1 -1
- package/src/{core → services}/sce/sce.js +9 -3
- package/src/{core → services}/sce/sce.spec.js +2 -3
- package/src/{core → services}/sce/sce.test.js +1 -1
- package/src/services/template-cache/interface.ts +8 -2
- package/src/services/template-cache/template-cache.js +3 -1
- package/src/services/template-cache/template-cache.spec.js +72 -0
- package/src/services/template-request.js +2 -1
- package/src/shared/cache.js +0 -2
- package/src/shared/dom.js +10 -0
- package/src/shared/test-utils.js +1 -0
- package/src/shared/url-utils/interface.ts +56 -0
- package/src/{core → shared}/url-utils/url-utils.html +4 -1
- package/src/{core → shared}/url-utils/url-utils.js +26 -23
- package/src/{core → shared}/url-utils/url-utils.spec.js +0 -8
- package/src/{core → shared}/url-utils/url-utils.test.js +1 -1
- package/src/shared/utils.js +47 -1
- package/utils/express.js +9 -1
- package/@types/core/task-tracker-factory.d.ts +0 -76
- package/@types/services/browser.d.ts +0 -101
- package/docs/static/typedoc/types/SwapInsertPosition.html +0 -2
- package/jsdoc.json +0 -22
- package/src/core/task-tracker-factory.js +0 -145
- package/src/services/browser.js +0 -212
- /package/src/{core → services}/location/location.md +0 -0
- /package/src/{core → services}/sce/sce.md +0 -0
- /package/src/{core → shared}/url-utils/url-utils.md +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
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: (
|
|
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(
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
177
|
+
if (aliasAs) {
|
|
178
|
+
$scope[aliasAs] = collection;
|
|
179
|
+
}
|
|
162
180
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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
|
-
|
|
178
|
-
|
|
195
|
+
collectionLength = collectionKeys.length;
|
|
196
|
+
nextBlockOrder = new Array(collectionLength);
|
|
179
197
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
266
|
+
nextNode = previousNode;
|
|
247
267
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
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
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
-
|
|
307
|
-
|
|
326
|
+
lastBlockMap = nextBlockMap;
|
|
327
|
+
},
|
|
328
|
+
isDefined($attr["lazy"]),
|
|
329
|
+
);
|
|
308
330
|
};
|
|
309
331
|
},
|
|
310
332
|
};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
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('
|
|
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("
|
|
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("
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
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
|
|
59
|
-
spyOn(
|
|
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
|
-
$
|
|
86
|
+
$compile("<div ng-setter='2+2'></div>")($rootScope);
|
|
63
87
|
await wait();
|
|
64
|
-
|
|
88
|
+
|
|
89
|
+
expect($log.warn).toHaveBeenCalledWith("ng-setter: expression invalid");
|
|
65
90
|
});
|
|
66
91
|
|
|
67
|
-
it("should
|
|
68
|
-
spyOn(
|
|
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
|
-
|
|
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
|
});
|