@angular-wave/angular.ts 0.4.4 → 0.4.6

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