@angular-wave/angular.ts 0.4.2 → 0.4.4
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/dist/angular-ts.esm.js +2 -2
- package/dist/angular-ts.umd.js +12 -2
- package/index.html +74 -3
- package/package.json +7 -7
- package/src/angular.spec.js +1 -269
- package/src/animations/animate-css-driver.js +2 -2
- package/src/animations/animate-css.js +12 -21
- package/src/animations/animate-js-driver.js +1 -3
- package/src/animations/animate-js.js +4 -4
- package/src/animations/animate-queue.js +23 -23
- package/src/animations/animate-runner.js +4 -8
- package/src/animations/animate.md +1 -1
- package/src/animations/animate.spec.js +0 -21
- package/src/animations/animation.js +4 -4
- package/src/animations/shared.js +14 -12
- package/src/binding.spec.js +0 -1
- package/src/core/cache/cache.js +2 -29
- package/src/core/compile/attributes.js +2 -3
- package/src/core/compile/compile.js +260 -245
- package/src/core/compile/compile.spec.js +63 -317
- package/src/core/compile/compile.test.js +1 -1
- package/src/core/controller/controller.js +2 -0
- package/src/core/di/injector.md +1 -1
- package/src/core/di/injector.spec.js +0 -2
- package/src/core/di/internal-injector.js +2 -1
- package/src/core/interpolate/interpolate.js +16 -3
- package/src/core/interpolate/interpolate.spec.js +70 -16
- package/src/core/location/location.js +0 -2
- package/src/core/location/location.spec.js +27 -27
- package/src/core/{scope/scope.html → model/model.html} +1 -1
- package/src/core/model/model.js +944 -0
- package/src/core/model/model.spec.js +3012 -0
- package/src/core/on.spec.js +0 -7
- package/src/core/parse/interpreter.js +10 -7
- package/src/core/parse/parse.js +28 -7
- package/src/core/parse/parse.spec.js +95 -91
- package/src/core/prop.spec.js +4 -60
- package/src/core/sce/sce.js +1 -2
- package/src/core/sce/sce.spec.js +0 -8
- package/src/core/scope/scope.js +62 -32
- package/src/core/scope/scope.spec.js +25 -1960
- package/src/directive/aria/aria.js +3 -6
- package/src/directive/aria/aria.spec.js +0 -87
- package/src/directive/attrs/attrs.spec.js +0 -5
- package/src/directive/{list/list.test.js → attrs/attrs.test.js} +1 -1
- package/src/{core/q/q.html → directive/attrs/boolean.html} +1 -1
- package/src/directive/attrs/boolean.spec.js +0 -15
- package/src/{core/q/q.test.js → directive/attrs/boolean.test.js} +1 -2
- package/src/{core/timeout/timeout.html → directive/attrs/element-style.html} +4 -1
- package/src/directive/attrs/element-style.spec.js +0 -8
- package/src/{core/scope/scope.test.js → directive/attrs/element-style.test.js} +1 -2
- package/src/directive/attrs/src.spec.js +0 -7
- package/src/directive/bind/bind.spec.js +0 -33
- package/src/directive/bind/bing-html.spec.js +1 -4
- package/src/{core/interval/interval.html → directive/channel/channel.html} +1 -1
- package/src/directive/channel/channel.js +29 -0
- package/src/directive/channel/channel.spec.js +52 -0
- package/src/directive/channel/channel.test.js +9 -0
- package/src/directive/class/class.js +3 -3
- package/src/directive/class/class.spec.js +9 -75
- package/src/directive/controller/controller.spec.js +0 -13
- package/src/directive/events/click.spec.js +0 -3
- package/src/directive/events/event.spec.js +0 -6
- package/src/directive/form/form.js +14 -22
- package/src/directive/form/form.spec.js +0 -65
- package/src/directive/if/if.spec.js +2 -7
- package/src/directive/if/if.test.js +1 -2
- package/src/directive/include/include.js +2 -2
- package/src/directive/include/include.spec.js +8 -59
- package/src/directive/init/init.js +6 -2
- package/src/directive/init/init.spec.js +0 -2
- package/src/directive/input/input.js +1 -2
- package/src/directive/input/input.spec.js +191 -331
- package/src/directive/messages/messages.spec.js +4 -35
- package/src/directive/model/model.js +30 -42
- package/src/directive/model/model.spec.js +2 -49
- package/src/directive/model-options/model-options.js +22 -26
- package/src/directive/model-options/model-options.spec.js +0 -6
- package/src/directive/non-bindable/non-bindable.spec.js +0 -1
- package/src/directive/observe/observe.js +0 -1
- package/src/directive/observe/observe.spec.js +0 -1
- package/src/directive/options/options.js +1 -3
- package/src/directive/options/options.spec.js +3 -38
- package/src/directive/ref/href.spec.js +0 -15
- package/src/directive/repeat/repeat.js +2 -2
- package/src/directive/repeat/repeat.spec.js +56 -192
- package/src/directive/script/script.spec.js +0 -2
- package/src/directive/select/select.js +3 -3
- package/src/directive/select/select.spec.js +9 -106
- package/src/directive/show-hide/show-hide.js +2 -2
- package/src/directive/show-hide/show-hide.spec.js +8 -19
- package/src/directive/style/style.spec.js +0 -7
- package/src/directive/switch/switch.js +1 -2
- package/src/directive/switch/switch.spec.js +5 -5
- package/src/directive/validators/validators.spec.js +0 -1
- package/src/loader.js +0 -1
- package/src/public.js +75 -80
- package/src/router/common/coreservices.js +0 -2
- package/src/router/directives/state-directives.js +24 -30
- package/src/router/directives/state-directives.spec.js +0 -83
- package/src/router/directives/view-directive.js +6 -15
- package/src/router/directives/view-directive.spec.js +25 -71
- package/src/router/hooks/lazy-load.js +2 -2
- package/src/router/hooks/views.js +3 -5
- package/src/router/resolve/resolvable.js +3 -6
- package/src/router/resolve/resolve-context.js +2 -2
- package/src/router/state/state-service.js +4 -4
- package/src/router/state/state.spec.js +2 -5
- package/src/router/state/views.js +9 -12
- package/src/router/template-factory.js +3 -6
- package/src/router/template-factory.spec.js +0 -4
- package/src/router/transition/transition-hook.js +1 -1
- package/src/router/transition/transition.js +1 -1
- package/src/router/url/url-service.js +2 -8
- package/src/router/url/url-service.spec.js +3 -4
- package/src/router/view-hook.spec.js +2 -2
- package/src/router/view-scroll.js +4 -6
- package/src/services/http/http.js +11 -15
- package/src/services/http/http.spec.js +30 -31
- package/src/services/http/template-request.spec.js +0 -10
- package/src/services/http-backend/http-backend.js +19 -17
- package/src/services/http-backend/http-backend.spec.js +3 -3
- package/src/services/template-request.js +2 -4
- package/src/shared/common.js +6 -10
- package/src/shared/jqlite/jqlite.js +14 -15
- package/src/shared/jqlite/jqlite.spec.js +2 -2
- package/src/shared/utils.js +15 -92
- package/types/core/cache/cache.d.ts +1 -1
- package/types/core/model/model.d.ts +204 -0
- package/types/core/parse/parse.d.ts +26 -0
- package/types/core/scope/scope.d.ts +22 -21
- package/types/directive/channel/channel.d.ts +11 -0
- package/types/directive/form/form.d.ts +1 -0
- package/types/shared/common.d.ts +0 -1
- package/types/shared/utils.d.ts +0 -35
- package/src/core/interval/interval-factory.js +0 -50
- package/src/core/interval/interval.js +0 -77
- package/src/core/interval/interval.md +0 -123
- package/src/core/interval/interval.spec.js +0 -280
- package/src/core/q/q.js +0 -472
- package/src/core/q/q.md +0 -211
- package/src/core/q/q.spec.js +0 -2748
- package/src/core/timeout/timeout.js +0 -109
- package/src/core/timeout/timeout.spec.js +0 -354
- package/src/core/timeout/timout.test.js +0 -12
- package/src/directive/list/list.html +0 -18
- package/src/directive/list/list.js +0 -46
- package/src/directive/list/list.md +0 -22
- package/src/directive/list/list.spec.js +0 -172
- package/types/directive/list/list.d.ts +0 -4
|
@@ -48,8 +48,6 @@ describe("ngMessages", () => {
|
|
|
48
48
|
' <div ng-message="val">Message is set</div>' +
|
|
49
49
|
"</div>",
|
|
50
50
|
)($rootScope);
|
|
51
|
-
$rootScope.$digest();
|
|
52
|
-
|
|
53
51
|
expect(element.text()).not.toContain("Message is set");
|
|
54
52
|
|
|
55
53
|
$rootScope.$apply(() => {
|
|
@@ -65,8 +63,6 @@ describe("ngMessages", () => {
|
|
|
65
63
|
' <div ng-message="one, two, three">Message is set</div>' +
|
|
66
64
|
"</div>",
|
|
67
65
|
)($rootScope);
|
|
68
|
-
$rootScope.$digest();
|
|
69
|
-
|
|
70
66
|
expect(element.text()).not.toContain("Message is set");
|
|
71
67
|
|
|
72
68
|
$rootScope.$apply(() => {
|
|
@@ -100,8 +96,6 @@ describe("ngMessages", () => {
|
|
|
100
96
|
' <ng-message when="val">Message is set</div>' +
|
|
101
97
|
"</ng-messages>",
|
|
102
98
|
)($rootScope);
|
|
103
|
-
$rootScope.$digest();
|
|
104
|
-
|
|
105
99
|
expect(element.text()).not.toContain("Message is set");
|
|
106
100
|
|
|
107
101
|
$rootScope.$apply(() => {
|
|
@@ -117,8 +111,6 @@ describe("ngMessages", () => {
|
|
|
117
111
|
' <ng-message when=" one two three ">Message is set</div>' +
|
|
118
112
|
"</ng-messages>",
|
|
119
113
|
)($rootScope);
|
|
120
|
-
$rootScope.$digest();
|
|
121
|
-
|
|
122
114
|
expect(element.text()).not.toContain("Message is set");
|
|
123
115
|
|
|
124
116
|
$rootScope.$apply(() => {
|
|
@@ -152,8 +144,6 @@ describe("ngMessages", () => {
|
|
|
152
144
|
' <div ng-message-exp="variable">Message is crazy</div>' +
|
|
153
145
|
"</div>",
|
|
154
146
|
)($rootScope);
|
|
155
|
-
$rootScope.$digest();
|
|
156
|
-
|
|
157
147
|
expect(element.text()).not.toContain("Message is crazy");
|
|
158
148
|
|
|
159
149
|
$rootScope.$apply(() => {
|
|
@@ -188,8 +178,6 @@ describe("ngMessages", () => {
|
|
|
188
178
|
' <ng-message when-exp="variable">Message is crazy</ng-message>' +
|
|
189
179
|
"</ng-messages>",
|
|
190
180
|
)($rootScope);
|
|
191
|
-
$rootScope.$digest();
|
|
192
|
-
|
|
193
181
|
expect(element.text()).not.toContain("Message is crazy");
|
|
194
182
|
|
|
195
183
|
$rootScope.$apply(() => {
|
|
@@ -236,7 +224,7 @@ describe("ngMessages", () => {
|
|
|
236
224
|
// ' <div ng-message="val">Message is set</div>' +
|
|
237
225
|
// "</div>",
|
|
238
226
|
// )($rootScope);
|
|
239
|
-
//
|
|
227
|
+
// ;
|
|
240
228
|
|
|
241
229
|
// $rootScope.$apply(() => {
|
|
242
230
|
// $rootScope.col = prop;
|
|
@@ -460,14 +448,11 @@ describe("ngMessages", () => {
|
|
|
460
448
|
|
|
461
449
|
// Trigger the message to be displayed
|
|
462
450
|
$rootScope.col = { primary: true };
|
|
463
|
-
$rootScope.$digest();
|
|
464
451
|
expect(messageChildren(element).length).toEqual(1);
|
|
465
452
|
const oldMessageNode = messageChildren(element)[0];
|
|
466
453
|
|
|
467
454
|
// Remove the message
|
|
468
455
|
$rootScope.col = { primary: undefined };
|
|
469
|
-
$rootScope.$digest();
|
|
470
|
-
|
|
471
456
|
// Since we have spied on the `leave` method, the message node is still in the DOM
|
|
472
457
|
//expect($animate.leave).toHaveBeenCalled();
|
|
473
458
|
// const nodeToRemove = $animate.leave.calls.mostRecent().args[0][0];
|
|
@@ -475,8 +460,6 @@ describe("ngMessages", () => {
|
|
|
475
460
|
|
|
476
461
|
// Add the message back in
|
|
477
462
|
$rootScope.col = { primary: true };
|
|
478
|
-
$rootScope.$digest();
|
|
479
|
-
|
|
480
463
|
// Simulate the animation completing on the node
|
|
481
464
|
// JQLite(nodeToRemove).remove();
|
|
482
465
|
|
|
@@ -570,9 +553,7 @@ describe("ngMessages", () => {
|
|
|
570
553
|
const deregisterSpy = spyOn(ctrl, "deregister").and.callThrough();
|
|
571
554
|
|
|
572
555
|
const nodeA = element[0].querySelector('[ng-message="a"]');
|
|
573
|
-
JQLite(nodeA).remove();
|
|
574
|
-
$rootScope.$digest(); // The next digest triggers the error
|
|
575
|
-
|
|
556
|
+
JQLite(nodeA).remove(); // The next digest triggers the error
|
|
576
557
|
// Make sure removing the element triggers the deregistration in ngMessages
|
|
577
558
|
expect(trim(deregisterSpy.calls.mostRecent().args[0].nodeValue)).toBe("");
|
|
578
559
|
expect(messageChildren(element).length).toBe(0);
|
|
@@ -609,9 +590,7 @@ describe("ngMessages", () => {
|
|
|
609
590
|
const deregisterSpy = spyOn(ctrl, "deregister").and.callThrough();
|
|
610
591
|
|
|
611
592
|
const nodeB = element[0].querySelector('[ng-message="b"]');
|
|
612
|
-
JQLite(nodeB).remove();
|
|
613
|
-
$rootScope.$digest(); // The next digest triggers the error
|
|
614
|
-
|
|
593
|
+
JQLite(nodeB).remove(); // The next digest triggers the error
|
|
615
594
|
// Make sure removing the element triggers the deregistration in ngMessages
|
|
616
595
|
expect(trim(deregisterSpy.calls.mostRecent().args[0].nodeValue)).toBe(
|
|
617
596
|
"",
|
|
@@ -679,8 +658,6 @@ describe("ngMessages", () => {
|
|
|
679
658
|
$rootScope.col = { unexpected: false };
|
|
680
659
|
});
|
|
681
660
|
|
|
682
|
-
$rootScope.$digest();
|
|
683
|
-
|
|
684
661
|
expect(element.text().trim()).toBe("");
|
|
685
662
|
expect(element[0].classList.contains("ng-active")).toBeFalse();
|
|
686
663
|
|
|
@@ -747,8 +724,6 @@ describe("ngMessages", () => {
|
|
|
747
724
|
)($rootScope);
|
|
748
725
|
$rootScope.default = true;
|
|
749
726
|
$rootScope.col = { unexpected: true };
|
|
750
|
-
$rootScope.$digest();
|
|
751
|
-
|
|
752
727
|
expect(element.text().trim()).toBe("Default message is set");
|
|
753
728
|
|
|
754
729
|
$rootScope.$apply("default = false");
|
|
@@ -853,7 +828,7 @@ describe("ngMessages", () => {
|
|
|
853
828
|
// $templateCache.set("abc.html", "<div></div>");
|
|
854
829
|
|
|
855
830
|
// element = $compile(html)($rootScope);
|
|
856
|
-
//
|
|
831
|
+
// ;
|
|
857
832
|
|
|
858
833
|
// const includeElement = element[0].querySelector(
|
|
859
834
|
// "[ng-messages-include], ng-messages-include",
|
|
@@ -918,7 +893,6 @@ describe("ngMessages", () => {
|
|
|
918
893
|
'<div ng-messages="data"><div ng-messages-include="/mock/hello"></div></div>',
|
|
919
894
|
)($rootScope);
|
|
920
895
|
|
|
921
|
-
$rootScope.$digest();
|
|
922
896
|
expect($templateCache.get("/mock/hello")).toBeDefined();
|
|
923
897
|
});
|
|
924
898
|
|
|
@@ -934,12 +908,9 @@ describe("ngMessages", () => {
|
|
|
934
908
|
failed: true,
|
|
935
909
|
};
|
|
936
910
|
|
|
937
|
-
$rootScope.$digest();
|
|
938
|
-
|
|
939
911
|
expect(messageChildren(element).length).toBe(1);
|
|
940
912
|
expect(trim(element.text())).toEqual("Your value is that of failure");
|
|
941
913
|
|
|
942
|
-
$rootScope.$digest();
|
|
943
914
|
setTimeout(() => {
|
|
944
915
|
expect(messageChildren(element).length).toBe(1);
|
|
945
916
|
expect(trim(element.text())).toEqual("You did not enter a value");
|
|
@@ -1034,8 +1005,6 @@ describe("ngMessages", () => {
|
|
|
1034
1005
|
$templateCache.set("messages1.html", "");
|
|
1035
1006
|
$templateCache.set("messages2.html", " ");
|
|
1036
1007
|
element = $compile(html)($rootScope);
|
|
1037
|
-
$rootScope.$digest();
|
|
1038
|
-
|
|
1039
1008
|
expect(element.text()).toBe("");
|
|
1040
1009
|
expect(element[0].childNodes.length).toBe(2);
|
|
1041
1010
|
});
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
} from "../../shared/constants";
|
|
11
11
|
import {
|
|
12
12
|
minErr,
|
|
13
|
-
forEach,
|
|
14
13
|
isNumber,
|
|
15
14
|
isNumberNaN,
|
|
16
15
|
isPromiseLike,
|
|
@@ -29,6 +28,7 @@ import {
|
|
|
29
28
|
import { defaultModelOptions } from "../model-options/model-options";
|
|
30
29
|
import { startingTag } from "../../shared/jqlite/jqlite";
|
|
31
30
|
import { ScopePhase } from "../../core/scope/scope";
|
|
31
|
+
import { isProxySymbol } from "../../core/model/model";
|
|
32
32
|
|
|
33
33
|
export const ngModelMinErr = minErr("ngModel");
|
|
34
34
|
|
|
@@ -77,8 +77,6 @@ export class NgModelController {
|
|
|
77
77
|
"$element",
|
|
78
78
|
"$parse",
|
|
79
79
|
"$animate",
|
|
80
|
-
"$timeout",
|
|
81
|
-
"$q",
|
|
82
80
|
"$interpolate",
|
|
83
81
|
];
|
|
84
82
|
|
|
@@ -89,8 +87,6 @@ export class NgModelController {
|
|
|
89
87
|
* @param {import('../../shared/jqlite/jqlite').JQLite} $element
|
|
90
88
|
* @param {import("../../core/parse/parse").ParseService} $parse
|
|
91
89
|
* @param {*} $animate
|
|
92
|
-
* @param {*} $timeout
|
|
93
|
-
* @param {import("../../core/q/q").QPromise<any>} $q
|
|
94
90
|
* @param {*} $interpolate
|
|
95
91
|
*/
|
|
96
92
|
constructor(
|
|
@@ -100,8 +96,6 @@ export class NgModelController {
|
|
|
100
96
|
$element,
|
|
101
97
|
$parse,
|
|
102
98
|
$animate,
|
|
103
|
-
$timeout,
|
|
104
|
-
$q,
|
|
105
99
|
$interpolate,
|
|
106
100
|
) {
|
|
107
101
|
/** @type {any} The actual value from the control's view */
|
|
@@ -160,16 +154,14 @@ export class NgModelController {
|
|
|
160
154
|
this.$$currentValidationRunId = 0;
|
|
161
155
|
|
|
162
156
|
/** @type {import('../../core/scope/scope.js').Scope} */
|
|
163
|
-
this.$$scope = $scope;
|
|
157
|
+
this.$$scope = $element.controller() ? $element.controller() : $scope; // attempt to bind to nearest controller if present
|
|
164
158
|
|
|
165
159
|
/** @type {import('../../core/scope/scope.js').Scope} */
|
|
166
160
|
this.$$rootScope = $scope.$root;
|
|
167
161
|
this.$$attr = $attr;
|
|
168
162
|
this.$$element = $element;
|
|
169
163
|
this.$$animate = $animate;
|
|
170
|
-
this.$$timeout = $timeout;
|
|
171
164
|
this.$$parse = $parse;
|
|
172
|
-
this.$q = $q;
|
|
173
165
|
this.$$exceptionHandler = $exceptionHandler;
|
|
174
166
|
|
|
175
167
|
this.$$hasNativeValidators = false;
|
|
@@ -525,7 +517,7 @@ export class NgModelController {
|
|
|
525
517
|
* </example>
|
|
526
518
|
*/
|
|
527
519
|
$rollbackViewValue() {
|
|
528
|
-
|
|
520
|
+
clearTimeout(this.$$pendingDebounce);
|
|
529
521
|
this.$viewValue = this.$$lastCommittedViewValue;
|
|
530
522
|
this.$render();
|
|
531
523
|
}
|
|
@@ -597,10 +589,10 @@ export class NgModelController {
|
|
|
597
589
|
setValidity(errorKey, null);
|
|
598
590
|
} else {
|
|
599
591
|
if (!that.$$parserValid) {
|
|
600
|
-
|
|
592
|
+
Object.keys(that.$validators).forEach((name) => {
|
|
601
593
|
setValidity(name, null);
|
|
602
594
|
});
|
|
603
|
-
|
|
595
|
+
Object.keys(that.$asyncValidators).forEach((name) => {
|
|
604
596
|
setValidity(name, null);
|
|
605
597
|
});
|
|
606
598
|
}
|
|
@@ -614,13 +606,13 @@ export class NgModelController {
|
|
|
614
606
|
|
|
615
607
|
function processSyncValidators() {
|
|
616
608
|
let syncValidatorsValid = true;
|
|
617
|
-
|
|
609
|
+
Object.entries(that.$validators).forEach(([name, validator]) => {
|
|
618
610
|
const result = Boolean(validator(modelValue, viewValue));
|
|
619
611
|
syncValidatorsValid = syncValidatorsValid && result;
|
|
620
612
|
setValidity(name, result);
|
|
621
613
|
});
|
|
622
614
|
if (!syncValidatorsValid) {
|
|
623
|
-
|
|
615
|
+
Object.keys(that.$asyncValidators).forEach((name) => {
|
|
624
616
|
setValidity(name, null);
|
|
625
617
|
});
|
|
626
618
|
return false;
|
|
@@ -631,7 +623,7 @@ export class NgModelController {
|
|
|
631
623
|
function processAsyncValidators() {
|
|
632
624
|
const validatorPromises = [];
|
|
633
625
|
let allValid = true;
|
|
634
|
-
|
|
626
|
+
Object.entries(that.$asyncValidators).forEach(([name, validator]) => {
|
|
635
627
|
const promise = validator(modelValue, viewValue);
|
|
636
628
|
if (!isPromiseLike(promise)) {
|
|
637
629
|
throw ngModelMinErr(
|
|
@@ -656,7 +648,7 @@ export class NgModelController {
|
|
|
656
648
|
if (!validatorPromises.length) {
|
|
657
649
|
validationDone(true);
|
|
658
650
|
} else {
|
|
659
|
-
|
|
651
|
+
Promise.all(validatorPromises).then(
|
|
660
652
|
() => {
|
|
661
653
|
validationDone(allValid);
|
|
662
654
|
},
|
|
@@ -686,7 +678,7 @@ export class NgModelController {
|
|
|
686
678
|
* usually handles calling this in response to input events.
|
|
687
679
|
*/
|
|
688
680
|
$commitViewValue() {
|
|
689
|
-
|
|
681
|
+
clearTimeout(this.$$pendingDebounce);
|
|
690
682
|
|
|
691
683
|
// If the view value has not changed then we should just exit, except in the case where there is
|
|
692
684
|
// a native validator on the element. In this case the validation state may have changed even though
|
|
@@ -737,9 +729,8 @@ export class NgModelController {
|
|
|
737
729
|
}
|
|
738
730
|
if (isNumberNaN(this.$modelValue)) {
|
|
739
731
|
// this.$modelValue has not been touched yet...
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
);
|
|
732
|
+
// @ts-ignore
|
|
733
|
+
this.$modelValue = this.$$ngModelGet(this.$$scope);
|
|
743
734
|
}
|
|
744
735
|
const prevModelValue = this.$modelValue;
|
|
745
736
|
const allowInvalid = this.$options.getOption("allowInvalid");
|
|
@@ -761,6 +752,9 @@ export class NgModelController {
|
|
|
761
752
|
// external validators (e.g. calculated on the server),
|
|
762
753
|
// that just call $setValidity and need the model value
|
|
763
754
|
// to calculate their validity.
|
|
755
|
+
if (that.$modelValue[isProxySymbol]) {
|
|
756
|
+
delete that.$modelValue;
|
|
757
|
+
}
|
|
764
758
|
that.$modelValue = allValid ? modelValue : undefined;
|
|
765
759
|
writeToModelIfNeeded();
|
|
766
760
|
}
|
|
@@ -768,7 +762,8 @@ export class NgModelController {
|
|
|
768
762
|
);
|
|
769
763
|
|
|
770
764
|
function writeToModelIfNeeded() {
|
|
771
|
-
|
|
765
|
+
// intentional loose equality
|
|
766
|
+
if (that.$modelValue != prevModelValue) {
|
|
772
767
|
that.$$writeModelToScope();
|
|
773
768
|
}
|
|
774
769
|
}
|
|
@@ -776,17 +771,13 @@ export class NgModelController {
|
|
|
776
771
|
|
|
777
772
|
$$writeModelToScope() {
|
|
778
773
|
this.$$ngModelSet(this.$$scope, this.$modelValue);
|
|
779
|
-
forEach(
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
}
|
|
787
|
-
},
|
|
788
|
-
this,
|
|
789
|
-
);
|
|
774
|
+
Object.values(this.$viewChangeListeners).forEach((listener) => {
|
|
775
|
+
try {
|
|
776
|
+
listener();
|
|
777
|
+
} catch (e) {
|
|
778
|
+
this.$$exceptionHandler(e);
|
|
779
|
+
}
|
|
780
|
+
}, this);
|
|
790
781
|
}
|
|
791
782
|
|
|
792
783
|
/**
|
|
@@ -859,13 +850,13 @@ export class NgModelController {
|
|
|
859
850
|
debounceDelay = debounceDelay["*"];
|
|
860
851
|
}
|
|
861
852
|
|
|
862
|
-
|
|
853
|
+
clearTimeout(this.$$pendingDebounce);
|
|
863
854
|
const that = this;
|
|
864
855
|
if (/** @type {number} */ (debounceDelay) > 0) {
|
|
865
856
|
// this fails if debounceDelay is an object
|
|
866
|
-
this.$$pendingDebounce =
|
|
857
|
+
this.$$pendingDebounce = setTimeout(() => {
|
|
867
858
|
that.$commitViewValue();
|
|
868
|
-
}, debounceDelay);
|
|
859
|
+
}, /** @type {number} */ (debounceDelay));
|
|
869
860
|
} else if (this.$$rootScope.$$phase !== ScopePhase.NONE) {
|
|
870
861
|
this.$commitViewValue();
|
|
871
862
|
} else {
|
|
@@ -1072,7 +1063,7 @@ function setupModelWatcher(ctrl) {
|
|
|
1072
1063
|
// -> scope value did not change since the last digest as
|
|
1073
1064
|
// ng-change executes in apply phase
|
|
1074
1065
|
// 4. view should be changed back to 'a'
|
|
1075
|
-
ctrl.$$scope.$watch((scope) => {
|
|
1066
|
+
ctrl.$$scope.$watch("scope", (scope) => {
|
|
1076
1067
|
const modelValue = ctrl.$$ngModelGet(scope);
|
|
1077
1068
|
|
|
1078
1069
|
// if scope model value and ngModel value are out of sync
|
|
@@ -1105,6 +1096,7 @@ export function ngModelDirective($rootScope) {
|
|
|
1105
1096
|
/** @param {import("../../shared/jqlite/jqlite.js").JQLite} element */
|
|
1106
1097
|
(element) => {
|
|
1107
1098
|
// Setup initial state of the control
|
|
1099
|
+
|
|
1108
1100
|
element[0].classList.add(PRISTINE_CLASS, UNTOUCHED_CLASS, VALID_CLASS);
|
|
1109
1101
|
|
|
1110
1102
|
return {
|
|
@@ -1143,11 +1135,7 @@ export function ngModelDirective($rootScope) {
|
|
|
1143
1135
|
element.on("blur", () => {
|
|
1144
1136
|
if (modelCtrl.$touched) return;
|
|
1145
1137
|
|
|
1146
|
-
|
|
1147
|
-
scope.$evalAsync(setTouched);
|
|
1148
|
-
} else {
|
|
1149
|
-
scope.$apply(setTouched);
|
|
1150
|
-
}
|
|
1138
|
+
scope.$apply(setTouched);
|
|
1151
1139
|
});
|
|
1152
1140
|
},
|
|
1153
1141
|
};
|
|
@@ -40,7 +40,6 @@ describe("ngModel", () => {
|
|
|
40
40
|
element = JQLite("<form><input></form>");
|
|
41
41
|
let $controller = injector.get("$controller");
|
|
42
42
|
scope = injector.get("$rootScope");
|
|
43
|
-
$q = injector.get("$q");
|
|
44
43
|
$rootScope = scope;
|
|
45
44
|
ctrl = $controller(NgModelController, {
|
|
46
45
|
$scope: scope,
|
|
@@ -371,8 +370,6 @@ describe("ngModel", () => {
|
|
|
371
370
|
};
|
|
372
371
|
|
|
373
372
|
ctrl.$setViewValue("123");
|
|
374
|
-
scope.$digest();
|
|
375
|
-
|
|
376
373
|
expect(element[0].classList.contains("ng-valid-parse")).toBeTrue();
|
|
377
374
|
expect(element[0].classList.contains("ng-invalid-parse")).toBeFalse();
|
|
378
375
|
expect(
|
|
@@ -381,8 +378,6 @@ describe("ngModel", () => {
|
|
|
381
378
|
|
|
382
379
|
parserIsFailing = true;
|
|
383
380
|
ctrl.$setViewValue("12345");
|
|
384
|
-
scope.$digest();
|
|
385
|
-
|
|
386
381
|
expect(element[0].classList.contains("ng-valid-parse")).toBeFalse();
|
|
387
382
|
expect(element[0].classList.contains("ng-invalid-parse")).toBeTrue();
|
|
388
383
|
expect(
|
|
@@ -422,8 +417,6 @@ describe("ngModel", () => {
|
|
|
422
417
|
expect(scope.value).toBeUndefined();
|
|
423
418
|
|
|
424
419
|
defer.resolve();
|
|
425
|
-
scope.$digest();
|
|
426
|
-
|
|
427
420
|
expect(ctrl.$modelValue).toBe("b");
|
|
428
421
|
expect(scope.value).toBe("b");
|
|
429
422
|
|
|
@@ -434,8 +427,6 @@ describe("ngModel", () => {
|
|
|
434
427
|
expect(scope.value).toBe("b");
|
|
435
428
|
|
|
436
429
|
defer.resolve();
|
|
437
|
-
scope.$digest();
|
|
438
|
-
|
|
439
430
|
expect(ctrl.$modelValue).toBe("c");
|
|
440
431
|
expect(scope.value).toBe("c");
|
|
441
432
|
});
|
|
@@ -519,11 +510,9 @@ describe("ngModel", () => {
|
|
|
519
510
|
)($rootScope);
|
|
520
511
|
|
|
521
512
|
$rootScope.val = 123;
|
|
522
|
-
$rootScope.$digest();
|
|
523
513
|
expect($rootScope.form.field.$viewValue).toBe("123");
|
|
524
514
|
|
|
525
515
|
$rootScope.val = null;
|
|
526
|
-
$rootScope.$digest();
|
|
527
516
|
expect($rootScope.form.field.$viewValue).toBe(null);
|
|
528
517
|
|
|
529
518
|
dealoc(form);
|
|
@@ -534,11 +523,9 @@ describe("ngModel", () => {
|
|
|
534
523
|
'<form name="form"><input type="text" name="field" ng-model="val" /></form>',
|
|
535
524
|
)($rootScope);
|
|
536
525
|
$rootScope.val = 123;
|
|
537
|
-
$rootScope.$digest();
|
|
538
526
|
expect($rootScope.form.field.$viewValue).toBe("123");
|
|
539
527
|
|
|
540
528
|
$rootScope.val = null;
|
|
541
|
-
$rootScope.$digest();
|
|
542
529
|
expect($rootScope.form.field.$viewValue).toBe(null);
|
|
543
530
|
|
|
544
531
|
dealoc(form);
|
|
@@ -549,11 +536,9 @@ describe("ngModel", () => {
|
|
|
549
536
|
'<form name="form"><input type="email" name="field" ng-model="val" /></form>',
|
|
550
537
|
)($rootScope);
|
|
551
538
|
$rootScope.val = 123;
|
|
552
|
-
$rootScope.$digest();
|
|
553
539
|
expect($rootScope.form.field.$viewValue).toBe("123");
|
|
554
540
|
|
|
555
541
|
$rootScope.val = null;
|
|
556
|
-
$rootScope.$digest();
|
|
557
542
|
expect($rootScope.form.field.$viewValue).toBe(null);
|
|
558
543
|
|
|
559
544
|
dealoc(form);
|
|
@@ -564,11 +549,9 @@ describe("ngModel", () => {
|
|
|
564
549
|
'<form name="form"><input type="url" name="field" ng-model="val" /></form>',
|
|
565
550
|
)($rootScope);
|
|
566
551
|
$rootScope.val = 123;
|
|
567
|
-
$rootScope.$digest();
|
|
568
552
|
expect($rootScope.form.field.$viewValue).toBe("123");
|
|
569
553
|
|
|
570
554
|
$rootScope.val = null;
|
|
571
|
-
$rootScope.$digest();
|
|
572
555
|
expect($rootScope.form.field.$viewValue).toBe(null);
|
|
573
556
|
|
|
574
557
|
dealoc(form);
|
|
@@ -633,7 +616,7 @@ describe("ngModel", () => {
|
|
|
633
616
|
// const input = $compile(
|
|
634
617
|
// '<input name="myControl" maxlength="1" ng-model="value" >',
|
|
635
618
|
// )($rootScope);
|
|
636
|
-
//
|
|
619
|
+
// ;
|
|
637
620
|
|
|
638
621
|
// spyOn($animate, "addClass");
|
|
639
622
|
// spyOn($animate, "removeClass");
|
|
@@ -646,7 +629,7 @@ describe("ngModel", () => {
|
|
|
646
629
|
// setModelValue(ctrl, 3);
|
|
647
630
|
// ctrl.$processModelValue();
|
|
648
631
|
|
|
649
|
-
// // $animate adds / removes classes in the
|
|
632
|
+
// // $animate adds / removes classes in the $postUpdate, which
|
|
650
633
|
// // we cannot trigger with $digest, because that would set the model from the scope,
|
|
651
634
|
// // so we simply check if the functions have been called
|
|
652
635
|
// expect($animate.removeClass.calls.mostRecent().args[0][0]).toBe(
|
|
@@ -973,8 +956,6 @@ describe("ngModel", () => {
|
|
|
973
956
|
expect(ctrl.$pending.promiseValidator).toBe(true);
|
|
974
957
|
|
|
975
958
|
defer.resolve();
|
|
976
|
-
scope.$digest();
|
|
977
|
-
|
|
978
959
|
expect(ctrl.$valid).toBe(true);
|
|
979
960
|
expect(ctrl.$invalid).toBe(false);
|
|
980
961
|
expect(ctrl.$pending).toBeUndefined();
|
|
@@ -982,8 +963,6 @@ describe("ngModel", () => {
|
|
|
982
963
|
scope.$apply('value = "123"');
|
|
983
964
|
|
|
984
965
|
defer.reject();
|
|
985
|
-
scope.$digest();
|
|
986
|
-
|
|
987
966
|
expect(ctrl.$valid).toBe(false);
|
|
988
967
|
expect(ctrl.$invalid).toBe(true);
|
|
989
968
|
expect(ctrl.$pending).toBeUndefined();
|
|
@@ -1067,10 +1046,7 @@ describe("ngModel", () => {
|
|
|
1067
1046
|
newDefer = defer;
|
|
1068
1047
|
|
|
1069
1048
|
newDefer.reject();
|
|
1070
|
-
scope.$digest();
|
|
1071
1049
|
oldDefer.resolve();
|
|
1072
|
-
scope.$digest();
|
|
1073
|
-
|
|
1074
1050
|
expect(ctrl.$valid).toBe(false);
|
|
1075
1051
|
expect(ctrl.$invalid).toBe(true);
|
|
1076
1052
|
expect(ctrl.$pending).toBeUndefined();
|
|
@@ -1103,7 +1079,6 @@ describe("ngModel", () => {
|
|
|
1103
1079
|
expect(isObject(ctrl.$pending)).toBe(true);
|
|
1104
1080
|
|
|
1105
1081
|
defers[1].resolve();
|
|
1106
|
-
scope.$digest();
|
|
1107
1082
|
expect(ctrl.$valid).toBe(true);
|
|
1108
1083
|
expect(ctrl.$invalid).toBe(false);
|
|
1109
1084
|
expect(isObject(ctrl.$pending)).toBe(false);
|
|
@@ -1131,8 +1106,6 @@ describe("ngModel", () => {
|
|
|
1131
1106
|
expect(isObject(ctrl.$pending)).toBe(false);
|
|
1132
1107
|
|
|
1133
1108
|
defer.resolve();
|
|
1134
|
-
scope.$digest();
|
|
1135
|
-
|
|
1136
1109
|
expect(ctrl.$valid).toBe(false);
|
|
1137
1110
|
expect(ctrl.$invalid).toBe(true);
|
|
1138
1111
|
expect(isObject(ctrl.$pending)).toBe(false);
|
|
@@ -1186,13 +1159,10 @@ describe("ngModel", () => {
|
|
|
1186
1159
|
const formCtrl = $rootScope.myForm;
|
|
1187
1160
|
const usernameCtrl = formCtrl.username;
|
|
1188
1161
|
|
|
1189
|
-
$rootScope.$digest();
|
|
1190
1162
|
expect(usernameCtrl.$invalid).toBe(true);
|
|
1191
1163
|
expect(formCtrl.$invalid).toBe(true);
|
|
1192
1164
|
|
|
1193
1165
|
usernameCtrl.$setViewValue("valid-username");
|
|
1194
|
-
$rootScope.$digest();
|
|
1195
|
-
|
|
1196
1166
|
expect(usernameCtrl.$invalid).toBe(false);
|
|
1197
1167
|
expect(formCtrl.$invalid).toBe(false);
|
|
1198
1168
|
delete Object.prototype.someThing;
|
|
@@ -1219,42 +1189,30 @@ describe("ngModel", () => {
|
|
|
1219
1189
|
return usernameDefer.promise;
|
|
1220
1190
|
};
|
|
1221
1191
|
|
|
1222
|
-
$rootScope.$digest();
|
|
1223
1192
|
expect(usernameCtrl.$invalid).toBe(true);
|
|
1224
1193
|
expect(formCtrl.$invalid).toBe(true);
|
|
1225
1194
|
|
|
1226
1195
|
usernameCtrl.$setViewValue("valid-username");
|
|
1227
|
-
$rootScope.$digest();
|
|
1228
|
-
|
|
1229
1196
|
expect(formCtrl.$pending.usernameAvailability).toBeTruthy();
|
|
1230
1197
|
expect(usernameCtrl.$invalid).toBeUndefined();
|
|
1231
1198
|
expect(formCtrl.$invalid).toBeUndefined();
|
|
1232
1199
|
|
|
1233
1200
|
usernameDefer.resolve();
|
|
1234
|
-
$rootScope.$digest();
|
|
1235
1201
|
expect(usernameCtrl.$invalid).toBe(false);
|
|
1236
1202
|
expect(formCtrl.$invalid).toBe(true);
|
|
1237
1203
|
|
|
1238
1204
|
ageCtrl.$setViewValue(22);
|
|
1239
|
-
$rootScope.$digest();
|
|
1240
|
-
|
|
1241
1205
|
expect(usernameCtrl.$invalid).toBe(false);
|
|
1242
1206
|
expect(ageCtrl.$invalid).toBe(false);
|
|
1243
1207
|
expect(formCtrl.$invalid).toBe(false);
|
|
1244
1208
|
|
|
1245
1209
|
usernameCtrl.$setViewValue("valid");
|
|
1246
|
-
$rootScope.$digest();
|
|
1247
|
-
|
|
1248
1210
|
expect(usernameCtrl.$invalid).toBe(true);
|
|
1249
1211
|
expect(ageCtrl.$invalid).toBe(false);
|
|
1250
1212
|
expect(formCtrl.$invalid).toBe(true);
|
|
1251
1213
|
|
|
1252
1214
|
usernameCtrl.$setViewValue("another-valid-username");
|
|
1253
|
-
$rootScope.$digest();
|
|
1254
|
-
|
|
1255
1215
|
usernameDefer.resolve();
|
|
1256
|
-
$rootScope.$digest();
|
|
1257
|
-
|
|
1258
1216
|
expect(usernameCtrl.$invalid).toBe(false);
|
|
1259
1217
|
expect(formCtrl.$invalid).toBe(false);
|
|
1260
1218
|
expect(formCtrl.$pending).toBeFalsy();
|
|
@@ -1471,11 +1429,9 @@ describe("ngModel", () => {
|
|
|
1471
1429
|
it("should set ng-empty or ng-not-empty when the view value changes", () => {
|
|
1472
1430
|
const element = $compile('<input ng-model="value" />')($rootScope);
|
|
1473
1431
|
|
|
1474
|
-
$rootScope.$digest();
|
|
1475
1432
|
expect(element.val()).toBe("");
|
|
1476
1433
|
|
|
1477
1434
|
$rootScope.value = "XXX";
|
|
1478
|
-
$rootScope.$digest();
|
|
1479
1435
|
expect(element.val()).toBe("XXX");
|
|
1480
1436
|
|
|
1481
1437
|
element.val("");
|
|
@@ -1492,7 +1448,6 @@ describe("ngModel", () => {
|
|
|
1492
1448
|
$rootScope,
|
|
1493
1449
|
);
|
|
1494
1450
|
|
|
1495
|
-
$rootScope.$digest();
|
|
1496
1451
|
expect(element[0].classList.contains("ng-valid")).toBeTrue();
|
|
1497
1452
|
expect(element[0].classList.contains("ng-pristine")).toBeTrue();
|
|
1498
1453
|
expect(element[0].classList.contains("ng-touched")).toBeFalse();
|
|
@@ -1530,8 +1485,6 @@ describe("ngModel", () => {
|
|
|
1530
1485
|
const element = $compile(
|
|
1531
1486
|
'<input type="email" ng-model="value" required />',
|
|
1532
1487
|
)($rootScope);
|
|
1533
|
-
$rootScope.$digest();
|
|
1534
|
-
|
|
1535
1488
|
expect(element[0].classList.contains("ng-invalid")).toBeTrue();
|
|
1536
1489
|
expect(element[0].classList.contains("ng-invalid-required")).toBeTrue();
|
|
1537
1490
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isDefined, trim } from "../../shared/utils";
|
|
2
2
|
|
|
3
3
|
const DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
|
|
4
4
|
|
|
@@ -70,33 +70,29 @@ class ModelOptions {
|
|
|
70
70
|
options = Object.assign({}, options);
|
|
71
71
|
|
|
72
72
|
// Inherit options from the parent if specified by the value `"$inherit"`
|
|
73
|
-
forEach(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (key === "updateOn") {
|
|
83
|
-
options.updateOnDefault = this.$$options.updateOnDefault;
|
|
84
|
-
}
|
|
73
|
+
Object.entries(options).forEach(([key, option]) => {
|
|
74
|
+
if (option === "$inherit") {
|
|
75
|
+
if (key === "*") {
|
|
76
|
+
inheritAll = true;
|
|
77
|
+
} else {
|
|
78
|
+
options[key] = this.$$options[key];
|
|
79
|
+
// `updateOn` is special so we must also inherit the `updateOnDefault` option
|
|
80
|
+
if (key === "updateOn") {
|
|
81
|
+
options.updateOnDefault = this.$$options.updateOnDefault;
|
|
85
82
|
}
|
|
86
|
-
} else if (key === "updateOn") {
|
|
87
|
-
// If the `updateOn` property contains the `default` event then we have to remove
|
|
88
|
-
// it from the event list and set the `updateOnDefault` flag.
|
|
89
|
-
options.updateOnDefault = false;
|
|
90
|
-
options[key] = trim(
|
|
91
|
-
option.replace(DEFAULT_REGEXP, () => {
|
|
92
|
-
options.updateOnDefault = true;
|
|
93
|
-
return " ";
|
|
94
|
-
}),
|
|
95
|
-
);
|
|
96
83
|
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
84
|
+
} else if (key === "updateOn") {
|
|
85
|
+
// If the `updateOn` property contains the `default` event then we have to remove
|
|
86
|
+
// it from the event list and set the `updateOnDefault` flag.
|
|
87
|
+
options.updateOnDefault = false;
|
|
88
|
+
options[key] = trim(
|
|
89
|
+
/** @type {string} */ (option).replace(DEFAULT_REGEXP, () => {
|
|
90
|
+
options.updateOnDefault = true;
|
|
91
|
+
return " ";
|
|
92
|
+
}),
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}, this);
|
|
100
96
|
|
|
101
97
|
if (inheritAll) {
|
|
102
98
|
// We have a property of the form: `"*": "$inherit"`
|