-
Notifications
You must be signed in to change notification settings - Fork 21
Creating custom components
FormQL loads the fields in the form programmatically using the Dynamic Component Loader technique, this gives the ability to create your own components and add bespoke functionality to your form. This article explains the steps to create your own custom components and add them to the form using the editor.
Creating a new component in FormQL is nothing different than implementing the ControlValueAccessor in a Reactive Form with a few extra steps depending on the properties we want the component to have.
The properties used by FormQL are:
-
componentName (
string- required): static property with the name of the component, this is the name used by FormQL to identify the component.
export class MyComponent implements ControlValueAccessor {
static componentName = 'MyComponent';
// ...The component can implement any existing Angular validator or a bespoke validator. T
-
formQLComponent (
boolean- required): static property used by FormQL to differentiate the component from any other one that can be loaded programmatically.
export class MyComponent implements ControlValueAccessor {
static componentName = 'MyComponent';
static formQLComponent = true;
// ...-
@Input field (
FormComponent<T>- required): input object that passes the properties of the component. FormComponent is an interface exposed by the @formql/core package
export class MyComponent implements ControlValueAccessor {
static componentName = 'MyComponent';
static formQLComponent = true;
@Input() field: FormComponent<string>;
// ...-
@Input formControl (
FormControl- required): input object that passes the FormControl assigned to the component. FormComponent is an interface exposed by the @formql/core package
export class MyComponent implements ControlValueAccessor {
static componentName = 'MyComponent';
static formQLComponent = true;
@Input() field: FormComponent<string>;
@Input() formControl: FormControl;
// ...-
validators (
Array<FormValidator>- optional): static array with the list of validators the component supports. FormValidator is an interface exposed by the @formql/core package and it's defined as follows:
export interface FormValidator {
name: string;
key: string;
validator: ValidatorFn;
parameters: any;
}The component can implement any of the existing validators or implement its own custom ones. Below is an example of a component implementing the required validator.
export class MyComponent implements ControlValueAccessor {
static componentName = 'MyComponent';
static formQLComponent = true;
static validators = [
<FormValidator>{
name: 'Required',
validator: Validators.required,
key: 'required'
}
];
// ...-
actions (
Array<FormAction>- optional): static array with the list of actions the component can perform. FormAction is an interface exposed by the @formql/core package and it's defined as follows:
export interface FormAction {
key: FormActionType;
customkey: string;
parameters: any;
}import { Component, Input, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR,
NG_VALIDATORS, Validators, FormControl } from '@angular/forms';
import { FormComponent, FormValidator } from '@formql/core';
@Component({
selector: 'app-my-component',
styleUrls: ['./app-my.component.scss'],
template: `<div *ngIf="formControl!=null">
<label [attr.for]="field.componentId">{{field.label}}</label>
<div>
<input [id]="field.componentId" [type]="field.type"
[formControl]="formControl" [tabIndex]="field.tabIndex"
[attr.disabled]="formControl.disabled ? '' : null">
</div>
</div>`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MyComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => MyComponent),
multi: true
}]
})
export class MyComponent implements ControlValueAccessor {
static componentName = 'MyComponent';
static formQLComponent = true;
static validators = [
<FormValidator>{
name: 'Required',
validator: Validators.required,
key: 'required'
}
];
@Input() field: FormComponent<string>;
@Input() formControl: FormControl;
private _value: string;
get value(): any {
return this._value;
}
set value(value: any) {
this._value = value;
}
writeValue(value: string): void {
if (value)
this._value = value;
}
registerOnChange(fn: any): void {}
registerOnTouched(fn: any): void { }
}