Bläddra i källkod

Some signs it's working"

Richard Knight 6 år sedan
förälder
incheckning
db08a3e353

+ 16 - 18
src/app/app.component.html

@@ -1,25 +1,23 @@
 <form [formGroup]="form">
-  <div class="container">
-    <div class="row">
-      <div class="col-12 pt-4">
-       <h1>NgDynaform</h1>
-       <p>
-         Dynamic Form Layout Module
-       </p>
-      </div>
-    </div>
-      <app-dynaform formGroupName="dynaformtest" [meta]="formMetaDataObj" [template]="tref"></app-dynaform>
-  </div>
+	<div class="container">
+		<div class="row">
+			<div class="col-12 pt-4 pb-2">
+				<h1>NgDynaform</h1>
+				<p>
+				Dynamic Form Layout Module
+				</p>
+			</div>
+		</div>
+		<app-dynaform formGroupName="dynaformtest" [meta]="formMetaDataObj" [template]="tref"></app-dynaform>
+		<div calss="row">
+			<div class="col-12 pt-4">
+				<json-formatter [data]="form.value" open="2"></json-formatter>
+			</div>
+		</div>
+	</div>
 </form>
 
 
-
-<ng-template #testTemplate let-control="control" let-meta="meta">
-    <h3 style="color: blue;"><small>controlName is </small>{{ meta.name }}</h3>
-    <p>{{ meta | json }}</p>
-    <hr>
-</ng-template>
-  
   
   
   

+ 3 - 1
src/app/app.module.ts

@@ -3,6 +3,7 @@ import { NgModule } from '@angular/core';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import { DynaformModule } from './dynaform/dynaform.module';
 import { AppComponent } from './app.component';
