-
Notifications
You must be signed in to change notification settings - Fork 0
/
input.component.ts
101 lines (95 loc) · 3.8 KB
/
input.component.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { Component, EventEmitter, forwardRef, Input, OnChanges, Output, Type } from '@angular/core';
import { ControlValueAccessor, FormControl, FormGroup, NG_VALUE_ACCESSOR, AbstractControl } from '@angular/forms';
import { FieldConfigProperty } from '@ec.components/core';
import { Field } from '@ec.components/core/src/field/field';
import { Form } from '@ec.components/core/src/form/form';
import { Item } from '@ec.components/core/src/item/item';
import { DefaultInputComponent } from '../../form/default-input/default-input.component';
import { DynamicSlotComponent } from '../dynamic-slot/dynamic-slot.component';
/** This directive can be used to display a field. It is used inside ec-form as well as ec-list. */
@Component({
selector: 'ec-input',
templateUrl: '../dynamic-slot/dynamic-slot.component.html',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => InputComponent),
multi: true
}
]
})
export class InputComponent extends DynamicSlotComponent implements ControlValueAccessor, OnChanges {
/** The belonging form group */
@Input() group: FormGroup;
/** The belonging form control. This is not required if you pass in a field and group. */
@Input() control: AbstractControl;
/** The changed ouput emits whenever the form control of the input changes. */
@Output() changed = new EventEmitter();
/** Debounce time in ms before the changed event emits. */
@Input() debounce = 0;
/** The instance of field that should be used in the template, can also be a property name. */
@Input() field: Field;
/** The property name that is edited. Expects a form as item input */
@Input() property: string;
/** The belonging item */
@Input() item: Item<any>;
/** Config that should be used, only needed when not using field input */
@Input() config: FieldConfigProperty;
/** Overrides the default component */
@Input() component: Type<any>;
/** Holds a reference to the component instance. This is helpful when you want to modify the component after form intialization.
* You can access a form's InputComponents via FormComponent#inputs */
componentInstance: Component
ngOnChanges() {
if (this.property && this.item instanceof Form) {
this.field = this.item.getField(this.property);
} else if (!this.field && this.config) {
this.field = new Field(this.property || 'input', this.config);
}
if (!this.field) {
return;
}
if (!this.control) {
this.control = this.group ? this.group.get(this.field.property) : new FormControl();
}
if (!this.group) {
this.group = new FormGroup({
[this.property || this.field.property || 'input']: this.control
});
}
const data = {
group: this.group,
control: this.control || this.group ? this.group.get(this.field.property) : null,
item: this.item,
field: this.field,
input: this
};
const componentRef = this.loadComponent(this.component || this.field.input || DefaultInputComponent, data);
this.componentInstance = componentRef.instance;
if (componentRef.instance.control) {
componentRef.instance.control.valueChanges
.debounceTime(this.debounce)
.subscribe((change) => {
this.changed.emit(change);
this.propagateChange(change);
});
}
if (this.field && typeof this.field.init === 'function') {
this.field.init(this.componentInstance, this);
}
}
/** writes value to editor on outside model change. */
writeValue(value: any) {
if (this.componentInstance && this.componentInstance['writeValue']) {
this.componentInstance['writeValue'](value); // TODO: this is pretty hacky
}
}
propagateChange = (_: any) => {
};
/** Registers change callback */
registerOnChange(fn) {
this.propagateChange = fn;
}
registerOnTouched() {
}
}