ソースを参照

Changing to OnPush change detection for greater efficiency

Richard Knight 5 年 前
コミット
ff113f0631
共有24 個のファイルを変更した7491 個の追加4720 個の削除を含む
  1. 2 2
      ng-dynaform.code-workspace
  2. 7288 4626
      package-lock.json
  3. 32 32
      package.json
  4. 48 5
      src/app/dynaform/components/_abstract/native-input.component.ts
  5. 6 3
      src/app/dynaform/components/clarity/checkbox/clr-checkbox.component.ts
  6. 6 3
      src/app/dynaform/components/clarity/datepicker/datepicker.component.ts
  7. 7 3
      src/app/dynaform/components/clarity/display/clr-display.component.ts
  8. 6 3
      src/app/dynaform/components/clarity/password/clr-password.component.ts
  9. 6 3
      src/app/dynaform/components/clarity/radio/clr-radio.component.ts
  10. 38 5
      src/app/dynaform/components/clarity/select/clr-select.component.ts
  11. 6 3
      src/app/dynaform/components/clarity/text/clr-text.component.ts
  12. 6 3
      src/app/dynaform/components/clarity/textarea/clr-textarea.component.ts
  13. 2 2
      src/app/dynaform/components/custom/checkbutton/checkbutton.component.ts
  14. 6 3
      src/app/dynaform/components/custom/datetime/datetime.component.ts
  15. 6 3
      src/app/dynaform/components/custom/dropdown-modified-input/dropdown-modified-input.component.ts
  16. 6 3
      src/app/dynaform/components/custom/multiline/multiline.component.ts
  17. 3 3
      src/app/dynaform/directives/dynafield.directive.ts
  18. 1 1
      src/app/dynaform/dynaform.component.ts
  19. 4 4
      src/app/dynaform/models/field.model.ts
  20. 6 5
      src/app/dynaform/services/_formdata-utils.ts
  21. 1 1
      src/app/dynaform/utils.ts
  22. 1 1
      src/polyfills.ts
  23. 2 2
      src/styles.scss
  24. 2 1
      tsconfig.json

+ 2 - 2
ng-dynaform.code-workspace

@@ -4,10 +4,10 @@
 			"path": "."
 		},
 		{
-			"path": "src\\app\\dynaform"
+			"path": "src/app"
 		},
 		{
-			"path": "src/app"
+			"path": "src/app/dynaform"
 		}
 	],
 	"settings": {}

ファイルの差分が大きいため隠しています
+ 7288 - 4626
package-lock.json


+ 32 - 32
package.json