+import { JsonFormatterDirective } from './directives/json-formatter.directive';
 
 @NgModule({
 	imports: [
@@ -12,7 +13,8 @@ import { AppComponent } from './app.component';
 		DynaformModule
 	],
 	declarations: [
-		AppComponent
+		AppComponent,
+		JsonFormatterDirective
 	],
 	providers: [],
 	bootstrap: [AppComponent]

+ 0 - 10
src/app/directives/component-host.directive.ts

@@ -1,10 +0,0 @@
-import { Directive, ViewContainerRef } from '@angular/core';
-
-@Directive({
-	selector: '[component-host]'
-})
-export class ComponentHostDirective {
-
-	constructor(public viewContainerRef: ViewContainerRef) { }
-
-}

+ 4 - 2
src/app/directives/json-formatter.directive.ts

@@ -9,11 +9,14 @@ export class JsonFormatterDirective implements OnChanges {
 	@Input()
 	data: Object;
 
+	@Input()
+	open = 2;
+
 	constructor(private elRef: ElementRef) { }
 
 	ngOnChanges() {
 		if (this.data) {
-			const formatter = new JSONFormatter(this.data);
+			const formatter = new JSONFormatter(this.data, this.open);
 			while (this.elRef.nativeElement.firstChild) {
 				this.elRef.nativeElement.removeChild(this.elRef.nativeElement.firstChild);
 			}
@@ -21,4 +24,3 @@ export class JsonFormatterDirective implements OnChanges {
 		}
 	}
 }
-			

+ 12 - 5
src/app/dynaform/components/dynaform/dynaform.component.html

@@ -1,15 +1,22 @@
-<h2>I am DynaformComponent</h2>
-
 <ng-container *ngFor="let controlName of controlNames">
 	<ng-container *ngTemplateOutlet="template ? template : default; context: getTemplateContext(controlName)"></ng-container>
 </ng-container>
 
 
+<!-- Default template for form field
+     used when a TemplateRef is NOT supplied to component -->
 <ng-template #default let-control="control" let-meta="meta">
-	<h3 style="color: red;"><small>controlName is </small>{{ meta.name }}</h3>
-	<p>{{ meta | json }}</p>
-	<hr>
+	<div class="row">
+		<div class="col-sm-4">
+			<label [for]="meta.name">{{ meta.label }}</label>
+		</div>
+		<div class="col-sm-8">
+			<!-- <input type="text" [formControl]="control" class="form-control form-control-sm"> -->
+			<ng-container dynafield [control]="control" [meta]="meta"></ng-container>
+		</div>
+	</div>
 </ng-template>
 
 
 
+		

+ 2 - 6
src/app/dynaform/components/dynaform/dynaform.component.ts

@@ -1,6 +1,5 @@
 import { Component, Input, ViewChild, TemplateRef, Optional, OnInit } from '@angular/core';
 import { FormGroup, FormGroupName, AbstractControl, ControlContainer } from '@angular/forms';
-// import { KeysPipe } from '@pipes/keys.pipe';
 
 export interface DynarowContext {
 	control: AbstractControl;
@@ -10,8 +9,7 @@ export interface DynarowContext {
 @Component({
 	selector: 'app-dynaform',
 	templateUrl: './dynaform.component.html',
-	styleUrls: ['./dynaform.component.scss'],
-	// providers: [ KeysPipe ]
+	styleUrls: ['./dynaform.component.scss']
 })
 export class DynaformComponent implements OnInit {
 
@@ -61,11 +59,9 @@ export class DynaformComponent implements OnInit {
 			this.formGroup = <FormGroup>this.cc.control; // Get theFormGroup from the ControlContainer
 		}
 		if (!this.formGroup) {
-			throw new Error('Dynaform Component Initialised without [formGroup] or formGroupName');
+			throw new Error('Dynaform Component initialised without [formGroup] or formGroupName');
 		}
 		this.controlNames = Object.keys(this.formGroup.controls);
-		console.log('Dynaform Component: Controls >');
-		console.log(this.controlNames);
 	}
 
 	getTemplateContext(controlName: string): DynarowContext {

+ 1 - 1
src/app/dynaform/components/fields/basicinput/basicinput.component.html

@@ -1 +1 @@
-<input type="text" (change)="onChange($event.target.value)" class="form-control form-control-sm">
+<input type="text" [formControl]="control" class="form-control form-control-sm">

+ 6 - 39
src/app/dynaform/components/fields/basicinput/basicinput.component.ts

@@ -1,52 +1,19 @@
-import { Component, Input, OnInit, forwardRef } from '@angular/core';
-import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+import { Component, Input } from '@angular/core';
 
 @Component({
 	selector: 'app-basicinput',
 	templateUrl: './basicinput.component.html',
-	styleUrls: ['./basicinput.component.scss'],
-	providers: [
-		{
-			provide: NG_VALUE_ACCESSOR,
-			useExisting: forwardRef(() => BasicinputComponent),
-			multi: true
-		}
-	]
+	styleUrls: ['./basicinput.component.scss']
 })
-export class BasicinputComponent implements OnInit {
+export class BasicinputComponent {
 
 	@Input()
-	type?: string = 'text';
+	type = 'text';
 
 	@Input()
-	value?: string | boolean = true;
+	value?: string;
 
 	@Input()
-	isDisabled?: boolean = false;
-	
-	@Input()
-	meta = {};
-
-	currentValue: string;
-	propagateChange = (_: any) => {};
-
-	ngOnInit() {
-		// meta input overrides other inputs if provided
-		['type', 'value', 'isDisabled'].map(p => this[p] = this.meta[p] || this[p]);
-	}
-	
-	onChange(value) {
-		this.currentValue = value;
-		this.propagateChange(value);
-	}
-
-	public writeValue(value: any): void {
-		this.currentValue = value;
-	}
-
-	public registerOnChange(fn: any): void {
-		this.propagateChange = fn;
-	}
+	isDisabled = false;
 
-	public registerOnTouched(fn: any): void {}
 }

+ 8 - 0
src/app/dynaform/components/fields/index.ts

@@ -0,0 +1,8 @@
+// Barrel grouping all form field components
+// See https://basarat.gitbooks.io/typescript/docs/tips/barrel.html
+
+export { BasicinputComponent } from './basicinput/basicinput.component';
+export { DropdownModifiedInputComponent } from './dropdown-modified-input/dropdown-modified-input.component';
+export { CheckbuttonComponent } from './checkbutton/checkbutton.component';
+export { CheckbuttonGroupComponent } from './checkbutton-group/checkbutton-group.component';
+

+ 0 - 10
src/app/dynaform/directives/component-host.directive.ts

@@ -1,10 +0,0 @@
-import { Directive, ViewContainerRef } from '@angular/core';
-
-@Directive({
-	selector: '[component-host]'
-})
-export class ComponentHostDirective {
-
-	constructor(public viewContainerRef: ViewContainerRef) { }
-
-}

+ 51 - 0
src/app/dynaform/directives/dynafield.directive.ts

@@ -0,0 +1,51 @@
+import { ComponentFactoryResolver, ComponentRef, Directive, Input, OnChanges, OnInit, Type, ViewContainerRef } from '@angular/core';
+import { FormControl } from '@angular/forms';
+
+import * as formFieldComponents from './../components/fields';
+
+@Directive({
+	// tslint:disable-next-line:directive-selector
+	selector: '[dynafield]'
+})
+export class DynafieldDirective implements OnInit, OnChanges {
+
+	@Input()
+	control: FormControl;
+
+	@Input()
+	meta: StringMap;
+
+	component: ComponentRef<any>; // TODO: Tighten up on 'any'
+
+	constructor(
+		private resolver: ComponentFactoryResolver,
+		private container: ViewContainerRef
+	) {}
+
+	ngOnInit() {
+		const type = `${this.meta.type}Component`;
+		if (!formFieldComponents[type]) {
+			const validComponentTypes = Object.keys(formFieldComponents).join(', ');
+			throw new Error(
+				`Dynaform Dynafield Error: Invalid field type: ${type}.
+			 	 Supported types: ${validComponentTypes}`
+			);
+		}
+		const component = this.resolver.resolveComponentFactory<any>(formFieldComponents[type]);
+		this.component = this.container.createComponent(component);
+		this.component.instance.control = this.control;
+		this.component.instance.meta = this.meta;
+
+		// Now move meta variables up a level, for direct access in templates implementing dynaField
+		Object.keys(this.meta).map(p => this[p] = this.meta[p]);
+	}
+
+	ngOnChanges() {
+		if (this.component) {
+			this.component.instance.meta = this.meta;
+			this.component.instance.control = this.control;
+		}
+	}
+
+}
+

+ 16 - 2
src/app/dynaform/dynaform.module.ts

@@ -3,6 +3,11 @@ import { CommonModule } from '@angular/common';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 
 import { DynaformComponent } from './components/dynaform/dynaform.component';
+import { DynafieldDirective } from './directives/dynafield.directive';
+
+import {
+	BasicinputComponent, DropdownModifiedInputComponent, CheckbuttonComponent, CheckbuttonGroupComponent
+} from './components/fields';
 
 @NgModule({
 	imports: [
@@ -11,9 +16,18 @@ import { DynaformComponent } from './components/dynaform/dynaform.component';
 		ReactiveFormsModule
 	],
 	declarations: [
-		DynaformComponent
+		DynaformComponent,
+		DynafieldDirective,
+		BasicinputComponent,
+		DropdownModifiedInputComponent,
+		CheckbuttonComponent,
+		CheckbuttonGroupComponent
 	],
-	providers: [
+	entryComponents: [
+		BasicinputComponent,
+		DropdownModifiedInputComponent,
+		CheckbuttonComponent,
+		CheckbuttonGroupComponent
 	],
 	exports: [
 		DynaformComponent

+ 11 - 0
src/styles.scss

@@ -1 +1,12 @@
 /* You can add global styles to this file, and also import other style files */
+
+h1 {
+	color: magenta;
+	border-bottom: 4px blueviolet solid;
+	margin-bottom: 1em;
+}
+
+div.col-sm-4 {
+	background-color: lavenderblush;
+	border-top: 3px white solid;
+}