-
Notifications
You must be signed in to change notification settings - Fork 496
Custom Components with Angular Elements
Starting from angular-formio v4.3.0 you can register an Angular component as a formio field. It uses the @angular/elements in the background, so that package is required as peer dependency.
@webcomponents/custom-elements package is required.
After installing it via npm or yarn, add the following line to the angular.json file to the scripts array:
"node_modules/@webcomponents/custom-elements/src/native-shim.js"And the following line to the app's polyfills.ts file:
import '@webcomponents/custom-elements/custom-elements.min';You should implement the FormioCustomComponent interface and define the required variables. The Component class may look like the following:
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { FormioCustomComponent } from 'angular-formio';
@Component({
selector: 'app-rating-wrapper',
templateUrl: './rating-wrapper.component.html',
styleUrls: ['./rating-wrapper.component.scss']
})
export class RatingWrapperComponent implements FormioCustomComponent<number> {
@Input()
value: number;
@Output()
valueChange = new EventEmitter<number>();
@Input()
disabled: boolean;
}The value input stores the value of the field. The valueChange output should be called upon value update, but please not that's only a change trigger event, the formio framework reads the value from the value field. So a value update may look like the following:
updateValue(payload: number) {
this.value = payload; // Should be updated first
this.valueChange.emit(payload); // Should be called after this.value update
}The change event (output) is named as valueChange to keep compatibility with the Angular principles if you want to use the same component at other places inside your app.
You should register your Angular component in the entryComponents array. This won't be required after Angular v9 with Ivy.
Add a new file next to your component. E.g. if you have rating-wrapper.component.ts place a new file next to it, e.g. rating-wrapper.formio.ts
Add the following content:
import { Injector } from '@angular/core';
import { FormioCustomComponentInfo, registerCustomFormioComponent } from 'angular-formio';
import { RatingWrapperComponent } from './rating-wrapper.component';
const COMPONENT_OPTIONS: FormioCustomComponentInfo = {
type: 'myrating', // custom type. Formio will identify the field with this type.
selector: 'my-rating', // custom selector. Angular Elements will create a custom html tag with this selector
title: 'Rating', // Title of the component
group: 'basic', // Build Group
icon: 'fa fa-star', // Icon
};
export function registerRatingComponent(injector: Injector) {
registerCustomFormioComponent(COMPONENT_OPTIONS, RatingWrapperComponent, injector);
}Call the registration in the constructor of your NgModule like this:
export class AppModule {
constructor(injector: Injector) {
registerRatingComponent(injector);
}
}If you don't want to register an Angular Component as you want to implement the logic in a simple class, take a look at the CheckMatrix example: https://github.com/formio/angular-demo/blob/master/src/app/components/CheckMatrix.js
Please remember that the Formio.registerComponent method is not available in TypeScript environment due to typings limitations, call the Components.addComponent method instead.