Quellcode durchsuchen

Adding metadata tree traversal code, for ease of use

Richard Knight vor 6 Jahren
Ursprung
Commit
c1a8e333b6
2 geänderte Dateien mit 37 neuen und 22 gelöschten Zeilen
  1. 2 1
      src/app/app.component.html
  2. 35 21
      src/app/dynaform/dynaform.component.ts

+ 2 - 1
src/app/app.component.html

@@ -10,7 +10,8 @@
 	<form [formGroup]="form">
 		<span formGroupName="dynaformtest">
 			<span formGroupName="d">
-				<app-dynaform formGroupName="g" [meta]="meta" [template]="tref"></app-dynaform>
+				<app-dynaform [formGroup]="form" [meta]="meta" [template]="tref"></app-dynaform>
+				<!-- <app-dynaform formGroupName="g" [meta]="meta" [template]="tref"></app-dynaform> -->
 			</span>
 		</span>
 	</form>

+ 35 - 21
src/app/dynaform/dynaform.component.ts

@@ -19,7 +19,7 @@ export class DynaformComponent implements OnInit {
 	 * USAGE:
 	 *
 	 * Supply component with either a FormGroup or the name of a FormGroup,
-	 * the group's meta data,
+	 * the forms full metadata tree,
 	 * and, optionally, a TemplateRef used as a field row template (overrides the default template)
 	 *
 	 * e.g.
@@ -58,6 +58,25 @@ export class DynaformComponent implements OnInit {
 	) {}
 
 	ngOnInit() {
+		
+		// Get the full path in the tree (used to match metadata)
+		let parents = [];
+		if (this.formGroup) {
+			// formGroup supplied directly, so reconstruct current FormGroup's full path
+			let fg = this.formGroup;
+			while (fg.parent) {
+				// Find the identity (i.e. object key) of the parent FormGroup that IS FormGroup 'fg'
+				const fgIdentity = Object.entries(fg.parent.controls).filter(([key, candidate]) => candidate === fg);
+				parents.push(fgIdentity[0][0]);
+				fg = <FormGroup>fg.parent;
+			}
+		} else if (this.formGroupName) {
+			// formGroupName supplied, so get the full path from the ControlContainer
+			parents = this.cc.path.reverse();
+		}
+		const path = parents;
+		
+		// Get the formGroup from the formGroupName if necessary
 		if (!this.formGroup && this.formGroupName) {
 			this.formGroup = <FormGroup>this.cc.control; // Get theFormGroup from the ControlContainer
 		}
@@ -66,31 +85,26 @@ export class DynaformComponent implements OnInit {
 		}
 		this.controlNames = Object.keys(this.formGroup.controls);
 
-		// If we're given a formGroupName and the form's full metadata tree
+		// If we're given a formGroupName or nested FormFroup, and the form's full (or partial but fuller) metadata tree,
 		// drill down to find the corresponding FormGroup's metadata
-		if (this.formGroupName) {
-			const path = this.cc.path.reverse();
-			const firstControlName = this.controlNames[0];
-			while (path.length && !this.formMetaData[firstControlName]) {
-				const branch = path.pop();
-				this.formMetaData = this.formMetaData[branch].meta;
-			}
+		const metaDataKeysExpected = this.controlNames.join(',');
+		while (path.length && metaDataKeysExpected !== Object.keys(this.formMetaData).join(',')) {
+			const branch = path.pop();
+			this.formMetaData = this.formMetaData[branch].meta;
+		}
+		
+		// Check we've got a match
+		const metaDataKeys = Object.keys(this.formMetaData).join(',');
+		if (metaDataKeys !== metaDataKeysExpected) {
+			throw new Error(`
+				Dynaform can't match FormGroup's controls with metadata
+				Expected ${metaDataKeysExpected}
+				Got ${metaDataKeys}`
+			);
 		}
 	}
 
 	getTemplateContext(controlName: string): DynarowContext {
-		/*
-		console.log('-------------------------------------');
-		console.log('getTemplateContext', controlName);
-		console.log(this.formGroup);
-		console.log(this.formMetaData);
-		const context = {
-			control: this.formGroup.get(controlName),
-			meta: this.formMetaData[controlName]
-		};
-		console.log(context);
-		return context;
-		*/
 		return {
 			control: this.formGroup.get(controlName),
 			meta: this.formMetaData[controlName]