浏览代码

Adding library functions fto build modeled metadata from basic metadata

Richard Knight 6 年之前
父节点
当前提交
cc6e0d7dbd

+ 29 - 41
src/app/_mock/testfields.ts

@@ -58,6 +58,11 @@ const checkbutton = new fmd.CheckbuttonField({
 	value: '456'
 });
 
+const checkbutton2 = new fmd.CheckbuttonField({
+	name: 'checkbutton2',
+	value: 'Yowsa'
+});
+
 const modifiers = ['Matches', 'Starts With', 'Contains'];
 const transformerFunctions: ValueTransformer = {
 	inputFn: val => {
@@ -102,18 +107,6 @@ const checkbuttonGroup = new fmd.CheckbuttonGroup({
 	meta: [{name: 'iMaskTheOthers'}, {name: 'groupMemberTwo'}, {name: 'groupMemberThree'}]
 });
 
-
-const checkbuttonSA = new fmd.CheckbuttonField({
-	name: 'checkbuttonSA',
-	value: '456'
-});
-
-
-const checkbuttonGroupSA = new fmd.CheckbuttonGroup({
-	name: 'checkbuttonGroupSA',
-	meta: [{name: 'iMaskTheOthers'}, {name: 'groupMemberTwo'}, {name: 'groupMemberThree'}]
-});
-
 // ---------------------------------------------------------------------------------------------------------------------
 // Kendo
 
@@ -129,43 +122,38 @@ const datepicker = new fmd.DatepickerField({
 // Container
 
 const container = new fmd.Container({
-	basicTextField,
-	styledTextField,
-	textareaField,
-	passwordField,
-	selectField,
-	radioField,
-	disabledTextField,
-	radioFieldHorizontal,
-	checkbutton,
-	dropdownModifiedInput,
-	checkbuttonGroup,
-	timepicker,
-	datepicker
+	// basicTextField,
+	// styledTextField,
+	// textareaField,
+	// passwordField,
+	// selectField,
+	// radioField,
+	// disabledTextField,
+	// radioFieldHorizontal,
+	checkbutton2,
+	// dropdownModifiedInput,
+	// checkbuttonGroup,
+	// timepicker,
+	// datepicker
 });
 
 // ---------------------------------------------------------------------------------------------------------------------
 
 export const formMetaDataObj = {
 	basicTextField,
-	styledTextField,
-	textareaField,
-	passwordField,
-	selectField,
-	radioField,
-	disabledTextField,
-	radioFieldHorizontal,
+	// styledTextField,
+	// textareaField,
+	// passwordField,
+	// selectField,
+	// radioField,
+	// disabledTextField,
+	// radioFieldHorizontal,
 	checkbutton,
-	dropdownModifiedInput,
-	checkbuttonGroup,
-	timepicker,
-	datepicker,
+	// dropdownModifiedInput,
+	// checkbuttonGroup,
+	// timepicker,
+	// datepicker,
 	container
 };
 
-export const standAlone = {
-	checkbuttonSA,
-	checkbuttonGroupSA
-}
-
 console.log(formMetaDataObj);

+ 0 - 11
src/app/app.component.html

@@ -9,12 +9,6 @@
 			</div>
 		</div>
 		<app-dynaform formGroupName="dynaformtest" [meta]="formMetaDataObj" [template]="tref"></app-dynaform>
-		<!-- <div class="row">
-			<div class="col-12 pt-4 pb-4" formGroupName="standAlone">
-				<app-checkbutton [formControl]="tempctl" [meta]="standAlone.checkbuttonSA"></app-checkbutton>
-				<app-checkbutton-group formGroupName="checkbuttonGroupSA" [control]="tempgrp" [meta]="standAlone.checkbuttonGroupSA" firstEnablesRest></app-checkbutton-group>
-			</div>
-		</div> -->
 		<div calss="row">
 			<div class="col-12 pt-4 pb-4">
 				<json-formatter [data]="form.value" open="3"></json-formatter>
@@ -22,8 +16,3 @@
 		</div>
 	</div>
 </form>
-
-
-  
-  
-  

+ 2 - 3
src/app/app.component.ts

@@ -2,7 +2,7 @@ import { Component, OnInit, ViewChild, TemplateRef } from '@angular/core';
 import { FormBuilder, FormGroup } from '@angular/forms';
 import { buildFormGroup } from './dynaform/libs';
 
-import { formMetaDataObj, standAlone } from './_mock/testfields';
+import { formMetaDataObj } from './_mock/testfields';
 
 @Component({
 	selector: 'app-root',
@@ -14,7 +14,6 @@ export class AppComponent implements OnInit {
 	form: FormGroup;
 
 	formMetaDataObj = formMetaDataObj;
-	standAlone = standAlone;
 
 	@ViewChild('testTemplate', { read: TemplateRef })
 	private tref: TemplateRef<any>;
@@ -29,7 +28,7 @@ export class AppComponent implements OnInit {
 			dynaformtest: { meta: this.formMetaDataObj }
 		};
 		this.form = buildFormGroup(fullFormMeta);
-		this.form.addControl('standAlone', buildFormGroup(standAlone));
+		console.log(this.form);
 	}
 }
 

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

@@ -23,6 +23,11 @@ export class CheckbuttonComponent extends CustomInputComponent implements OnChan
 	value?: string | boolean = true;
 	currentValue: string | boolean;
 
+	ngOnInit() {
+		super.ngOnInit();
+		console.log(this.control);
+	}
+
 	ngOnChanges() {
 		this.isDisabled = this.meta.isDisabled;
 	}

+ 2 - 2
src/app/dynaform/components/native/radio/radio.component.html

@@ -1,4 +1,4 @@
 <div *ngFor="let opt of options; let i = index;" class="custom-control custom-radio" [ngClass]="{'custom-control-inline' : horizontal}">
-	<input type="radio" [formControl]="control" [value]="opt.value" [name]="name" [id]="name + i" class="custom-control-input">
-	<label class="custom-control-label" [for]="name + i">{{ opt.label }}</label>
+	<input type="radio" [formControl]="control" [value]="opt.value" [name]="prefix" [id]="prefix + i" class="custom-control-input">
+	<label class="custom-control-label" [for]="prefix + i">{{ opt.label }}</label>
 </div>

+ 6 - 0
src/app/dynaform/components/native/radio/radio.component.ts

@@ -9,5 +9,11 @@ import { NativeInputComponent } from '../../_abstract/native-input.component';
 export class RadioComponent extends NativeInputComponent {
 
 	exposeMetaInTemplate: string[] = ['name', 'options', 'horizontal'];
+	prefix: string;
+
+	constructor() {
+		super();
+		this.prefix = 'radio_u_' + Math.floor((Math.random() * 10000)).toString();
+	}
 
 }

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

@@ -2,7 +2,7 @@ import {
 	Directive, ComponentFactoryResolver, ComponentRef, ViewContainerRef,
 	Input, Output, EventEmitter, OnInit, SkipSelf
 } from '@angular/core';
-import { Form, FormControl, ControlContainer, NgControl, ControlValueAccessor, ValidatorFn, AsyncValidatorFn } from '@angular/forms';
+import { Form, FormControl, ControlContainer, NgControl, ControlValueAccessor, ValidatorFn, AsyncValidatorFn, AbstractFormGroupDirective } from '@angular/forms';
 
 import * as formFieldComponents from './../components';
 
@@ -66,7 +66,11 @@ export class DynafieldDirective extends NgControl implements OnInit {
 			const el = this.component.location.nativeElement;
 			el.classList.add(type.toLowerCase().replace('component', ''));
 
+			// Support the recursive insertion of Dynaform components
 			if (type === 'DynaformComponent') {
+				if (meta.template) {
+					(<any>instance).template = meta.template;
+				}
 				meta = meta.meta;
 			}
 
@@ -92,7 +96,7 @@ export class DynafieldDirective extends NgControl implements OnInit {
 				// so we need to wire it up!
 				this.name = name;
 				this.valueAccessor = <FFCCustom>this.component.instance;
-				this._control = this.formDirective.addControl(this);
+				this._control = this.formGroupDirective.addControl(this);
 			}
 		} catch (e) {
 			console.error('ERROR INSTANTIATING DYNAFORM CHILD COMPONENT', type);
@@ -104,7 +108,7 @@ export class DynafieldDirective extends NgControl implements OnInit {
 		return [...this.cc.path, this.name];
 	}
 
-	get formDirective(): Form | null {
+	get formGroupDirective(): Form | null {
 		return this.cc ? this.cc.formDirective : null;
 	}
 

+ 7 - 3
src/app/dynaform/dynaform.component.html

@@ -6,7 +6,8 @@
 <!-- Default template for form field
      used when a TemplateRef is NOT supplied to component -->
 <ng-template #default let-control="control" let-meta="meta">
-	<div class="row" *ngIf="meta.type !== 'CONTAINER'; else recursiveDynaform" [ngClass]="getRowClass(meta.type)">
+	
+	<div class="row" *ngIf="meta.type !== 'Dynaform'; else recursiveDynaform" [ngClass]="getRowClass(meta.type)">
 		<div class="col-sm-4">
 			<label [for]="meta.name">{{ meta.label }}</label>
 		</div>
@@ -14,10 +15,13 @@
 			<ng-container dynafield [control]="control" [meta]="meta"></ng-container>
 		</div>
 	</div>
+	
 	<ng-template #recursiveDynaform>
+		<div class="row pt-3">
+			<h3 class="col-sm-12">{{ meta.name }}</h3>
+		</div>
 		<app-dynaform [formGroup]="control" [meta]="meta.meta" [template]="template"></app-dynaform>
 	</ng-template>
-</ng-template>
-
 
+</ng-template>
 

+ 19 - 0
src/app/dynaform/libs/index.ts

@@ -1,5 +1,6 @@
 import { FormBuilder, FormControl } from '@angular/forms';
 import { reduce } from 'lodash/fp';
+import * as fmdModels from './../models';
 
 /*
  * FORM UTILITIES
@@ -42,6 +43,24 @@ const addMissingNames = metaG => Object.entries(metaG)
 	.reduce((res, [key, val]) => addProp(res, key, val), {});
 
 // ---------------------------------------------------------------------------------------------------------------------
+// Form Metadata Factory
+
+const buildModeledField = metaF => {
+	// TODO: Add validity check
+	const modeledMetaF= new fmdModels[metaF.type](metaF);
+	return modeledMetaF;
+}
+
+// Build Form Group Member
+const buildModeledGroupMember = metaFoG => isGroup(metaFoG) ? _buildModeledGroup(metaFoG.meta) : buildModeledField(metaFoG);
+
+// Build Form Group
+const buildModeledGroupReducerIteree = (res, metaFoG) => Object.assign(res, { [metaFoG.name]: buildFormGroupMember(metaFoG) });
+const _buildModeledGroup = metaG => reduce(buildModeledGroupReducerIteree, {}, metaG);
+const buildModeledGroup = metaG => _buildModeledGroup(addMissingNames(metaG));
+
+// ---------------------------------------------------------------------------------------------------------------------
+// Functions which build FormControls and FormGroups
 
 // Build Form Control
 // TODO: Flesh out function to build validators

+ 3 - 0
src/app/dynaform/models/index.ts

@@ -4,6 +4,7 @@
  * Keep in one file for now, but maybe split if this grows too large
  ********************************************************************************************************************* */
 
+import { TemplateRef } from '@angular/core'; 
 import { ValidatorFn, AsyncValidatorFn } from '@angular/forms';
 import { ValueTransformer } from './../interfaces';
 
@@ -183,6 +184,8 @@ class DatepickerField extends SimpleField {
 
 class Container {
 	type = 'Dynaform';
+	label = '';
+	template?: TemplateRef<any>;
 	meta: StringMap // TODO: Tighten up on type with union type
 	constructor(children: StringMap) {
 		this.meta = children;