Browse Source

Adding support for validation functions

Richard Knight 6 years ago
parent
commit
e5d143ba6d

+ 38 - 0
src/app/_mock/testfields.v6.ts

@@ -0,0 +1,38 @@
+// TESTS: Validators
+
+import { Validators } from '@angular/forms';
+
+const model = {
+	dynaformtest: {
+		a: 'Value 1',
+		b: 'Value 2',
+		c: 'Maybe',
+		d: {
+			e: 444,
+			f: 555,
+			g: {
+				h: true,
+				i: false
+			}
+		},
+		z: 'THE END'
+	}
+};
+
+const meta = {
+	dynaformtest: {
+		meta: {
+			a: { validators: Validators.required },
+			b: { type: 'checkbutton' },
+			c: { label: 'Property Three', type: 'radio', options: ['Yes', 'No', 'Maybe'], horizontal: 1 },
+			d: {
+				meta: {
+					e: { type: 'radio', 'label': 'Does it work yet?' },
+					f: { type: 'datepicker' }
+				}
+			}
+		}
+	}
+};
+
+export { model, meta };

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

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

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

@@ -2,7 +2,7 @@ import { Component, OnInit, ViewChild, TemplateRef } from '@angular/core';
 import { FormGroup } from '@angular/forms';
 import { DynaformService } from './dynaform/services/dynaform.service';
 
-import { model, meta as lazyMeta } from './_mock/testfields.v5';
+import { model, meta as lazyMeta } from './_mock/testfields.v6';
 
 @Component({
 	selector: 'app-root',

+ 6 - 4
src/app/dynaform/dynaform.component.ts

@@ -1,4 +1,4 @@
-import { Component, Input, TemplateRef, Optional, OnInit } from '@angular/core';
+import { Component, Input, TemplateRef, Optional, OnInit, ChangeDetectionStrategy } from '@angular/core';
 import { FormGroup, FormGroupName, AbstractControl, ControlContainer } from '@angular/forms';
 
 export interface DynarowContext {
@@ -9,7 +9,8 @@ export interface DynarowContext {
 @Component({
 	selector: 'app-dynaform',
 	templateUrl: './dynaform.component.html',
-	styleUrls: ['./dynaform.component.scss']
+	styleUrls: ['./dynaform.component.scss'],
+	changeDetection: ChangeDetectionStrategy.OnPush
 })
 export class DynaformComponent implements OnInit {
 
@@ -44,7 +45,7 @@ export class DynaformComponent implements OnInit {
 
 	@Input()
 	set meta(data) {
-		this.formMetaData = data;
+		this.formMetaData = this.formMetaData || data;
 	}
 
 	@Input()
@@ -98,7 +99,7 @@ export class DynaformComponent implements OnInit {
 			let fg = this.formGroup;
 			while (fg.parent) {
 				// Find the identity of 'fg' in the parent FormGroup's controls
-				const fgIdentity = Object.entries(fg.parent.controls).filter(([key, candidate]) => candidate === fg).pop();
+				const fgIdentity = Object.entries(fg.parent.controls).find(([key, candidate]) => candidate === fg);
 				path.push(fgIdentity[0]);
 				fg = <FormGroup>fg.parent;
 			}
@@ -107,6 +108,7 @@ export class DynaformComponent implements OnInit {
 	}
 	
 	getTemplateContext(controlName: string): DynarowContext {
+		// console.log(controlName);
 		return {
 			control: this.formGroup.get(controlName),
 			meta: this.formMetaData[controlName]

+ 18 - 9
src/app/dynaform/services/meta-utils.ts

@@ -1,7 +1,3 @@
-import { FormBuilder, FormGroup, FormControl } from '@angular/forms';
-import { reduce } from 'lodash/fp';
-import * as fmdModels from './../models';
-
 /*
  * FORM METADATA UTILITIES
  *
@@ -21,6 +17,19 @@ import * as fmdModels from './../models';
  *
  */
 
+import { FormBuilder, FormGroup, FormControl, ValidatorFn, AsyncValidatorFn } from '@angular/forms';
+import { reduce } from 'lodash/fp';
+import * as fmdModels from './../models';
+
+// REMINDER: Import this directly from @angular/forms when we upgrade to Angular 6
+// While we're still' on Angular 5 just declare it
+interface AbstractControlOptions {
+	validators?: ValidatorFn | ValidatorFn[] | null
+	asyncValidators?: AsyncValidatorFn | AsyncValidatorFn[] | null
+	updateOn?: 'change' | 'blur' | 'submit'
+}
+
+
 // ---------------------------------------------------------------------------------------------------------------------
 // Raw Model (or Mapped Raw Model) to Automatic Metadata
 // ---------------------------------------------------------------------------------------------------------------------
@@ -106,12 +115,12 @@ const buildFormGroupFunctionFactory = (fb: FormBuilder): (meta) => FormGroup =>
 	// Build Form Control
 	// TODO: Flesh out function to build validators
 	const buildControlState = metaF => ({ value: metaF.value || metaF.default, disabled: metaF.isDisabled });
-	const buildValidators = metaF => ({
-		validators: null,
-		asyncValidators: null,
+	const buildValidators = (metaF): AbstractControlOptions => ({
+		validators: metaF.validators,
+		asyncValidators: metaF.asyncValidators,
 		updateOn: 'blur'
 	});
-	const buildFormControl = metaF => new FormControl(buildControlState(metaF) /*, buildValidators(metaF) */);
+	const buildFormControl = metaF => new FormControl(buildControlState(metaF), buildValidators(metaF));
 
 	// Build Form Group Member
 	const buildFormGroupMember = metaFoG => isGroup(metaFoG) ?
@@ -130,7 +139,7 @@ const buildFormGroupFunctionFactory = (fb: FormBuilder): (meta) => FormGroup =>
 
 
 // ---------------------------------------------------------------------------------------------------------------------
-// Helper Funstions
+// Helper Functions
 // ---------------------------------------------------------------------------------------------------------------------
 
 // Add Property to object

+ 7 - 0
src/styles.scss

@@ -58,3 +58,10 @@ div.col-sm-8 {
 	display: inline-block;
 	max-width: 165px;
 }
+
+input[type=text].ng-invalid ,
+input[type=password].ng-invalid ,
+textarea.ng-invalid ,
+select.ng-invalid  {
+	border-left: 3px red solid;
+}