File

packages/ui/src/lib/io/input/input.component.ts

Description

This directive can be used to display a field. It is used inside ec-form as well as ec-list.

Extends

DynamicSlotComponent

Implements

ControlValueAccessor OnChanges

Metadata

changeDetection ChangeDetectionStrategy.OnPush
providers { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputComponent), multi: true, }
selector ec-input
templateUrl ../dynamic-slot/dynamic-slot.component.html

Index

Properties
Methods
Inputs
Outputs

Inputs

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

Outputs

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

Methods

connectControl
connectControl()
Returns : void
focus
focus(focus)
Parameters :
Name Optional Default value
focus No true
Returns : void
init
init()
Returns : void
ngOnChanges
ngOnChanges(changes?)
Parameters :
Name Optional
changes Yes
Returns : void
registerOnChange
registerOnChange(fn)

Registers change callback

Parameters :
Name Optional
fn No
Returns : void
registerOnTouched
registerOnTouched()
Returns : void
setDisabledState
setDisabledState(isDisabled)
Parameters :
Name Optional
isDisabled No
Returns : void
writeValue
writeValue(value: any)

writes value to editor on outside model change.

Parameters :
Name Type Optional
value any No
Returns : void
loadComponent
loadComponent(component: Type, attributes: Object)
Inherited from DynamicSlotComponent

Loads the given component inside the fieldHost. Sets current item and field by default.

Parameters :
Name Type Optional Default value
component Type<any> No
attributes Object No {}
Returns : ComponentRef<any>

Properties

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
fieldHost
Type : SlotHostDirective
Decorators :
@ViewChild(SlotHostDirective, {static: true})
Inherited from DynamicSlotComponent

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>
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""