@@ -12,47 +12,47 @@
   },
   "private": true,
   "dependencies": {
-    "@angular/animations": "^8.0.1",
-    "@angular/common": "^8.0.1",
-    "@angular/compiler": "^8.0.1",
-    "@angular/core": "^8.0.1",
-    "@angular/forms": "^8.0.1",
-    "@angular/platform-browser": "^8.0.1",
-    "@angular/platform-browser-dynamic": "^8.0.1",
-    "@angular/router": "^8.0.1",
-    "@clr/angular": "^1.1.4",
-    "@clr/icons": "^1.1.4",
-    "@clr/ui": "^1.1.4",
-    "@webcomponents/custom-elements": "^1.2.4",
+    "@angular/animations": "^8.2.14",
+    "@angular/common": "^8.2.14",
+    "@angular/compiler": "^8.2.14",
+    "@angular/core": "^8.2.14",
+    "@angular/forms": "^8.2.14",
+    "@angular/platform-browser": "^8.2.14",
+    "@angular/platform-browser-dynamic": "^8.2.14",
+    "@angular/router": "^8.2.14",
+    "@clr/angular": "^2.3.2",
+    "@clr/icons": "^2.3.2",
+    "@clr/ui": "^2.3.2",
+    "@webcomponents/custom-elements": "^1.3.1",
     "angular-super-validator": "^2.0.0",
     "json-formatter-js": "^2.2.1",
-    "lodash": "^4.17.11",
+    "lodash": "^4.17.15",
     "ramda": "^0.26.1",
-    "rxjs": "^6.5.2",
-    "zone.js": "~0.9.1"
+    "rxjs": "^6.5.3",
+    "zone.js": "~0.10.2"
   },
   "devDependencies": {
-    "@angular-devkit/build-angular": "~0.800.0",
-    "@angular/cli": "^8.0.3",
-    "@angular/compiler-cli": "^8.0.1",
-    "@angular/language-service": "^8.0.1",
-    "@types/jasmine": "^3.3.13",
-    "@types/jasminewd2": "~2.0.6",
-    "@types/lodash": "^4.14.134",
-    "@types/node": "^12.0.8",
-    "codelyzer": "^5.1.0",
-    "jasmine-core": "~3.4.0",
+    "@angular-devkit/build-angular": "~0.803.19",
+    "@angular/cli": "^8.3.19",
+    "@angular/compiler-cli": "^8.2.14",
+    "@angular/language-service": "^8.2.14",
+    "@types/jasmine": "^3.5.0",
+    "@types/jasminewd2": "~2.0.8",
+    "@types/lodash": "^4.14.149",
+    "@types/node": "^12.12.14",
+    "codelyzer": "^5.2.0",
+    "jasmine-core": "~3.5.0",
     "jasmine-spec-reporter": "~4.2.1",
-    "karma": "^4.1.0",
-    "karma-chrome-launcher": "~2.2.0",
-    "karma-coverage-istanbul-reporter": "^2.0.5",
+    "karma": "^4.4.1",
+    "karma-chrome-launcher": "~3.1.0",
+    "karma-coverage-istanbul-reporter": "^2.1.1",
     "karma-jasmine": "~2.0.1",
     "karma-jasmine-html-reporter": "^1.4.2",
-    "node-sass": "^4.12.0",
+    "node-sass": "^4.13.0",
     "protractor": "^5.4.2",
     "rxjs-tslint": "^0.1.7",
-    "ts-node": "^8.3.0",
-    "tslint": "~5.17.0",
-    "typescript": "3.4.5"
+    "ts-node": "^8.5.2",
+    "tslint": "~5.20.1",
+    "typescript": "3.5.3"
   }
 }

+ 48 - 5
src/app/dynaform/components/_abstract/native-input.component.ts

@@ -1,8 +1,9 @@
-import { Input, Output, EventEmitter } from '@angular/core';
+import { OnInit, Input, Output, ChangeDetectorRef, EventEmitter } from '@angular/core';
 import { FormControl } from '@angular/forms';
 import { FriendlyValidationErrorsService } from './../../services/friendly-validation-errors.service';
+// import { Subject } from 'rxjs';
 
