Custom Component
Overview
The custom component code in this tutorial can be found at https://github.com/formio/contrib/tree/master/src/components/rating
All components in Form.io are JavaScript classes. We have created a base class call Component in which all components extend from to create new component classes. Then from those newly created component classes we create more component classes and so on. In this tutorial you will learn how to
Create your own custom component class
Bundle your custom component via webpack
Add a custom component to your [JavaScript / Angular / React] application
Add a custom component to the enterprise portal application
The custom component in this tutorial is a Rating component. The features that will be implemented are
Changing icons (using bootstrap icons)
Changing the size of the icons
Changing the color of the icons
Changing the number of icons
Prerequisites
Install Node.js
An IDE for developing code such as Visual Studio Code or Webstorm
A understanding of JavaScript, HTML, CSS, and Modules Bundlers
Creating the Custom Component
This section of the tutorial will teach you how to create a custom component. We will be going over some of the basics on custom component creation by creating a Rating Component. This section is to teach you...
How to extend from the base component class
What are the fundamental methods of the base component should you implement
Creating a custom template for your component
Creating a edit form for your component
Start by creating a new project folder in your IDE. We will be naming this project RatingComponent
In your project directory run the commands
npm init -y
andnpm install @formio/js
Create a folder structure in your IDE that looks like the following
Add the following code to Rating.js.
Every component in Formio extends from the a base component. This allows you to inherit all the methods and instance variables from the component you are extending from. Learn more about class inheritance here
Schema is a static method that defines the json properties of your component. It also defines the default values of your json properties as well as override some of the json properties you are extending from. The best way to understand what schema is doing is to create a form builder, drag a component onto the builder, and then click the edit JSON option on the component. You will see the components JSON schema.
The constructor is useful for defining instance variables that will be used internally by your component. You can learn more about class constructors here
The render method is one of the most important functions extended from the base component. It allows you to define how your component will render when using Formio.createForm
. In this tutorial we will be using a custom template to define the html of our custom component.
The attach method is another important function extended from the base component. The attach method is were you will add event listeners and attach functionality to your component. This method is ran after your component has been rendered on the DOM.
It is important to note the this.loadRefs method called at the top of the attach method. This load refs method will look for attributes specified in the method on the component html element and put them in the object refs on the instance of your component. For example, the above this.loadRefs will... - Look for a single ref attribute on the component element and save it in this.refs - Look for multiple ref attributes on the component element and save it in this.refs We will dive deeper into refs in the Creating the Custom Template section of this tutorial
The setValue method is a function that takes a value and updates the component data modal. This function is useful for when you want to make updates to what data your component is holding. This data can be of any type (string, number, object, etc). For example, if this.setValue('3/5') was called then when making a submission to the form with this component the submission data would look something like...
Its important to note that if you want to retrieve the value that is set by setValue then you can call this.dataValue. The dataValue getter function retrieve the current value of you component. You may have seen this earlier when we called
The get defaultSchema function returns the schema of your component. It is used when merging all the json schemas upon component creation. There is not much more to say about this function other than your component will behave unexpectedly if this function is not included.
Setting the static editForm variable allows you to define the edit form of your component. This is the edit form that is displayed when you drag and drop a component onto the form builder. For example the edit form of a textfield component looks like the following
Lets create this editForm in the Rating.form.js file
Add the following code to Rating.form.js
A editForm is just a function that returns some JSON. In order to create a custom editForm for your component we use a function called baseEditForm. The baseEditForm is a function that takes an array of json to extend the editForm of the base component class. It is in this array were you will define the component structure of each tab in your editForm. The key property is the tab title in your editForm and the components is a json representation of an editForm within that tab. You can create completely new tabs and override existing base tabs. It is best practice to create separate files for defining the components for your tabs with the following naming convention [ComponentName].edit.[TabName].js
Note the ignore: true
. By setting ignore to true you can remove entire tabs of the baseEditForm. For example, the above code will result in the layout tab being removed from the edit form
Add the following code to Rating.edit.display.js
You may have noticed that the properties in each of these JSONs looks just like the JSON we define in the schema of our component or the json schema of the textfield shown earlier. This is because Form.io editForms are Form.io forms under the hood! When you are interacting with editForms in the form builder, you are actually using a Form.io form. This is possible because all Form.io forms can be created through a simple JSON schema!
It is important to note that the key property in the JSON should match the property in the component schema. This allows for changes made to the properties of the editForm to be reflected in the properties of the component. For example the keys numberOfIcons, icon, color, and iconSize need to match the properties in static schema
Note the ignore: true
. By setting ignore to true you can remove edit fields of the tab you are defining. For example, the above code will result in placeholder field being removed from the display tab
Creating the Custom Template
Templates in Form.io are functions that take a context object and return a html string. They have a structure that looks like the following
These template functions are passed an object conventionally named ctx. This ctx is what we call a context object. It is passed data about the component that is being rendered. Earlier in this tutorial we passed numberOfIcons and filledIcons into an object as the second parameter to the renderTemplate function
This adds numberOfIcons and filledIcons to the ctx object when rendering our template. For example, the above code would allow you to call ctx.numberOfIcons
. Additionally the template is also passed some default context data. You can find the additional data in the evalContext function and the data variable in the renderTemplate function
In this tutorial we will be creating a custom template that will be used by our custom component.
Get started by adding the following code to form.js
A couple things to note here
The ctx object is passed data to it that we can use to create our custom component html. For example we call
ctx.component.color
. This corresponds to the static schema we defined earlier in this tutorial. We can interpolate our component schema values into our html by calling ctx.component.[schemaProperty]The ref attribute. This is the most important attribute of your custom components template. It allows you to attach references to specific html elements by giving the reference a name. For example the
ref="rating" ref="icon"
allows you to reference 'rating' and 'icon' html elements in your custom component code. I will walk through step by step how this works...
The renderer renders your custom component onto the DOM. Lets say the render function outputted the following HTML
In the attach function of your custom component you would call this.loadRefs passing in the element given by attach and an object specifiying the refs you would like to load. In this case we need to load rating and icon. Notice that we give rating the 'single' value and icon the 'multiple' value. This is because there is only one ref attribute that has the value 'rating' and there multiple ref attributes that have the value 'icon'. The 'single' and 'multiple' values will dictate whether the ref will be saved as an HTMLElement or HTMLCollection.
Now that the refs are loaded we can call this.refs to access the references to the HTMLElement(s). For example, in our attachIcons function we reference the icons by calling
this.refs.icon
. The idea behind this is now that you have a reference to your HTMLElement(s) you can attach event listeners and properties to those references. In this example we are able to attach a click event listener to our icons because we are able to reference the HTMLElement viathis.refs.icon
Adding the Custom Component to your Application
To add the custom component to your application you can use the Formio.use function. The Formio.use function allows you to add plugins to your formio forms. In this case we will be adding our component and template as plugins. We will be going over how to add your custom component to a...
JavaScript Application (via webpack)
Angular Application
React Application
It is important to include bootstrap icons in your application as the custom rating component uses bootstrap icons when rendering
JavaScript Application (webpack)
To show how to bundle the custom component into a JavaScript app we first need to create a simple application. We will be using same nodejs project folder used to house the custom component files to house our application files as well.
Start by installing the following dependencies
npm install webpack webpack-cli webpack-dev-server html-webpack-plugin
Create a webpack.config.js file in the root directory of your project
Create a index.html and index.js files under the src directory. Your project structure should look like
In webpack.config.js add the following code
In your index.html file add the following html. Notice that we have included the cdn for bootstrap icons. This is necessary in order to load our icons for the custom component
In your index.js file add the following JavaScript. Notice how we are using Formio.use here. Formio.use allows you to add your custom component and custom template to formio so that it can be used by functions such as Formio.createForm and Formio.builder.
Try it out! Uncomment Formio.createForm or Formio.builder and run
webpack serve
to see the custom component in action.
Angular Application
Importing the custom component and custom template into an angular application is very similar to how you would in vanilla JavaScript. To get the custom component in your angular application all you need to do is move your custom component and custom template code into your app and call the Formio.use function at the top level of your angular application. For example, if you created a angular application using the ng new
command then your application code may look something like...
You will either need to allow angular to process Javascript files by setting allowJs: true
in tsconfig.json or convert your custom component and custom template files to typescript
You can test to see if the custom component works by using the formio directive in a template
React Application
Importing the custom component and custom template into a react application is very similar to how you would in vanilla JavaScript. To get the custom component in your react application all you need to do is move your custom component and custom template code into your app and call the Formio.use function at the top level of your react application. For example, if you created a react application using the npm create vite
command then your application code may look something like...
You will either need to allow angular to process Javascript files by setting allowJs: true
in tsconfig.json or convert your custom component and custom template files to typescript
You can test to see if the custom component works by rendering
Getting the Rating Component into the Developer Portal
To get custom components into the Developer Portal Application, you will be modifying the Custom JS & CSS settings in your project. We will be adding our custom component JavaScript code as well as bootstrap icons to the Developer Portal by adding the links to the Custom JS and Custom CSS fields in the settings. Because the Custom JS field only accepts a single JavaScript file we will need to bundle our custom component code into a single .js file.
Please follow the webpack setup in Adding the Custom Component to your Application as this setup will be used to bundle our code.
Before bundling the custom component into a single file we need to make one small change in webpack.config.js. Add the following code to webpack.config.js. This externals is a webpack configuration that excludes formiojs in the bundle of custom component code. Because the Developer Portal Application already includes formiojs in the application we need to exclude formiojs from our custom component code as it is not needed
Now run the command
webpack
. You shoud now see a /dist directory with your index.bundle.js file in it.You now need to take the code inside
index.bundle.js
and host it. If you already have a way to host your code then you can skip the following stepsOpen up GitHub and create a new repository called
MyCustomComponent
Click
uploading an existing file
Upload the
index.bundle.js
fileClick
Commit changes
You should now have a repository called MyCustomComponent with index.bundle.js inside
jsDeliver is an easy way to create CDNs from GitHub repositories. If you followed the steps above your CDN should be
https://cdn.jsdelivr.net/gh/user/MyCustomComponent/index.bundle.js
Replace
user
with your GitHub username
Now that you have a CDN with your bundled code you can get the custom component onto the enterprise form builder
Open up your developer portal and create a new project
In the navigation bar click
Settings
Click on
Custom JS & CSS
Under
Custom Javascript
andCustom CSS
add the links to your custom component code and bootstrap icons. If you followed the steps to using GitHub to host your custom component code then your Custom CSS and JavaScript should look like the followingSave Settings (Click OK if you're asked if you would like to load the JavaScript)
Create a new Web Form
You should now see Rating component under the basic tab in the form builder
You can now use the Rating component when creating Forms!
It is important to understand that the Developer Portal and your application are two separate applications. This means that if you have added the custom component onto the Developer Portal and are embedding the form into your application via an embed link then you must have the custom component on your application as well in order for the custom component to work. If you see "Unknown component: rating" when trying to create a form using the rating component then the rating component is not being properly bundled into your application. Check the Formio.use function and make sure that you have followed the steps outlined in this tutorial correctly.
Last updated
Was this helpful?