Bläddra i källkod

Adding support for FormArray types

Richard Knight 6 år sedan
förälder
incheckning
69902c66bc

+ 1 - 9
src/app/_mock/testfields.v8.ts

@@ -1,13 +1,5 @@
 // TESTS: FormBuilder FormArray's and CheckButtomGroups (with Select All / Select Non option)
 
-/*
-const checkbuttonGroup = {
-	type: 'CheckbuttonGroup',
-	firstEnablesRest: true,
-	meta: [{name: 'iMaskTheOthers'}, {name: 'groupMemberTwo'}, {name: 'groupMemberThree'}]
-};
-*/
-
 const model = {
 	standardField: '',
 	cbFormArray: ['A', 'B', 'C', 'D', 'E']
@@ -17,7 +9,7 @@ const model = {
 // But when to render as a FormArray and when as a FormGroup?
 const meta = {
 	standardField: { type: 'textarea' },
-	cbFormArray: { type: 'checkButtonGroup' }
+	cbFormArray: { type: 'CheckbuttonGroup' }
 };
 
 export { model, meta };

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

@@ -4,7 +4,7 @@
 			<h1>NgDynaform</h1>
 			<p>
 			Dynamic Form Layout Module<br>
-			Load different tests by appendiing a query param <b>?test=N</b> (where N is a number between 1 and 7).<br>
+			Load different tests by appending a query param to the URL <b>?test=N</b> (where N is a number between 1 and 8).<br>
 			NOTE: Model set to update on change, but this can be set to blur or submit for less re-rendering.
 			</p>
 		</div>

+ 16 - 0
src/app/app.component.ts

@@ -46,6 +46,22 @@ export class AppComponent implements OnInit, OnChanges {
 		console.log('Model', model);
 		console.log('Meta', meta);
 
+		// Test autoMeta
+		const auto = this.dynaform.autoMeta(model);
+		console.log(auto);
+
+		// Test combine
+		const m2 = this.dynaform.combineModelWithMeta(model, meta);
+		console.log(m2);
+
+		// Test building Field-Specific-Meta
+		const fsm = this.dynaform.buildFieldSpecificMeta(m2);
+		console.log(fsm);
+
+		// Test building the FormGroup
+		const fg = this.dynaform.buildFormGroup(fsm);
+		console.log(fg);
+
 		// Build the FormGroup and Modeled Metadata from the imported test data
 		const dynaformdata = this.dynaform.build(model, meta);
 		({ form: this.form, meta: this.meta } = dynaformdata);

+ 0 - 2
src/app/app.module.ts

@@ -5,8 +5,6 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import { DynaformModule } from './dynaform/dynaform.module';
 import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
 import { AppComponent } from './app.component';
-// import { CheckbuttonGroupComponent } from './dynaform/components/group/checkbutton-group/checkbutton-group.component';
-// import { CheckbuttonComponent } from './dynaform/components/custom/checkbutton/checkbutton.component';
 import { JsonFormatterDirective } from './directives/json-formatter.directive';
 
 @NgModule({

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

@@ -17,7 +17,7 @@
  *
  */
 
-import { FormBuilder, FormGroup, FormControl, ValidatorFn, AsyncValidatorFn } from '@angular/forms';
+import { FormBuilder, FormGroup, FormArray, FormControl, ValidatorFn, AsyncValidatorFn } from '@angular/forms';
 import { reduce } from 'lodash/fp';
 import * as fmdModels from '../models/field.model';
 
@@ -31,17 +31,20 @@ interface AbstractControlOptions {
 
 
 // ---------------------------------------------------------------------------------------------------------------------
-// Raw Model (or Mapped Raw Model) to Automatic Metadata
+// AutoMeta: Raw Model (or Mapped Raw Model) to Automatic Metadata
 // ---------------------------------------------------------------------------------------------------------------------
 
 const isScalar = val => typeof val === 'boolean' || typeof val === 'number' || typeof val === 'string';
+const isArray = val => Array.isArray(val);
 
 const keyValPairToMeta = (val, key) => ({ name: key, [isScalar(val) ? 'value' : 'meta']: val });
 const keyValPairToMetaRecursive = ( [key, val] ) => {
-	const innerVal = isScalar(val) ? val : autoMeta(val);
+	const innerVal = isScalar(val) ? val : (isArray(val) ? arrayToMeta(val) : autoMeta(val));
 	const metaVal = keyValPairToMeta(innerVal, key);
 	return [key, metaVal];
 };
+const arrayToMeta = arrVals => arrVals.map(val => ({ name: val, 'value' : val }));
+
 const autoMeta = model => Object.entries(model)
 	.map(keyValPairToMetaRecursive)
 	.reduce((res, [key, val]) => addProp(res, key, val), {});
@@ -121,14 +124,18 @@ const buildFormGroupFunctionFactory = (fb: FormBuilder): (meta) => FormGroup =>
 	});
 	const buildFormControl = metaF => new FormControl(buildControlState(metaF), buildValidators(metaF));
 
-	// Build Form Group Member
+	// Build Form Array
+	const buildFormArray = (metaG): FormArray => fb.array(metaG.map(metaF => buildFormControl(metaF)));
+
+	// Build Form Group Member - builds a FormControl, FormArray, or another FormGroup which can contain any of these
 	const buildFormGroupMember = metaFoG => isGroup(metaFoG) ?
-		_buildFormGroup(metaFoG.meta) :
+		(isArray(metaFoG.meta) ? buildFormArray(metaFoG.meta) : _buildFormGroup(metaFoG.meta)) :
 		buildFormControl(metaFoG);
 
 	const buildFormGroupReducerIteree = (res, metaFoG) => Object.assign(res, { [metaFoG.name]: buildFormGroupMember(metaFoG) });
 	const _buildFormGroup = _metaG => fb.group(reduce(buildFormGroupReducerIteree, {}, _metaG));
 
+	// The main function - builds FormGroups containing other FormGroups, FormArrays and FormControls
 	const buildFormGroup = metaG => {
 		// Ensure that we have Field-Specific Metadata, not raw Objects
 		const metaWithNameKeys = addMissingNames(metaG);
@@ -161,7 +168,7 @@ const addNameIfMissing = (metaFoG, key) => metaFoG.name ? metaFoG : addProp(meta
 const addNameToSelfAndChildren = ( [key, metaFoG] ) => {
 	metaFoG = addNameIfMissing(metaFoG, key);
 	if (isGroup(metaFoG)) {
-		metaFoG.meta = Array.isArray(metaFoG.meta) ? Object.values(addMissingNames(metaFoG.meta)) : addMissingNames(metaFoG.meta); // Recursion
+		metaFoG.meta = isArray(metaFoG.meta) ? Object.values(addMissingNames(metaFoG.meta)) : addMissingNames(metaFoG.meta); // Recursion
 	}
 	return [key, metaFoG];
 };