Skip to content

Instantly share code, notes, and snippets.

@travist
Last active November 30, 2019 23:12
Show Gist options
  • Save travist/59fa77086ec899e24992fc1508e61075 to your computer and use it in GitHub Desktop.
Save travist/59fa77086ec899e24992fc1508e61075 to your computer and use it in GitHub Desktop.
Angular 5 + Form.io Custom Component
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { FormioAuthService } from 'angular-formio/auth';
import { AppConfig } from '../config';
import { FormioForm } from 'formiojs/full';
import from './CheckMatrix'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'app';
offlineCount = 0;
offlineMode: any = null;
offlineError = '';
constructor(private auth: FormioAuthService, private router: Router) {
this.auth.onLogin.subscribe(() => {
this.router.navigate(['/home']);
});
this.auth.onLogout.subscribe(() => {
this.router.navigate(['/auth/login']);
});
this.auth.onRegister.subscribe(() => {
this.router.navigate(['/home']);
});
// Register our custom components.
FormioForm.registerComponent('checkmatrix', CheckMatrix);
}
}
/**
* This file shows how to create a custom component and register that within an Angular application.
*
* Get the base component class by referencing Formio.Components.components map.
*/
import BaseComponent from 'formiojs/components/base/Base';
import TableComponent from 'formiojs/components/table/Table';
import Components from 'formiojs/components/Components';
/**
* Create a new CheckMatrixComponent "class" using ES5 class inheritance notation.
* https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance
*
* Here we will derive from the base component which all Form.io form components derive from.
*
* @param component
* @param options
* @param data
* @constructor
*/
export default class CheckMatrixComponent extends BaseComponent {
/**
* Define what the default JSON schema for this component is. We will derive from the BaseComponent
* schema and provide our overrides to that.
* @return {*}
*/
static schema() {
return BaseComponent.schema({
type: 'checkmatrix',
numRows: 3,
numCols: 3
});
}
/**
* Register this component to the Form Builder by providing the "builderInfo" object.
*/
static get builderInfo() {
return {
title: 'Check Matrix',
group: 'basic',
icon: 'fa fa-table',
weight: 70,
documentation: 'http://help.form.io/userguide/#table',
schema: CheckMatrixComponent.schema()
};
}
/**
* Tell the renderer how to build this component using DOM manipulation.
*/
build() {
this.element = this.ce('div', {
class: 'table-responsive'
});
this.createLabel(this.element);
var tableClass = 'table ';
['striped', 'bordered', 'hover', 'condensed'].forEach(function(prop) {
if (this.component[prop]) {
tableClass += `table-${prop} `;
}
}.bind(this));
var table = this.ce('table', {
class: tableClass
});
// Build the body.
var tbody = this.ce('tbody');
this.inputs = [];
this.checks = [];
for (let i = 0; i < this.component.numRows; i++) {
var tr = this.ce('tr');
this.checks.push([]);
for (let j = 0; j < this.component.numCols; j++) {
var td = this.ce('td');
this.checks[i][j] = this.ce('input', {
type: 'checkbox'
});
this.addInput(this.checks[i][j], td);
tr.appendChild(td);
}
tbody.appendChild(tr);
}
table.appendChild(tbody);
this.element.appendChild(table);
}
/**
* Provide the input element information. Because we are using checkboxes, the change event needs to be
* 'click' instead of the default 'change' from the BaseComponent.
*
* @return {{type, component, changeEvent, attr}}
*/
elementInfo() {
const info = super.elementInfo();
info.changeEvent = 'click';
return info;
}
/**
* Tell the renderer how to "get" a value from this component.
*
* @return {Array}
*/
getValue() {
var value = [];
this.checks.forEach((row, rowIndex) => {
value[rowIndex] = [];
row.forEach((col, colIndex) => {
value[rowIndex][colIndex] = !!col.checked;
});
});
return value;
}
/**
* Tell the renderer how to "set" the value of this component.
*
* @param value
* @return {boolean}
*/
setValue(value) {
if (!value) {
return;
}
this.checks.forEach((row, rowIndex) => {
if (!value[rowIndex]) {
return false;
}
row.forEach((col, colIndex) => {
if (!value[rowIndex][colIndex]) {
return false;
}
let checked = value[rowIndex][colIndex] ? 1 : 0;
col.value = checked;
col.checked = checked;
});
});
}
}
// Use the table component edit form.
CheckMatrixComponent.editForm = TableComponent.editForm;
// Register the component to the Formio.Components registry.
Components.addComponent('checkmatrix', CheckMatrixComponent);
{
"type": "checkmatrix",
"input": true,
"numRows": 5,
"numColumns": 5,
"label": "Check Matrix",
"key": "checkMatrix"
}
@asalhani
Copy link

@travist thanks for this helpful gist. One more thing that i think if you avhive it then it will yake you library to new level is how the controls in the custom component being created. As demonstrated here you are creating the control in the code by injecting html elements. Instead of that, and you agree with me that injecting(drawing) htlm controls this way will be creazy when the logic of custom component becomes complicated. Is it possible to have the component htlm defined in a separate file and then somehow in component. Js file we link the code with html file? Also we need to think about properties and functions binding between template and code file. In shott, can you make the custom component using the same way Angular creating them? Where in angular you have the html template and. Ts file that utilize that template

