|
@@ -1,30 +1,41 @@
|
|
|
import {
|
|
|
Directive, ComponentFactoryResolver, ComponentRef, ViewContainerRef,
|
|
|
- Input, Output, EventEmitter, OnInit
|
|
|
- SkipSelf
|
|
|
+ Input, Output, EventEmitter, OnInit, SkipSelf
|
|
|
} from '@angular/core';
|
|
|
-import { FormControl, ControlContainer, NgControl, ValidatorFn, AsyncValidatorFn } from '@angular/forms';
|
|
|
+import { Form, FormControl, ControlContainer, NgControl, ControlValueAccessor, ValidatorFn, AsyncValidatorFn } from '@angular/forms';
|
|
|
|
|
|
import * as formFieldComponents from './../components/fields';
|
|
|
|
|
|
+interface FFC {
|
|
|
+ control: FormControl
|
|
|
+ meta: StringMap
|
|
|
+ propagateChange?: Function
|
|
|
+}
|
|
|
+type FFCCustom = FFC & ControlValueAccessor;
|
|
|
+
|
|
|
@Directive({
|
|
|
// tslint:disable-next-line:directive-selector
|
|
|
- selector: '[dynafield]',
|
|
|
+ selector: '[dynafield]'
|
|
|
})
|
|
|
export class DynafieldDirective extends NgControl implements OnInit /* OnChanges */ {
|
|
|
|
|
|
@Input()
|
|
|
- control: FormControl;
|
|
|
+ meta: StringMap;
|
|
|
|
|
|
@Input()
|
|
|
- meta: StringMap;
|
|
|
+ set control(fc: FormControl) {
|
|
|
+ this._control = this._control || fc;
|
|
|
+ }
|
|
|
+
|
|
|
+ get control(): FormControl | null {
|
|
|
+ return this._control;
|
|
|
+ }
|
|
|
|
|
|
@Output('ngModelChange')
|
|
|
update = new EventEmitter();
|
|
|
|
|
|
- component: ComponentRef<any>; // TODO: Tighten up on 'any'
|
|
|
-
|
|
|
- _control: FormControl;
|
|
|
+ component: ComponentRef<FFC>;
|
|
|
+ _control;
|
|
|
|
|
|
constructor(
|
|
|
private resolver: ComponentFactoryResolver,
|
|
@@ -44,15 +55,27 @@ export class DynafieldDirective extends NgControl implements OnInit /* OnChanges
|
|
|
);
|
|
|
}
|
|
|
try {
|
|
|
- this.name = this.meta.name;
|
|
|
- const component = this.resolver.resolveComponentFactory<any>(formFieldComponents[type]);
|
|
|
+ const { name, class: cssClass, id: cssId } = this.meta;
|
|
|
+ const component = this.resolver.resolveComponentFactory<FFC>(formFieldComponents[type]);
|
|
|
this.component = this.container.createComponent(component);
|
|
|
- this.component.instance.control = this.control;
|
|
|
- this.component.instance.meta = this.meta;
|
|
|
- if (this.component.instance.propagateChange) {
|
|
|
- // We're dealing with a custom form control that implements the ControlValueAccessor interface,
|
|
|
- // so we need to wire it up
|
|
|
- this.valueAccessor = this.component.instance;
|
|
|
+ const instance = this.component.instance;
|
|
|
+ const el = this.component.location.nativeElement;
|
|
|
+
|
|
|
+ // Send in the data
|
|
|
+ instance.control = this.control;
|
|
|
+ instance.meta = this.meta;
|
|
|
+ if (cssClass) {
|
|
|
+ const classesToAdd = Array.isArray(cssClass) ? cssClass : [cssClass];
|
|
|
+ el.classList.add(...classesToAdd);
|
|
|
+ }
|
|
|
+ if (cssId) {
|
|
|
+ el.id = cssId;
|
|
|
+ }
|
|
|
+ if (instance.propagateChange) {
|
|
|
+ // We're dealing with a custom form control which implements the ControlValueAccessor interface,
|
|
|
+ // so we need to wire it up!
|
|
|
+ this.name = name;
|
|
|
+ this.valueAccessor = <FFCCustom>this.component.instance;
|
|
|
this._control = this.formDirective.addControl(this);
|
|
|
}
|
|
|
} catch(e) {
|
|
@@ -74,12 +97,10 @@ export class DynafieldDirective extends NgControl implements OnInit /* OnChanges
|
|
|
return [...this.cc.path !, this.name];
|
|
|
}
|
|
|
|
|
|
- get formDirective(): any {
|
|
|
+ get formDirective(): Form | null {
|
|
|
return this.cc ? this.cc.formDirective : null;
|
|
|
}
|
|
|
|
|
|
- // get control(): FormControl { return this._control; }
|
|
|
-
|
|
|
get validator(): ValidatorFn | null { return null; }
|
|
|
|
|
|
get asyncValidator(): AsyncValidatorFn { return null; }
|