packages/ui/src/lib/io/input/input.component.ts
This directive can be used to display a field. It is used inside ec-form as well as ec-list.
ControlValueAccessor
OnChanges
changeDetection | ChangeDetectionStrategy.OnPush |
providers |
{
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputComponent), multi: true,
}
|
selector | ec-input |
templateUrl | ../dynamic-slot/dynamic-slot.component.html |
Properties |
Methods |
Inputs |
Outputs |
component | |
Type : Type<any>
|
|
Overrides the default component |
config | |
Type : FieldConfigProperty
|
|
Config that should be used, only needed when not using field input |
control | |
Type : AbstractControl
|
|
The belonging form control. This is not required if you pass in a field and group. |
debounce | |
Default value : 0
|
|
Debounce time in ms before the changed event emits. |
field | |
Type : Field
|
|
The instance of field that should be used in the template, can also be a property name. |
group | |
Type : FormGroup
|
|
The belonging form group |
item | |
Type : Item<any>
|
|
The belonging item |
lazy | |
Type : boolean
|
|
If true, the input will never reinit/reload. |
property | |
Type : string
|
|
The property name that is edited. Expects a form as item input |
changed | |
Type : EventEmitter
|
|
The changed ouput emits whenever the form control of the input changes. |
ready | |
Type : EventEmitter
|
|
Emits when the component has been loaded |
connectControl |
connectControl()
|
Returns :
void
|
focus | ||||||
focus(focus)
|
||||||
Parameters :
Returns :
void
|
init |
init()
|
Returns :
void
|
ngOnChanges | ||||
ngOnChanges(changes?)
|
||||
Parameters :
Returns :
void
|
registerOnChange | ||||
registerOnChange(fn)
|
||||
Registers change callback
Parameters :
Returns :
void
|
registerOnTouched |
registerOnTouched()
|
Returns :
void
|
setDisabledState | ||||
setDisabledState(isDisabled)
|
||||
Parameters :
Returns :
void
|
writeValue | ||||||
writeValue(value: any)
|
||||||
writes value to editor on outside model change.
Parameters :
Returns :
void
|
loadComponent | ||||||||||||
loadComponent(component: Type
|
||||||||||||
Inherited from
DynamicSlotComponent
|
||||||||||||
Defined in
DynamicSlotComponent:17
|
||||||||||||
Loads the given component inside the fieldHost. Sets current item and field by default.
Parameters :
Returns :
ComponentRef<any>
|
componentInstance |
Type : InputComponent
|
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 |
disabled |
Type : FormGroup
|
If true, the input is readonly. Is set by ControlValueAccessor#setDisabled |
focusEvent |
Type : EventEmitter<boolean>
|
Default value : new EventEmitter()
|
Emitter to focus the input field |
propagateChange |
Default value : () => {...}
|
value |
Type : any
|
The current value of the input. Needs to be saved for the case the component is not yet loaded |
Public componentFactoryResolver |
Type : ComponentFactoryResolver
|
Inherited from
DynamicSlotComponent
|
Defined in
DynamicSlotComponent:14
|
fieldHost |
Type : SlotHostDirective
|
Decorators :
@ViewChild(SlotHostDirective, {static: true})
|
Inherited from
DynamicSlotComponent
|
Defined in
DynamicSlotComponent:11
|
The FieldHostDirective will be used to nest custom components into the field |
import {
Component,
EventEmitter,
forwardRef,
Input,
OnChanges,
Output,
Type,
ChangeDetectionStrategy,
} from '@angular/core';
import { ControlValueAccessor, FormControl, FormGroup, NG_VALUE_ACCESSOR, AbstractControl } from '@angular/forms';
import { FieldConfigProperty, Field, Form, Item } from '@ec.components/core';
import { DynamicSlotComponent } from '../dynamic-slot/dynamic-slot.component';
import { DefaultInputComponent } from '../../form/default-input/default-input.component';
import { debounceTime } from 'rxjs/operators';
/** 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',
changeDetection: ChangeDetectionStrategy.OnPush,
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;
/** If true, the input is readonly. Is set by ControlValueAccessor#setDisabled */
disabled: 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();
/** Emits when the component has been loaded */
@Output() ready = 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>;
/** If true, the input will never reinit/reload. */
@Input() lazy: boolean;
/** 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: InputComponent;
/** The current value of the input. Needs to be saved for the case the component is not yet loaded */
value: any;
/** Emitter to focus the input field */
focusEvent: EventEmitter<boolean> = new EventEmitter();
ngOnChanges(changes?) {
if (!this.lazy || !this.componentInstance || changes.field) {
this.init();
}
}
focus(focus = true) {
if (this.componentInstance && this.componentInstance.focusEvent) {
this.componentInstance.focusEvent.emit(focus);
} else {
console.warn('could not focus component', this.componentInstance);
}
}
init() {
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,
config: this.config || this.field.config || {},
focusEvent: this.focusEvent,
};
const componentRef = this.loadComponent(this.component || this.field.input || DefaultInputComponent, data);
this.componentInstance = componentRef.instance;
this.connectControl();
this.ready.emit(this);
if (this.componentInstance.control) {
this.componentInstance.control.valueChanges.pipe(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);
}
}
connectControl() {
if (!this.componentInstance) {
// console.warn('could not connect control: no instance loaded');
return;
}
this.componentInstance.disabled = this.disabled;
if (this.componentInstance.registerOnChange && this.propagateChange) {
this.componentInstance.registerOnChange(this.propagateChange);
}
if (this.value !== undefined) {
this.writeValue(this.value);
}
}
/** writes value to editor on outside model change. */
writeValue(value: any) {
if (this.componentInstance && this.componentInstance.writeValue) {
this.componentInstance.writeValue(value);
}
this.value = value;
}
propagateChange = (_: any) => {};
/** Registers change callback */
registerOnChange(fn) {
this.propagateChange = fn;
this.connectControl();
}
registerOnTouched() {}
setDisabledState(isDisabled) {
this.disabled = isDisabled;
if (this.componentInstance) {
if (this.componentInstance.setDisabledState) {
this.componentInstance.setDisabledState(isDisabled);
} else {
this.componentInstance.disabled = isDisabled;
}
}
}
}
<ng-template ecSlotHost></ng-template>