@angular-wave/angular.ts 0.7.7 → 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 -1
- 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/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 +15 -0
- package/Makefile +3 -2
- package/dist/angular-ts.esm.js +982 -1190
- package/dist/angular-ts.umd.js +982 -1190
- package/dist/angular-ts.umd.min.js +1 -1
- package/docs/content/docs/directive/bind.md +9 -7
- package/docs/content/docs/directive/get.md +203 -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 +2 -2
- 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 -10
- 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 -2
- package/src/directive/attrs/attrs.js +7 -4
- package/src/directive/events/events.js +6 -2
- 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 +4 -0
- package/src/directive/model/model.js +1 -1
- package/src/directive/options/options.js +454 -464
- package/src/directive/setter/setter.js +12 -14
- package/src/directive/setter/setter.spec.js +39 -16
- package/src/directive/switch/switch.js +1 -0
- 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.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 +1 -1
- 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 +128 -26
- 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 +28 -0
- 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,14 +1,32 @@
|
|
|
1
1
|
import { Angular } from "../../loader.js";
|
|
2
2
|
import { browserTrigger, wait } from "../../shared/test-utils.js";
|
|
3
|
+
import { dealoc } from "../../shared/dom.js";
|
|
3
4
|
|
|
4
|
-
describe("
|
|
5
|
+
describe("ng-get", () => {
|
|
5
6
|
let $compile, $rootScope, $log, el;
|
|
6
7
|
|
|
7
8
|
beforeEach(() => {
|
|
8
9
|
el = document.getElementById("app");
|
|
10
|
+
dealoc(el);
|
|
9
11
|
el.innerHTML = "";
|
|
10
12
|
let angular = new Angular();
|
|
11
|
-
angular.module("default", [])
|
|
13
|
+
angular.module("default", []).config([
|
|
14
|
+
"$stateProvider",
|
|
15
|
+
"$locationProvider",
|
|
16
|
+
($stateProvider) => {
|
|
17
|
+
$stateProvider
|
|
18
|
+
.state({
|
|
19
|
+
name: "success",
|
|
20
|
+
url: "/success",
|
|
21
|
+
template: `success`,
|
|
22
|
+
})
|
|
23
|
+
.state({
|
|
24
|
+
name: "error",
|
|
25
|
+
url: "/error",
|
|
26
|
+
template: `error`,
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
]);
|
|
12
30
|
angular
|
|
13
31
|
.bootstrap(el, ["default"])
|
|
14
32
|
.invoke((_$compile_, _$rootScope_, _$log_) => {
|
|
@@ -37,6 +55,16 @@ describe("ngGet", () => {
|
|
|
37
55
|
expect(el.firstChild.innerHTML).toBe("<div>Hello</div>");
|
|
38
56
|
});
|
|
39
57
|
|
|
58
|
+
it("should compile innerHTML", async () => {
|
|
59
|
+
const scope = $rootScope.$new();
|
|
60
|
+
el.innerHTML = '<button ng-get="/mock/divexpr">Load</button>';
|
|
61
|
+
scope.expr = "World";
|
|
62
|
+
$compile(el)(scope);
|
|
63
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
64
|
+
await wait(100);
|
|
65
|
+
expect(el.innerText).toBe("World");
|
|
66
|
+
});
|
|
67
|
+
|
|
40
68
|
it("should replace innerHTML on error", async () => {
|
|
41
69
|
const scope = $rootScope.$new();
|
|
42
70
|
el.innerHTML = '<button ng-get="/mock/422">Load</button>';
|
|
@@ -55,7 +83,7 @@ describe("ngGet", () => {
|
|
|
55
83
|
expect(el.innerText).toBe("Load");
|
|
56
84
|
});
|
|
57
85
|
|
|
58
|
-
it("should replace innerHTML on
|
|
86
|
+
it("should replace innerHTML on status error without a body", async () => {
|
|
59
87
|
const scope = $rootScope.$new();
|
|
60
88
|
el.innerHTML = '<button ng-get="/mock/401">Load</button>';
|
|
61
89
|
$compile(el)(scope);
|
|
@@ -64,6 +92,111 @@ describe("ngGet", () => {
|
|
|
64
92
|
expect(el.innerText).toBe("Unauthorized");
|
|
65
93
|
});
|
|
66
94
|
|
|
95
|
+
describe("data-trigger", () => {
|
|
96
|
+
it("should not trigger request on click if element has trigger attribute", async () => {
|
|
97
|
+
el.innerHTML =
|
|
98
|
+
'<button ng-get="/mock/hello" data-trigger="mouseover">Load</button>';
|
|
99
|
+
const scope = $rootScope.$new();
|
|
100
|
+
$compile(el)(scope);
|
|
101
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
102
|
+
await wait(100);
|
|
103
|
+
expect(el.innerText).toBe("Load");
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("should trigger request on new event name if element has trigger attribute", async () => {
|
|
107
|
+
el.innerHTML =
|
|
108
|
+
'<button ng-get="/mock/hello" data-trigger="mouseover">Load</button>';
|
|
109
|
+
const scope = $rootScope.$new();
|
|
110
|
+
$compile(el)(scope);
|
|
111
|
+
browserTrigger(el.querySelector("button"), "mouseover");
|
|
112
|
+
await wait(100);
|
|
113
|
+
expect(el.innerText).toBe("Hello");
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe("data-latch", () => {
|
|
118
|
+
it("should trigger request on latch change", async () => {
|
|
119
|
+
el.innerHTML =
|
|
120
|
+
'<button ng-get="/mock/now" data-latch="{{ latch }}">Load</button>';
|
|
121
|
+
const scope = $rootScope.$new();
|
|
122
|
+
$compile(el)(scope);
|
|
123
|
+
await wait(100);
|
|
124
|
+
expect(el.innerText).toBe("Load");
|
|
125
|
+
scope.latch = true;
|
|
126
|
+
await wait(100);
|
|
127
|
+
expect(el.innerText).not.toBe("Load");
|
|
128
|
+
const firstRes = parseInt(el.innerText);
|
|
129
|
+
expect(firstRes).toBeLessThan(Date.now());
|
|
130
|
+
|
|
131
|
+
scope.latch = !scope.latch;
|
|
132
|
+
await wait(100);
|
|
133
|
+
const secondRes = parseInt(el.innerText);
|
|
134
|
+
expect(secondRes).toBeGreaterThan(firstRes);
|
|
135
|
+
|
|
136
|
+
scope.latch = !scope.latch;
|
|
137
|
+
await wait(100);
|
|
138
|
+
const thirdRes = parseInt(el.innerText);
|
|
139
|
+
expect(thirdRes).toBeGreaterThan(secondRes);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("should still work with events with latch change", async () => {
|
|
143
|
+
el.innerHTML =
|
|
144
|
+
'<button ng-get="/mock/now" data-latch="{{ latch }}">Load</button>';
|
|
145
|
+
const scope = $rootScope.$new();
|
|
146
|
+
$compile(el)(scope);
|
|
147
|
+
await wait(100);
|
|
148
|
+
expect(el.innerText).toBe("Load");
|
|
149
|
+
scope.latch = true;
|
|
150
|
+
await wait(100);
|
|
151
|
+
expect(el.innerText).not.toBe("Load");
|
|
152
|
+
const firstRes = parseInt(el.innerText);
|
|
153
|
+
expect(firstRes).toBeLessThan(Date.now());
|
|
154
|
+
|
|
155
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
156
|
+
await wait(100);
|
|
157
|
+
const secondRes = parseInt(el.innerText);
|
|
158
|
+
expect(secondRes).toBeGreaterThan(firstRes);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("should still work with custom events with latch change", async () => {
|
|
162
|
+
el.innerHTML =
|
|
163
|
+
'<button ng-get="/mock/now" data-latch="{{ latch }}" data-trigger="mouseover">Load</button>';
|
|
164
|
+
const scope = $rootScope.$new();
|
|
165
|
+
$compile(el)(scope);
|
|
166
|
+
await wait(100);
|
|
167
|
+
expect(el.innerText).toBe("Load");
|
|
168
|
+
scope.latch = true;
|
|
169
|
+
await wait(100);
|
|
170
|
+
expect(el.innerText).not.toBe("Load");
|
|
171
|
+
const firstRes = parseInt(el.innerText);
|
|
172
|
+
expect(firstRes).toBeLessThan(Date.now());
|
|
173
|
+
|
|
174
|
+
browserTrigger(el.querySelector("button"), "mouseover");
|
|
175
|
+
await wait(100);
|
|
176
|
+
const secondRes = parseInt(el.innerText);
|
|
177
|
+
expect(secondRes).toBeGreaterThan(firstRes);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("should still work with ng-event directives with latch change", async () => {
|
|
181
|
+
el.innerHTML =
|
|
182
|
+
'<button ng-get="/mock/now" data-latch="{{ latch }}" ng-mouseover="latch = !latch">Load</button>';
|
|
183
|
+
const scope = $rootScope.$new();
|
|
184
|
+
$compile(el)(scope);
|
|
185
|
+
await wait(100);
|
|
186
|
+
expect(el.innerText).toBe("Load");
|
|
187
|
+
browserTrigger(el.querySelector("button"), "mouseover");
|
|
188
|
+
await wait(100);
|
|
189
|
+
expect(el.innerText).not.toBe("Load");
|
|
190
|
+
const firstRes = parseInt(el.innerText);
|
|
191
|
+
expect(firstRes).toBeLessThan(Date.now());
|
|
192
|
+
|
|
193
|
+
browserTrigger(el.querySelector("button"), "mouseover");
|
|
194
|
+
await wait(100);
|
|
195
|
+
const secondRes = parseInt(el.innerText);
|
|
196
|
+
expect(secondRes).toBeGreaterThan(firstRes);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
67
200
|
describe("data-swap", () => {
|
|
68
201
|
it("should not change anything if swap is 'none'", async () => {
|
|
69
202
|
const scope = $rootScope.$new();
|
|
@@ -208,4 +341,148 @@ describe("ngGet", () => {
|
|
|
208
341
|
expect(el.lastChild.textContent).toBe("Hello");
|
|
209
342
|
});
|
|
210
343
|
});
|
|
344
|
+
|
|
345
|
+
describe("data-delay", () => {
|
|
346
|
+
it("should accept delay as a data attribute", async () => {
|
|
347
|
+
const scope = $rootScope.$new();
|
|
348
|
+
el.innerHTML =
|
|
349
|
+
'<button ng-get="/mock/hello" data-delay="1000">Load</button>';
|
|
350
|
+
$compile(el)(scope);
|
|
351
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
352
|
+
await wait(100);
|
|
353
|
+
expect(el.innerText).toBe("Load");
|
|
354
|
+
|
|
355
|
+
await wait(1000);
|
|
356
|
+
expect(el.innerText).toBe("Hello");
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
describe("data-throttle", () => {
|
|
361
|
+
it("should accept throttle as a data attribute", async () => {
|
|
362
|
+
const scope = $rootScope.$new();
|
|
363
|
+
el.innerHTML =
|
|
364
|
+
'<button ng-get="/mock/now" data-throttle="1000">Load</button>';
|
|
365
|
+
$compile(el)(scope);
|
|
366
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
367
|
+
await wait(100);
|
|
368
|
+
const firstRes = parseInt(el.innerText);
|
|
369
|
+
expect(firstRes).toBeLessThan(Date.now());
|
|
370
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
371
|
+
await wait(100);
|
|
372
|
+
const secondRes = parseInt(el.innerText);
|
|
373
|
+
expect(secondRes).toBe(firstRes);
|
|
374
|
+
|
|
375
|
+
await wait(900);
|
|
376
|
+
// should release the throttle
|
|
377
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
378
|
+
await wait(100);
|
|
379
|
+
const thirdRes = parseInt(el.innerText);
|
|
380
|
+
expect(thirdRes).toBeGreaterThan(firstRes);
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
describe("data-interval", () => {
|
|
385
|
+
it("should accept delay as a data attribute and should stop on $destroy", async () => {
|
|
386
|
+
const scope = $rootScope.$new();
|
|
387
|
+
el.innerHTML =
|
|
388
|
+
'<button ng-get="/mock/now" data-interval="100">Load</button>';
|
|
389
|
+
$compile(el)(scope);
|
|
390
|
+
|
|
391
|
+
await wait(200);
|
|
392
|
+
await wait(200);
|
|
393
|
+
const firstRes = parseInt(el.innerText);
|
|
394
|
+
expect(firstRes).toBeLessThan(Date.now());
|
|
395
|
+
await wait(200);
|
|
396
|
+
await wait(200);
|
|
397
|
+
const secondRes = parseInt(el.innerText);
|
|
398
|
+
expect(secondRes).toBeGreaterThan(firstRes);
|
|
399
|
+
await wait(200);
|
|
400
|
+
await wait(200);
|
|
401
|
+
const thirdRes = parseInt(el.innerText);
|
|
402
|
+
expect(thirdRes).toBeGreaterThan(secondRes);
|
|
403
|
+
|
|
404
|
+
scope.$broadcast("$destroy");
|
|
405
|
+
|
|
406
|
+
await wait(200);
|
|
407
|
+
await wait(200);
|
|
408
|
+
const finalRes = parseInt(el.innerText);
|
|
409
|
+
|
|
410
|
+
await wait(1000);
|
|
411
|
+
await wait(200);
|
|
412
|
+
expect(parseInt(el.innerText)).toEqual(finalRes);
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
describe("data-loading", () => {
|
|
417
|
+
it("should update loading data attribute", async () => {
|
|
418
|
+
const scope = $rootScope.$new();
|
|
419
|
+
el.innerHTML = '<button ng-get="/mock/now" data-loading>Load</button>';
|
|
420
|
+
$compile(el)(scope);
|
|
421
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
422
|
+
expect(el.querySelector("button").dataset.loading).toEqual("true");
|
|
423
|
+
await wait(200);
|
|
424
|
+
expect(el.querySelector("button").dataset.loading).toEqual("false");
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
describe("data-loading-class", () => {
|
|
429
|
+
it("should update class from data-loading-class attribute", async () => {
|
|
430
|
+
const scope = $rootScope.$new();
|
|
431
|
+
el.innerHTML =
|
|
432
|
+
'<button ng-get="/mock/now" data-loading-class="red">Load</button>';
|
|
433
|
+
$compile(el)(scope);
|
|
434
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
435
|
+
expect(el.querySelector("button").classList.contains("red")).toBeTrue();
|
|
436
|
+
await wait(200);
|
|
437
|
+
expect(el.querySelector("button").classList.contains("red")).toBeFalse();
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
describe("data-success", () => {
|
|
442
|
+
it("should evaluate expression passing result", async () => {
|
|
443
|
+
const scope = $rootScope.$new();
|
|
444
|
+
el.innerHTML =
|
|
445
|
+
'<button ng-get="/mock/hello" data-success="res = $res">Load</button>';
|
|
446
|
+
$compile(el)(scope);
|
|
447
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
448
|
+
await wait(200);
|
|
449
|
+
expect(scope.res).toEqual("Hello");
|
|
450
|
+
});
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
describe("data-state-success", () => {
|
|
454
|
+
it("should call stateService with success state", async () => {
|
|
455
|
+
const scope = $rootScope.$new();
|
|
456
|
+
el.innerHTML =
|
|
457
|
+
'<button ng-get="/mock/hello" data-state-success="success">Load</button><ng-view id="view"></ng-view>';
|
|
458
|
+
$compile(el)(scope);
|
|
459
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
460
|
+
await wait(200);
|
|
461
|
+
expect(document.getElementById("view").innerHTML).toEqual("success");
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
describe("data-state-error", () => {
|
|
466
|
+
it("should call stateService with success state", async () => {
|
|
467
|
+
const scope = $rootScope.$new();
|
|
468
|
+
el.innerHTML =
|
|
469
|
+
'<button ng-get="/mock/422" data-state-success="success" data-state-error="error">Load</button><ng-view id="view"></ng-view>';
|
|
470
|
+
$compile(el)(scope);
|
|
471
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
472
|
+
await wait(200);
|
|
473
|
+
expect(document.getElementById("view").innerHTML).toEqual("error");
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
describe("data-error", () => {
|
|
478
|
+
it("should evaluate expression passing result", async () => {
|
|
479
|
+
const scope = $rootScope.$new();
|
|
480
|
+
el.innerHTML =
|
|
481
|
+
'<button ng-get="/mock/422" data-error="res = $res">Load</button>';
|
|
482
|
+
$compile(el)(scope);
|
|
483
|
+
browserTrigger(el.querySelector("button"), "click");
|
|
484
|
+
await wait(200);
|
|
485
|
+
expect(scope.res).toEqual("Invalid data");
|
|
486
|
+
});
|
|
487
|
+
});
|
|
211
488
|
});
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $injectTokens as $ } from "../../injection-tokens.js";
|
|
2
|
+
import {
|
|
3
|
+
callBackAfterFirst,
|
|
4
|
+
isDefined,
|
|
5
|
+
isObject,
|
|
6
|
+
wait,
|
|
7
|
+
} from "../../shared/utils.js";
|
|
2
8
|
|
|
3
9
|
/**
|
|
4
10
|
* @param {"get" | "delete" | "post" | "put"} method
|
|
@@ -7,13 +13,20 @@ import { isObject } from "../../shared/utils.js";
|
|
|
7
13
|
function defineDirective(method) {
|
|
8
14
|
const attrName = "ng" + method.charAt(0).toUpperCase() + method.slice(1);
|
|
9
15
|
const directive = createHttpDirective(method, attrName);
|
|
10
|
-
directive["$inject"] = [
|
|
16
|
+
directive["$inject"] = [$.$http, $.$compile, $.$log, $.$parse, $.$state];
|
|
11
17
|
return directive;
|
|
12
18
|
}
|
|
13
19
|
|
|
20
|
+
/** @type {import('../../interface.ts').DirectiveFactory} */
|
|
14
21
|
export const ngGetDirective = defineDirective("get");
|
|
22
|
+
|
|
23
|
+
/** @type {import('../../interface.ts').DirectiveFactory} */
|
|
15
24
|
export const ngDeleteDirective = defineDirective("delete");
|
|
25
|
+
|
|
26
|
+
/** @type {import('../../interface.ts').DirectiveFactory} */
|
|
16
27
|
export const ngPostDirective = defineDirective("post");
|
|
28
|
+
|
|
29
|
+
/** @type {import('../../interface.ts').DirectiveFactory} */
|
|
17
30
|
export const ngPutDirective = defineDirective("put");
|
|
18
31
|
|
|
19
32
|
/**
|
|
@@ -40,7 +53,7 @@ export function getEventNameForElement(element) {
|
|
|
40
53
|
* Handles DOM manipulation based on a swap strategy and server-rendered HTML.
|
|
41
54
|
*
|
|
42
55
|
* @param {string} html - The HTML string returned from the server.
|
|
43
|
-
* @param {import("../../interface.ts").
|
|
56
|
+
* @param {import("../../interface.ts").SwapModeType} swap
|
|
44
57
|
* @param {Element} target - The target DOM element to apply the swap to.
|
|
45
58
|
* @param {import('../../core/scope/scope.js').Scope} scope
|
|
46
59
|
* @param {import('../../core/compile/compile.js').CompileFn} $compile
|
|
@@ -131,9 +144,11 @@ export function createHttpDirective(method, attrName) {
|
|
|
131
144
|
* @param {import("interface.ts").HttpService} $http
|
|
132
145
|
* @param {import("../../core/compile/compile.js").CompileFn} $compile
|
|
133
146
|
* @param {import("../../services/log/interface.ts").LogService} $log
|
|
147
|
+
* @param {import("../../core/parse/interface.ts").ParseService} $parse
|
|
148
|
+
* @param {import("../../router/state/state-service.js").StateProvider} $state
|
|
134
149
|
* @returns {import('../../interface.ts').Directive}
|
|
135
150
|
*/
|
|
136
|
-
return function ($http, $compile, $log) {
|
|
151
|
+
return function ($http, $compile, $log, $parse, $state) {
|
|
137
152
|
/**
|
|
138
153
|
* Collects form data from the element or its associated form.
|
|
139
154
|
*
|
|
@@ -194,16 +209,38 @@ export function createHttpDirective(method, attrName) {
|
|
|
194
209
|
restrict: "A",
|
|
195
210
|
terminal: true,
|
|
196
211
|
link(scope, element, attrs) {
|
|
197
|
-
|
|
198
|
-
|
|
212
|
+
const eventName =
|
|
213
|
+
attrs["trigger"] ||
|
|
214
|
+
/** @type {EventType} */ getEventNameForElement(element);
|
|
215
|
+
|
|
199
216
|
const tag = element.tagName.toLowerCase();
|
|
200
217
|
|
|
201
|
-
|
|
218
|
+
if (isDefined(attrs["latch"])) {
|
|
219
|
+
attrs.$observe(
|
|
220
|
+
"latch",
|
|
221
|
+
callBackAfterFirst(() =>
|
|
222
|
+
element.dispatchEvent(new Event(eventName)),
|
|
223
|
+
),
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
let throttled = false;
|
|
228
|
+
let intervalId;
|
|
229
|
+
|
|
230
|
+
if (isDefined(attrs["interval"])) {
|
|
231
|
+
element.dispatchEvent(new Event(eventName));
|
|
232
|
+
intervalId = setInterval(
|
|
233
|
+
() => element.dispatchEvent(new Event(eventName)),
|
|
234
|
+
parseInt(attrs["interval"]) || 1000,
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
element.addEventListener(eventName, async (event) => {
|
|
202
239
|
if (/** @type {HTMLButtonElement} */ (element).disabled) return;
|
|
203
240
|
if (tag === "form") event.preventDefault();
|
|
204
241
|
|
|
205
|
-
const swap =
|
|
206
|
-
const targetSelector =
|
|
242
|
+
const swap = attrs["swap"] || "innerHTML";
|
|
243
|
+
const targetSelector = attrs["target"];
|
|
207
244
|
const target = targetSelector
|
|
208
245
|
? document.querySelector(targetSelector)
|
|
209
246
|
: element;
|
|
@@ -220,18 +257,67 @@ export function createHttpDirective(method, attrName) {
|
|
|
220
257
|
}
|
|
221
258
|
|
|
222
259
|
const handler = (res) => {
|
|
260
|
+
if (isDefined(attrs["loading"])) {
|
|
261
|
+
attrs.$set("loading", false);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (isDefined(attrs["loadingClass"])) {
|
|
265
|
+
attrs.$removeClass(attrs["loadingClass"]);
|
|
266
|
+
}
|
|
267
|
+
|
|
223
268
|
const html = res.data;
|
|
269
|
+
if (200 <= res.status && res.status <= 299) {
|
|
270
|
+
if (isDefined(attrs["success"])) {
|
|
271
|
+
$parse(attrs["success"])(scope, { $res: html });
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (isDefined(attrs["stateSuccess"])) {
|
|
275
|
+
$state.go(attrs["stateSuccess"]);
|
|
276
|
+
}
|
|
277
|
+
} else if (400 <= res.status && res.status <= 599) {
|
|
278
|
+
if (isDefined(attrs["error"])) {
|
|
279
|
+
$parse(attrs["error"])(scope, { $res: html });
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (isDefined(attrs["stateError"])) {
|
|
283
|
+
$state.go(attrs["stateError"]);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
224
287
|
handleSwapResponse(
|
|
225
288
|
html,
|
|
226
|
-
/** @type {import("../../interface.ts").
|
|
227
|
-
swap
|
|
228
|
-
),
|
|
289
|
+
/** @type {import("../../interface.ts").SwapModeType} */ (swap),
|
|
229
290
|
target,
|
|
230
291
|
scope,
|
|
231
292
|
$compile,
|
|
232
293
|
);
|
|
233
294
|
};
|
|
234
295
|
|
|
296
|
+
if (isDefined(attrs["delay"])) {
|
|
297
|
+
await wait(parseInt(attrs["delay"]) | 0);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (throttled) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (isDefined(attrs["throttle"])) {
|
|
305
|
+
throttled = true;
|
|
306
|
+
attrs.$set("throttled", true);
|
|
307
|
+
setTimeout(() => {
|
|
308
|
+
attrs.$set("throttled", false);
|
|
309
|
+
throttled = false;
|
|
310
|
+
}, parseInt(attrs["throttle"]));
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (isDefined(attrs["loading"])) {
|
|
314
|
+
attrs.$set("loading", true);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (isDefined(attrs["loadingClass"])) {
|
|
318
|
+
attrs.$addClass(attrs["loadingClass"]);
|
|
319
|
+
}
|
|
320
|
+
|
|
235
321
|
if (method === "post" || method === "put") {
|
|
236
322
|
const data = collectFormData(element);
|
|
237
323
|
$http[method](url, data).then(handler).catch(handler);
|
|
@@ -239,6 +325,8 @@ export function createHttpDirective(method, attrName) {
|
|
|
239
325
|
$http[method](url).then(handler).catch(handler);
|
|
240
326
|
}
|
|
241
327
|
});
|
|
328
|
+
|
|
329
|
+
scope.$on("$destroy", () => clearInterval(intervalId));
|
|
242
330
|
},
|
|
243
331
|
};
|
|
244
332
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { test, expect } from "@playwright/test";
|
|
2
2
|
|
|
3
|
-
const TEST_URL = "src/directive/http/http.html";
|
|
3
|
+
const TEST_URL = "src/directive/http/http.html?random=false";
|
|
4
4
|
|
|
5
5
|
test("unit tests contain no errors", async ({ page }) => {
|
|
6
6
|
await page.goto(TEST_URL);
|
|
7
7
|
await page.content();
|
|
8
|
-
await page.waitForTimeout(
|
|
8
|
+
await page.waitForTimeout(10000);
|
|
9
9
|
await expect(page.locator(".jasmine-overall-result")).toHaveText(
|
|
10
10
|
/0 failures/,
|
|
11
11
|
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Angular } from "../../loader.js";
|
|
2
|
+
import { dealoc } from "../../shared/dom.js";
|
|
2
3
|
// import { browserTrigger, wait } from "../../shared/test-utils.js";
|
|
3
4
|
|
|
4
5
|
describe("ngPost", () => {
|
|
@@ -6,6 +7,7 @@ describe("ngPost", () => {
|
|
|
6
7
|
|
|
7
8
|
beforeEach(() => {
|
|
8
9
|
el = document.getElementById("app");
|
|
10
|
+
dealoc(el);
|
|
9
11
|
el.innerHTML = "";
|
|
10
12
|
let angular = new Angular();
|
|
11
13
|
angular.module("default", []);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Angular } from "../../loader.js";
|
|
2
|
+
import { dealoc } from "../../shared/dom.js";
|
|
2
3
|
// import { browserTrigger, wait } from "../../shared/test-utils.js";
|
|
3
4
|
|
|
4
5
|
describe("ngPut", () => {
|
|
@@ -6,6 +7,7 @@ describe("ngPut", () => {
|
|
|
6
7
|
|
|
7
8
|
beforeEach(() => {
|
|
8
9
|
el = document.getElementById("app");
|
|
10
|
+
dealoc(el);
|
|
9
11
|
el.innerHTML = "";
|
|
10
12
|
let angular = new Angular();
|
|
11
13
|
angular.module("default", []);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { isDefined } from "../../shared/utils.js";
|
|
2
2
|
import { hasAnimate } from "../../shared/utils.js";
|
|
3
|
-
import { $injectTokens } from "../../injection-tokens.js";
|
|
3
|
+
import { $injectTokens as $t } from "../../injection-tokens.js";
|
|
4
4
|
|
|
5
5
|
ngIncludeDirective.$inject = [
|
|
6
|
-
$
|
|
7
|
-
$
|
|
8
|
-
$
|
|
9
|
-
$
|
|
6
|
+
$t.$templateRequest,
|
|
7
|
+
$t.$anchorScroll,
|
|
8
|
+
$t.$animate,
|
|
9
|
+
$t.$exceptionHandler,
|
|
10
10
|
];
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -14,7 +14,7 @@ ngIncludeDirective.$inject = [
|
|
|
14
14
|
* @param {*} $templateRequest
|
|
15
15
|
* @param {import("../../services/anchor-scroll.js").AnchorScrollFunction} $anchorScroll
|
|
16
16
|
* @param {*} $animate
|
|
17
|
-
* @param {import('../../
|
|
17
|
+
* @param {import('../../services/exception/interface.ts').Interface} $exceptionHandler
|
|
18
18
|
* @returns {import('../../interface.js').Directive}
|
|
19
19
|
*/
|
|
20
20
|
export function ngIncludeDirective(
|
|
@@ -133,7 +133,7 @@ export function ngIncludeDirective(
|
|
|
133
133
|
// We need this directive so that the element content is already filled when
|
|
134
134
|
// the link function of another directive on the same element as ngInclude
|
|
135
135
|
// is called.
|
|
136
|
-
ngIncludeFillContentDirective.$inject = [
|
|
136
|
+
ngIncludeFillContentDirective.$inject = [$t.$compile];
|
|
137
137
|
|
|
138
138
|
/**
|
|
139
139
|
* @param {import("../../core/compile/compile.js").CompileFn} $compile
|
|
@@ -323,7 +323,6 @@ export function createDateInputType(type, regexp, parseDate) {
|
|
|
323
323
|
element,
|
|
324
324
|
attr,
|
|
325
325
|
ctrl,
|
|
326
|
-
$browser,
|
|
327
326
|
$filter,
|
|
328
327
|
$parse,
|
|
329
328
|
) {
|
|
@@ -610,15 +609,7 @@ export function isValidForStep(viewValue, stepBase, step) {
|
|
|
610
609
|
return (value - stepBase) % step === 0;
|
|
611
610
|
}
|
|
612
611
|
|
|
613
|
-
export function numberInputType(
|
|
614
|
-
scope,
|
|
615
|
-
element,
|
|
616
|
-
attr,
|
|
617
|
-
ctrl,
|
|
618
|
-
$browser,
|
|
619
|
-
$filter,
|
|
620
|
-
$parse,
|
|
621
|
-
) {
|
|
612
|
+
export function numberInputType(scope, element, attr, ctrl, $filter, $parse) {
|
|
622
613
|
badInputChecker(scope, element, attr, ctrl, "number");
|
|
623
614
|
numberFormatterParser(ctrl);
|
|
624
615
|
baseInputType(scope, element, attr, ctrl);
|
|
@@ -934,15 +925,7 @@ function parseConstantExpr($parse, context, name, expression, fallback) {
|
|
|
934
925
|
return fallback;
|
|
935
926
|
}
|
|
936
927
|
|
|
937
|
-
function checkboxInputType(
|
|
938
|
-
scope,
|
|
939
|
-
element,
|
|
940
|
-
attr,
|
|
941
|
-
ctrl,
|
|
942
|
-
$browser,
|
|
943
|
-
$filter,
|
|
944
|
-
$parse,
|
|
945
|
-
) {
|
|
928
|
+
function checkboxInputType(scope, element, attr, ctrl, $filter, $parse) {
|
|
946
929
|
const trueValue = parseConstantExpr(
|
|
947
930
|
$parse,
|
|
948
931
|
scope,
|
|
@@ -980,30 +963,25 @@ function checkboxInputType(
|
|
|
980
963
|
ctrl.$parsers.push((value) => (value ? trueValue : falseValue));
|
|
981
964
|
}
|
|
982
965
|
|
|
983
|
-
|
|
984
|
-
* @returns {import('../../interface.ts').Directive}
|
|
985
|
-
*/
|
|
986
|
-
inputDirective.$inject = ["$browser", "$filter", "$parse"];
|
|
966
|
+
inputDirective.$inject = ["$filter", "$parse"];
|
|
987
967
|
|
|
988
968
|
/**
|
|
989
|
-
* @param {import('../../services/browser').Browser} $browser
|
|
990
969
|
* @param {*} $filter
|
|
991
970
|
* @param {*} $parse
|
|
992
|
-
* @returns
|
|
971
|
+
* @returns {import('../../interface.ts').Directive}
|
|
993
972
|
*/
|
|
994
|
-
export function inputDirective($
|
|
973
|
+
export function inputDirective($filter, $parse) {
|
|
995
974
|
return {
|
|
996
975
|
restrict: "E",
|
|
997
976
|
require: ["?ngModel"],
|
|
998
977
|
link: {
|
|
999
978
|
pre(scope, element, attr, ctrls) {
|
|
1000
979
|
if (ctrls[0]) {
|
|
1001
|
-
(inputType[lowercase(attr
|
|
980
|
+
(inputType[lowercase(attr["type"])] || inputType.text)(
|
|
1002
981
|
scope,
|
|
1003
982
|
element,
|
|
1004
983
|
attr,
|
|
1005
984
|
ctrls[0],
|
|
1006
|
-
$browser,
|
|
1007
985
|
$filter,
|
|
1008
986
|
$parse,
|
|
1009
987
|
);
|
|
@@ -238,6 +238,10 @@ export const ngMessageDirective = ngMessageDirectiveFactory(false);
|
|
|
238
238
|
export const ngMessageExpDirective = ngMessageDirectiveFactory(false);
|
|
239
239
|
export const ngMessageDefaultDirective = ngMessageDirectiveFactory(true);
|
|
240
240
|
|
|
241
|
+
/**
|
|
242
|
+
* @param {boolean} isDefault
|
|
243
|
+
* @returns {(any) => import("../../interface.js").Directive}
|
|
244
|
+
*/
|
|
241
245
|
function ngMessageDirectiveFactory(isDefault) {
|
|
242
246
|
ngMessageDirective.$inject = ["$animate"];
|
|
243
247
|
function ngMessageDirective($animate) {
|
|
@@ -78,7 +78,7 @@ export class NgModelController {
|
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
80
|
* @param {import('../../core/scope/scope.js').Scope} $scope
|
|
81
|
-
* @param {import('../../
|
|
81
|
+
* @param {import('../../services/exception/exception-handler.js').ErrorHandler} $exceptionHandler
|
|
82
82
|
* @param {import('../../core/compile/attributes.js').Attributes} $attr
|
|
83
83
|
* @param {Element} $element
|
|
84
84
|
* @param {import("../../core/parse/interface.ts").ParseService} $parse
|