-export abstract class NativeInputComponent {
+export abstract class NativeInputComponent implements OnInit {
 
 	@Input()
 	control: FormControl;
@@ -20,15 +21,44 @@ export abstract class NativeInputComponent {
 	exposeMetaInTemplate: string[] = [];
 	_meta: StringMap<any>;
 
-	constructor(protected valErrsService: FriendlyValidationErrorsService) {}
+	pendingValidation: boolean;
+
+	// firstFailureMsg: Subject<string> = new Subject();
+
+	constructor(
+		protected valErrsService: FriendlyValidationErrorsService,
+		protected _cdr: ChangeDetectorRef
+	) {}
+
+	ngOnInit() {
+		// this.control is not an instance of FormControl when it's a Checkbutton in a Checkbutton group (but is when it's a solo Checkbutton) - BUT WHY? WHY!!!
+		// Hence the 'if' statement
+		if (this.control instanceof FormControl) {
+			this.control.valueChanges.subscribe(this.markForCheck.bind(this));
+			this.control.statusChanges.subscribe(status => {
+				if (status === 'PENDING') {
+					this.pendingValidation = true;
+				} else if (this.pendingValidation) {
+					this.pendingValidation = false;
+					this.markForCheck();
+				}
+			});
+		}
+	}
 
 	exposeForTemplate() {
 		// Move meta variables up a level, for direct access in templates
 		this.exposeMetaInTemplate.map(p => this[p] = this._meta[p] !== undefined ? this._meta[p] : this[p]);
 	}
 
+	markForCheck() {
+		if (this._cdr) {
+			this._cdr.markForCheck();
+		}
+	}
+
 	handle(fnId: string, val: any): void {
-		this.call.emit(fnId); // Add value
+		this.call.emit(fnId); // Add control's current value
 	}
 
 	handleChange(): void {
@@ -42,11 +72,24 @@ export abstract class NativeInputComponent {
 	}
 
 	getFirstFailureMsg(): string {
-		if (!this.control.errors) {
+		if (!this.control.errors || this.control.errors === {}) {
 			return '';
 		}
 		const key = Object.keys(this.control.errors)[0];
 		return this._meta.valFailureMsgs[key] || this.valErrsService.getFriendly(key, this.control.errors[key]);
 	}
 
+	/*
+	getFirstFailureMsg(): void {
+		if (!this.control.errors || this.control.errors === {}) {
+			this.firstFailureMsg.next('');
+		}
+		console.log(this.control.errors);
+		const key = Object.keys(this.control.errors)[0];
+		const err = this._meta.valFailureMsgs[key] || this.valErrsService.getFriendly(key, this.control.errors[key]);
+		this.firstFailureMsg.next(err);
+	}
+	*/
+
+
 }

+ 6 - 3
src/app/dynaform/components/clarity/checkbox/clr-checkbox.component.ts

@@ -1,4 +1,4 @@
-import { Component } from '@angular/core';
+import { Component, ChangeDetectorRef } from '@angular/core';
 import { NativeInputComponent } from '../../_abstract/native-input.component';
 import { FriendlyValidationErrorsService } from './../../../services/friendly-validation-errors.service';
 
@@ -21,8 +21,11 @@ export class ClrCheckboxComponent extends NativeInputComponent {
 		this.handleChange();
 	}
 
-	constructor(protected valErrsService: FriendlyValidationErrorsService) {
-		super(valErrsService);
+	constructor(
+		protected valErrsService: FriendlyValidationErrorsService,
+		protected _cdr: ChangeDetectorRef
+	) {
+		super(valErrsService, _cdr);
 	}
 
 }

+ 6 - 3
src/app/dynaform/components/clarity/datepicker/datepicker.component.ts

@@ -1,4 +1,4 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, ChangeDetectorRef, OnInit } from '@angular/core';
 import { NativeInputComponent } from '../../_abstract/native-input.component';
 import { FriendlyValidationErrorsService } from './../../../services/friendly-validation-errors.service';
 
@@ -17,8 +17,11 @@ export class ClrDatepickerComponent extends NativeInputComponent implements OnIn
 
 	readonly componentName = 'DatepickerComponent'; // For AOT compatibility, as class names don't survive minification
 
-	constructor(protected valErrsService: FriendlyValidationErrorsService) {
-		super(valErrsService);
+	constructor(
+		protected valErrsService: FriendlyValidationErrorsService,
+		protected _cdr: ChangeDetectorRef
+	) {
+		super(valErrsService, _cdr);
 	}
 
 	ngOnInit() {

+ 7 - 3
src/app/dynaform/components/clarity/display/clr-display.component.ts

@@ -1,5 +1,6 @@
-import { Component, OnChanges } from '@angular/core';
+import { Component, ChangeDetectorRef, OnChanges } from '@angular/core';
 import { NativeInputComponent } from '../../_abstract/native-input.component';
+import { FriendlyValidationErrorsService } from './../../../services/friendly-validation-errors.service';
 
 @Component({
 	selector: 'app-clr-display',
@@ -15,8 +16,11 @@ export class ClrDisplayComponent extends NativeInputComponent implements OnChang
 
 	readonly componentName = 'DisplayComponent'; // For AOT compatibility, as class names don't survive minification
 
-	constructor() {
-		super(null);
+	constructor(
+		protected valErrsService: FriendlyValidationErrorsService,
+		protected _cdr: ChangeDetectorRef
+	) {
+		super(valErrsService, _cdr);
 	}
 
 	ngOnChanges() {

+ 6 - 3
src/app/dynaform/components/clarity/password/clr-password.component.ts

@@ -1,4 +1,4 @@
-import { Component } from '@angular/core';
+import { Component, ChangeDetectorRef } from '@angular/core';
 import { NativeInputComponent } from '../../_abstract/native-input.component';
 import { FriendlyValidationErrorsService } from './../../../services/friendly-validation-errors.service';
 
@@ -16,8 +16,11 @@ export class ClrPasswordComponent extends NativeInputComponent {
 
 	readonly componentName = 'PasswordComponent'; // For AOT compatibility, as class names don't survive minification
 
-	constructor(protected valErrsService: FriendlyValidationErrorsService) {
-		super(valErrsService);
+	constructor(
+		protected valErrsService: FriendlyValidationErrorsService,
+		protected _cdr: ChangeDetectorRef
+	) {
+		super(valErrsService, _cdr);
 	}
 
 }

+ 6 - 3
src/app/dynaform/components/clarity/radio/clr-radio.component.ts

@@ -1,4 +1,4 @@
-import { Component } from '@angular/core';
+import { Component, ChangeDetectorRef } from '@angular/core';
 import { NativeInputComponent } from '../../_abstract/native-input.component';
 import { IOption } from '../../../models/field.model';
 import { FriendlyValidationErrorsService } from './../../../services/friendly-validation-errors.service';
@@ -21,8 +21,11 @@ export class ClrRadioComponent extends NativeInputComponent {
 
 	readonly componentName = 'RadioComponent'; // For AOT compatibility, as class names don't survive minification
 
-	constructor(protected valErrsService: FriendlyValidationErrorsService) {
-		super(valErrsService);
+	constructor(
+		protected valErrsService: FriendlyValidationErrorsService,
+		protected _cdr: ChangeDetectorRef
+	) {
+		super(valErrsService, _cdr);
 	}
 
 }

+ 38 - 5
src/app/dynaform/components/clarity/select/clr-select.component.ts

@@ -1,4 +1,4 @@
-import { Component, Injector } from '@angular/core';
+import { Component, Input, ChangeDetectorRef } from '@angular/core';
 import { NativeInputComponent } from '../../_abstract/native-input.component';
 import { Router, ActivatedRoute } from '@angular/router';
 import { IOption, ILink } from '../../../models/field.model';
@@ -12,6 +12,32 @@ import { FriendlyValidationErrorsService } from './../../../services/friendly-va
 })
 export class ClrSelectComponent extends NativeInputComponent {
 
+	@Input()
+	set meta(meta: StringMap<any>) {
+		// If there's only one choice set the FormControls value (otherwise the field shows the choice, but the FormControl's value remains unchanged,
+		// maybe due to no updateOnBlur interaction?)
+		// If there are multiple choices that don't include the current value prepend a blank option
+		if (meta.options.length === 1) {
+			this.control.setValue(meta.options[0].value);
+			this.control.markAsDirty();
+			this.control.markAsTouched();
+			this.control.updateValueAndValidity();
+		} else {
+			const cval = this.control.value; // current value
+			// tslint:disable-next-line: triple-equals
+			const newOptsIncludeCVal = meta.options.find((opt: IOption) => opt.value == cval); // Deliberate type coercion with '=='
+			if (!newOptsIncludeCVal) {
+				meta.options.unshift({ label: '', value: ''});
+				this.control.setValue('');
+				this.control.markAsPristine();
+				this.control.markAsUntouched();
+				this.control.updateValueAndValidity();
+			}
+		}
+		this._meta = meta;
+		this.exposeForTemplate();
+	}
+
 	exposeMetaInTemplate: string[] = ['label', 'options', 'link'];
 
 	label: string;
@@ -20,14 +46,21 @@ export class ClrSelectComponent extends NativeInputComponent {
 
 	readonly componentName = 'SelectComponent'; // For AOT compatibility, as class names don't survive minification
 
-	// TODO: Emit event to parant dynaform to do routing - then all form components will be able to use it
-	// It's cleaner
+	// TODO: Emit event to parant dynaform to do routing - then all form components will be able to use it. Much cleaner!
 	constructor(
 		private router: Router,
 		private route: ActivatedRoute,
-		protected valErrsService: FriendlyValidationErrorsService
+		protected valErrsService: FriendlyValidationErrorsService,
+		protected _cdr: ChangeDetectorRef
 	) {
-		super(valErrsService);
+		super(valErrsService, _cdr);
+	}
+
+	handleChange() {
+		this.control.markAsDirty();
+		this.control.markAsTouched();
+		this.control.updateValueAndValidity();
+		super.handleChange();
 	}
 
 	navigate(field: HTMLSelectElement) {

+ 6 - 3
src/app/dynaform/components/clarity/text/clr-text.component.ts

@@ -1,4 +1,4 @@
-import { Component } from '@angular/core';
+import { Component, ChangeDetectorRef } from '@angular/core';
 import { NativeInputComponent } from '../../_abstract/native-input.component';
 import { FriendlyValidationErrorsService } from './../../../services/friendly-validation-errors.service';
 
@@ -17,8 +17,11 @@ export class ClrTextComponent extends NativeInputComponent {
 
 	readonly componentName = 'TextComponent'; // For AOT compatibility, as class names don't survive minification
 
-	constructor(protected valErrsService: FriendlyValidationErrorsService) {
-		super(valErrsService);
+	constructor(
+		protected valErrsService: FriendlyValidationErrorsService,
+		protected _cdr: ChangeDetectorRef
+	) {
+		super(valErrsService, _cdr);
 	}
 
 }

+ 6 - 3
src/app/dynaform/components/clarity/textarea/clr-textarea.component.ts

@@ -1,4 +1,4 @@
-import { Component } from '@angular/core';
+import { Component, ChangeDetectorRef } from '@angular/core';
 import { NativeInputComponent } from '../../_abstract/native-input.component';
 import { FriendlyValidationErrorsService } from './../../../services/friendly-validation-errors.service';
 
@@ -17,8 +17,11 @@ export class ClrTextareaComponent extends NativeInputComponent {
 
 	readonly componentName = 'TextareaComponent'; // For AOT compatibility, as class names don't survive minification
 
-	constructor(protected valErrsService: FriendlyValidationErrorsService) {
-		super(valErrsService);
+	constructor(
+		protected valErrsService: FriendlyValidationErrorsService,
+		protected _cdr: ChangeDetectorRef
+	) {
+		super(valErrsService, _cdr);
 	}
 
 }

+ 2 - 2
src/app/dynaform/components/custom/checkbutton/checkbutton.component.ts

@@ -31,9 +31,9 @@ export class CheckbuttonComponent extends CustomInputComponent implements OnChan
 
 	constructor(
 		protected valErrsService: FriendlyValidationErrorsService,
-		private _cdr: ChangeDetectorRef
+		protected _cdr: ChangeDetectorRef
 	) {
-		super(valErrsService);
+		super(valErrsService, _cdr);
 	}
 
 	ngOnChanges() {

+ 6 - 3
src/app/dynaform/components/custom/datetime/datetime.component.ts

@@ -1,4 +1,4 @@
-import { Component, OnInit, forwardRef } from '@angular/core';
+import { Component, OnInit, forwardRef, ChangeDetectorRef } from '@angular/core';
 import { NG_VALUE_ACCESSOR } from '@angular/forms';
 import { CustomInputComponent } from './../../_abstract/custom-input.component';
 import { FriendlyValidationErrorsService } from './../../../services/friendly-validation-errors.service';
@@ -32,8 +32,11 @@ export class DatetimeComponent extends CustomInputComponent implements OnInit {
 
 	readonly componentName = 'DatetimeComponent'; // For AOT compatibility, as class names don't survive minification
 
-	constructor(protected valErrsService: FriendlyValidationErrorsService) {
-		super(valErrsService);
+	constructor(
+		protected valErrsService: FriendlyValidationErrorsService,
+		protected _cdr: ChangeDetectorRef
+	) {
+		super(valErrsService, _cdr);
 	}
 
 	ngOnInit() {

+ 6 - 3
src/app/dynaform/components/custom/dropdown-modified-input/dropdown-modified-input.component.ts

@@ -1,4 +1,4 @@
-import { Component, OnInit, forwardRef } from '@angular/core';
+import { Component, OnInit, forwardRef, ChangeDetectorRef } from '@angular/core';
 import { NG_VALUE_ACCESSOR } from '@angular/forms';
 import { CustomInputComponent } from './../../_abstract/custom-input.component';
 import { ValueTransformer }	from './../../../interfaces';
@@ -34,8 +34,11 @@ export class DropdownModifiedInputComponent extends CustomInputComponent impleme
 
 	readonly componentName = 'DropdownModifiedInputComponent'; // For AOT compatibility, as class names don't survive minification
 
-	constructor(protected valErrsService: FriendlyValidationErrorsService) {
-		super(valErrsService);
+	constructor(
+		protected valErrsService: FriendlyValidationErrorsService,
+		protected _cdr: ChangeDetectorRef
+	) {
+		super(valErrsService, _cdr);
 	}
 
 	ngOnInit() {

+ 6 - 3
src/app/dynaform/components/custom/multiline/multiline.component.ts

@@ -1,4 +1,4 @@
-import { Component, forwardRef } from '@angular/core';
+import { Component, forwardRef, ChangeDetectorRef } from '@angular/core';
 import { NG_VALUE_ACCESSOR } from '@angular/forms';
 import { CustomInputComponent } from './../../_abstract/custom-input.component';
 import { FriendlyValidationErrorsService } from './../../../services/friendly-validation-errors.service';
@@ -25,8 +25,11 @@ export class MultilineComponent extends CustomInputComponent {
 
 	readonly componentName = 'MultilineComponent'; // For AOT compatibility, as class names don't survive minification
 
-	constructor(protected valErrsService: FriendlyValidationErrorsService) {
-		super(valErrsService);
+	constructor(
+		protected valErrsService: FriendlyValidationErrorsService,
+		protected _cdr: ChangeDetectorRef
+	) {
+		super(valErrsService, _cdr);
 	}
 
 	writeValue(value: any): void {

+ 3 - 3
src/app/dynaform/directives/dynafield.directive.ts

@@ -86,7 +86,7 @@ export class DynafieldDirective extends NgControl implements OnInit, OnChanges,
 			const validComponentTypes = Object.keys(formFieldComponents).join(', ');
 			throw new Error(
 				`Dynaform Dynafield Error: Invalid field type: ${type}.
-			 	 Supported types: ${validComponentTypes}`
+				 Supported types: ${validComponentTypes}`
 			);
 		}
 		try {
@@ -206,8 +206,8 @@ export class DynafieldDirective extends NgControl implements OnInit, OnChanges,
 		const classList = this.component.location.nativeElement.classList as DOMTokenList;
 		const componentTypeClass = type.toLowerCase().replace('component', '');
 		classList.add(componentTypeClass);
-		if (cssClass) {
-			const classesToAdd = Array.isArray(cssClass) ? cssClass : [...cssClass.split(/\s+/)];
+		if (typeof cssClass === 'string' || Array.isArray(cssClass)) {
+			const classesToAdd = (Array.isArray(cssClass) ? cssClass : [...cssClass.split(/\s+/)]).filter(Boolean);
 			const classesToRemove = [];
 			const dontRemove = [ ...classesToAdd, componentTypeClass, 'ng-star-inserted' ];
 			classList.forEach(c => classesToRemove.push(dontRemove.indexOf(c) < 0 ? c : null));

+ 1 - 1
src/app/dynaform/dynaform.component.ts

@@ -13,7 +13,7 @@ export interface DynarowContext {
 	selector: 'app-dynaform',
 	templateUrl: './dynaform.component.html',
 	styleUrls: ['./dynaform.component.scss'],
-	changeDetection: ChangeDetectionStrategy.Default // or ChangeDetectionStrategy.OnPush - should be more efficient. Experiment later.
+	changeDetection: ChangeDetectionStrategy.OnPush // or ChangeDetectionStrategy.OnPush - should be more efficient. Experiment later.
 })
 export class DynaformComponent implements OnInit, OnChanges {
 

+ 4 - 4
src/app/dynaform/models/field.model.ts

@@ -27,7 +27,6 @@ interface ISimpleFieldMetaData {
 	validators?: ValidatorFn[];				// Array of validator functions - following Angular FormControl API
 	asyncValidators?: AsyncValidatorFn[];	// Array of async validator functions - following Angular FormControl API
 	valFailureMsgs?: StringMap<any>;		// Validation failure messages - display appropriate message if validation fails
-	// onChange?: (val) => {};				// Function to call when field's value changes
 }
 
 interface IOption {
@@ -36,8 +35,8 @@ interface IOption {
 }
 
 interface IOptionsFieldMetaData extends ISimpleFieldMetaData {
-	options;									// Array of Options - for select, radio-button-group and other 'multiple-choice' types
-	horizontal?: boolean;						// Whether to arrang radio buttons or checkboxes horizontally (default false)
+	options: string[] | IOption[] | (() => IOption[]);	// Array of Options - for select, radio-button-group and other 'multiple-choice' types
+	horizontal?: boolean;								// Whether to arrange radio buttons or checkboxes horizontally (default false)
 }
 
 // For components that include links to other pages
@@ -129,6 +128,7 @@ class Option implements IOption {
 				this.value = opt.value;
 			}
 		} else {
+			// Simple string
 			this.label = opt;
 			this.value = opt;
 		}
@@ -136,7 +136,7 @@ class Option implements IOption {
 }
 
 abstract class OptionsField extends SimpleField {
-	options: Option[] = [];
+	options: Option[] | (() => Option[]) = [];
 	constructor(meta: IOptionsFieldMetaData, context?: any) {
 		super(meta);
 		let options;

+ 6 - 5
src/app/dynaform/services/_formdata-utils.ts

@@ -82,7 +82,7 @@ const combineExtraMeta = (metaG, extraMeta, createFromExtra = false, containerSe
 				const baseObjWithAllKeys = getRCBaseObjectWithAllKeys(metaFoG, val, createFromExtra);
 				metaFoG.meta = generateRepeatedGroup(metaFoG, val, baseObjWithAllKeys);
 				const extra = {
-					...omit(['meta', 'seed'], val),
+					...omit(['meta', 'seed'], val as StringMap<any>),
 					meta: metaFoG.meta.map(
 						rgMem => combineExtraMeta(
 							rgMem.meta,
@@ -564,6 +564,7 @@ const generateNewModel = (originalModel, updates) => {
 	return updateObject(originalModel, updates);
 };
 
+// NOT FINISHED!!!
 const updateMeta = (newMeta: StringMap<any>, path: string, meta: StringMap<any>): StringMap<any> => {
 	// TODO: Finish this later
 	if (path === '/') {
@@ -573,18 +574,18 @@ const updateMeta = (newMeta: StringMap<any>, path: string, meta: StringMap<any>)
 	// Drill down and update the branch specified by 'path' - all but final segment indicates a container
 	// What about array types? Think about this later!
 	// What about group components. Think about this later.
-	// What about bad paths. Thinkl about this later.
+	// What about bad paths. Think about this later.
 	console.log(path);
 	const segments = path.split('.');
 	console.log(segments);
 	let branchMeta = meta;
-	while(isContainer(branchMeta)) {
+	while (isContainer(branchMeta)) {
 		const s = segments.shift();
 		console.log(s, branchMeta[s].meta);
 		// TODO: add array check
 		branchMeta = branchMeta[s].meta;
 	}
-	while(segments.length > 1) {
+	while (segments.length > 1) {
 		const s = segments.shift();
 		console.log(s, branchMeta[s]);
 		// TODO: add array check
@@ -598,7 +599,7 @@ const updateMeta = (newMeta: StringMap<any>, path: string, meta: StringMap<any>)
 	branchMeta = updatedMeta;
 	console.log(branchMeta);
 	return meta;
-}
+};
 
 const updateObject = (obj, updates, createAdditionalKeys = false) => {
 	// THIS DOES NOT MUTATE obj, instead returning a new object

+ 1 - 1
src/app/dynaform/utils.ts

@@ -75,7 +75,7 @@ const makeAsyncTest = (boundFnName: string, failureFlag: string): (fc: FormContr
 		return merge(
 			of(fc).pipe(
 				filter(_fc => _fc.value !== initialValue),
-				switchMap(_fc => this[boundFnName](_fc.value)),
+				switchMap(_fc => this[boundFnName](_fc.value, _fc.root)),
 				map(res => res ? {} : { [failureFlag]: true } )
 			),
 			of(fc).pipe(

+ 1 - 1
src/polyfills.ts

@@ -43,7 +43,7 @@
 
 /** Evergreen browsers require these. **/
 // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
-import 'core-js/es7/reflect';
+// import 'core-js/es7/reflect';
 
 
 /**

+ 2 - 2
src/styles.scss

@@ -12,8 +12,8 @@ $col-charcoal: #444;
 
 // --------------------------------------------------------------------------------------------------------------------
 
-// Clarity Dependency SCSS
-@import "../node_modules/@clr/ui/src/utils/dependencies.clarity"; // Includes light theme
+// Clarity Dependency SCSS - No loner needed as of Clarity 2?
+// @import "../node_modules/@clr/ui/src/utils/dependencies.clarity"; // Includes light theme
 
 // PUT (or import) CLARITY VARIABLE OVERRIDES HERE
 $clr-forms-select-hover-background: $col-blue-lightest;

+ 2 - 1
tsconfig.json

@@ -30,4 +30,5 @@
     },
     "module": "esnext"
   }
-}
+}
+