@dslshweta
Copy link

@travist -
I am getting error as
Module not found: Error: Can't resolve 'formiojs/full'
Module not found: Error: Can't resolve 'formiojs/lib/components/table/Table'

I am using dependencies having following versions :
"formiojs": "^3.0.0-rc.7",
"angular-formio": "^2.0.0-rc.2",

Moreover I would like to get this custom component on a builder so as to allow user to drag and drop this as any other component. and dismiss the popup that comes for setting field properties.
Please suggest.
screenshot-portal form io-2018 07 18-12-30-17
screenshot-portal form io-2018 07 18-12-28-43

@travist
Copy link
Author

travist commented Jul 20, 2018

Yeah, this is currently for the 2.x branch of the formio.js library. I will need to make some changes to make it 3.x compatible and will need a few days before I have time to do this.

@Sigkill9
Copy link

Sigkill9 commented Aug 8, 2018

I am trying to register a custom component and cannot find where formiojs/full resides?
I have done a clean angular 6 ng new install and added the formios

npm i angular-formio --save
npm i angularjs --save

import { FormioForm } from 'formiojs/full';

I cannot find it.

@indingpig
Copy link

@dslshweta did you found the solution? Can you suggest me?

@indingpig
Copy link

@travist Hi, I have a question, In CheckMatrix.ts file, does the build() function build the html code? if I want to write html template code, how to do it?

@sriram275
Copy link

Hi,
Trying to create and register custom component here with help this gist

Registering like:
FormioForm.registerComponent('checkmatrix', CheckMatrix);

In Angular Form io:
But FormioForm doesn't have registerComponent method or might be import statement wrong
import { FormioForm } from 'angular-formio';

Let me know how to handle this?

Thanks.

@Sigkill9
Copy link

Sigkill9 commented Sep 24, 2018

@travist
I cannot seem to get this gist working.

I have installed the latest formiojs from npm.

The line below does not seem to exist anywhere. it is not in "formiojs": "^3.5.3".

import { FormioForm } from 'formiojs/full';

So following recommendations from @Aiso786
I added the following file:

// src/app/typings/index.d.ts
declare module 'formiojs'

Defined path to above file in tsconfig.json

"typeRoots": [
      "node_modules/@types",
      "./src/app/typings/index"
    ],

My error went away.
Now while debugging I see my component added to Formio.Components._components but when rendering the form I get
Unknown component: mycustomcomponent

The issue seems to be angular-formio is using it's own "internal" formiojs ./angular-formio/node_modules/formiojs which is a separate instance from ./myapplicationroot/node_modules/formiojs which I am registering my custom components with.
When trying to use this internal formiojs I get:

core.js:1598 ERROR Error: Uncaught (in promise): TypeError: comp.build is not a function

webpack:///./node_modules/angular-formio/node_modules/formiojs/components/Components.js

Where have I gone wrong here?

Any help is greatly appreciated.

@travist
Copy link
Author

travist commented Oct 13, 2018

I just updated this gist to now be correct with the latest renderer.

@chinmayek
Copy link

@travist, i want to have a custom component in react using react-formio, how can i do that.
Please help me out.

@shivlila01
Copy link

shivlila01 commented Dec 3, 2018

In the older version of angular-formio(1.18.0) we registered the custom components using Formio.registerComponent() method and it was working perfectly.
Recently we have upgraded our application with latest version of angular-formio (3.9.0) and formiojs version as 2.32.3 after this up-gradation our custom components are not working it is showing error message as "unknown component : mycustomcomponent". Please help.

@krixerx
Copy link

krixerx commented Jan 2, 2019

I'm using successfully custom component in angular6 like described. But i would like to use my custom component on formbuilder edit modal too (technically in Base.edit.logic.js).
Can we do it?

@sayyar-source
Copy link

i have same problem. please help

@sayyar-source
Copy link

i have same problem. please help

@suportecaso1
Copy link

Do you have any sample with Aurelia and Typescript?

@srinvasneelamraju
Copy link

Do you have any example on creating check box component using formio

@srinvasneelamraju
Copy link

any html code for rendering formio custom component..
I have to render custom formio select drop down component in to my application.For that i created one js file like Select.js and i had taken the Select.js code from https://formio.github.io/formio.js/docs/class/src/components/select/Select.js~SelectComponent.html
and also i registered that component into my custom_formio.component.ts as
Formio.registerComponent('custom_formio', SelectComponent);
where custom_formio is the name of my component which having Select.js file and other ts and html and css files. and SelectComponent is the name of class name which is declared in Select.js file.
So i am getting confusion that which code i have to write in html to render select dropdown into my application

@srinvasneelamraju
Copy link

how to disable the popup in check matrix component

@felipebelluco
Copy link

@srinvasneelamraju did you find the solution?

@felipebelluco
Copy link

@travis I'm trying to override the method createModal so as the build method was, but it's never called. Do you know how to do that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment