-
Notifications
You must be signed in to change notification settings - Fork 472
Form Renderer
The most important aspect of the Form.io platform is the ability to render a form dynamically within your application and then hook that form up to the REST API provided by the Form.io API platform. The Form Renderer within Form.io provides this capability.
As mentioned in the previous section, to use this library within your project, you will first need to install it as a dependency.
npm install --save angular-formio
Once you have the module installed, you will now need to include the form renderer within your application by adding the FormioModule
as a dependency within your application as follows.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormioModule } from 'angular-formio';
import { MainComponent } from './main';
@NgModule({
imports: [
BrowserModule,
FormioModule
],
declarations: [
MainComponent
],
providers: [],
bootstrap: [
MainComponent
]
})
export class AppModule {}
Once you have the module installed, you can now include the <formio>
directive within your Modules template like the following.
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: '<formio src="https://examples.form.io/example"></formio>'
})
export class MainComponent {}
This provides a way to render the form within your application.
In addition to providing the URL of the form you wish to render, you can also pass the JSON form directly to the renderer as follows.
<formio [form]='{
"title": "My Test Form",
"components": [
{
"type": "textfield",
"input": true,
"tableView": true,
"inputType": "text",
"inputMask": "",
"label": "First Name",
"key": "firstName",
"placeholder": "Enter your first name",
"prefix": "",
"suffix": "",
"multiple": false,
"defaultValue": "",
"protected": false,
"unique": false,
"persistent": true,
"validate": {
"required": true,
"minLength": 2,
"maxLength": 10,
"pattern": "",
"custom": "",
"customPrivate": false
},
"conditional": {
"show": "",
"when": null,
"eq": ""
}
},
{
"type": "textfield",
"input": true,
"tableView": true,
"inputType": "text",
"inputMask": "",
"label": "Last Name",
"key": "lastName",
"placeholder": "Enter your last name",
"prefix": "",
"suffix": "",
"multiple": false,
"defaultValue": "",
"protected": false,
"unique": false,
"persistent": true,
"validate": {
"required": true,
"minLength": 2,
"maxLength": 10,
"pattern": "",
"custom": "",
"customPrivate": false
},
"conditional": {
"show": "",
"when": null,
"eq": ""
}
},
{
"input": true,
"label": "Submit",
"tableView": false,
"key": "submit",
"size": "md",
"leftIcon": "",
"rightIcon": "",
"block": false,
"action": "submit",
"disableOnInvalid": true,
"theme": "primary",
"type": "button"
}
]
}'></formio>
This is a very simple example. This library is capable of building very complex forms which include e-signatures, columns, panels, field conditionals, validation requirements, and the list goes on and on.
The inputs for the <formio>
directive allow you to control how the form renderer behaves. For example, to set the submission
of a form (which will pre-populate the form with data), you can provide the following code which will set the form.
<formio src="https://examples.form.io/example" [submission]='{
"data": {
"firstName": "Joe",
"lastName": "Smith",
"email": "joe@example.com"
}
}'></formio>
The following inputs are accepted.
Name | Type | Description | ||||||
---|---|---|---|---|---|---|---|---|
src | String | To set the source URL of the form (or submission) to be rendered. Example: src="https://examples.form.io/example"
|
||||||
form | Object | To render the JSON schema of a form. Example: [form]='{"components":[...]}'
|
||||||
url | String | This is a way to passively provide the form URL to the renderer without it submitting data to that url. This is different than "src" in that if you provide your Form API url, it will not submit data to this url. This is commonly used in conjunction with the "form" attribute, where you also need to allow for File uploads (since they require an API call to the form url). | ||||||
submission | Object | The submission JSON to pre-poulate the form. Example: [submission]='{"data": {"name": "Joe Smith"}}'
|
||||||
refresh | EventEmitter<Any> | This allows you to refresh the form or the submission that is rendered within the renderer. EventEmitter must be type Any. See the section on Updating form and submissions below. | ||||||
service | FormioService | Your own instance of the FormioService object to perform the requests. | ||||||
readOnly | Boolean | Make the form (and submission) read only. Great for when you are rendering a previous submission that should not be editable. | ||||||
viewOnly | Boolean | Show the form in "viewOnly" mode, where it does not show a form, but rather a view only representation of a form + submission data. | ||||||
hideComponents | Array | An array of components that you wish to hide once the form is done rendering. | ||||||
hooks | Object | Used to provide "hooks" into the form renderer, such as a "beforeSubmit" hook to trigger when the form is submitting. | ||||||
language | String | The language code you wish to show this rendered form in. Example: "us-en" | ||||||
options | Object | A JSON object of the following options.
|
Once you have the form rendered within your application, the next step is to handle the submission within your Component. You can do this by using the (submit)
output of the form renderer.
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: '<formio src="https://examples.form.io/example" (submit)="onSubmit()"></formio>'
})
export class MainComponent {
onSubmit(submission: any) {
console.log(submission); // This will print out the full submission from Form.io API.
}
}
Let's suppose you need to hook into the Form submission, make a call to your own service to perform a custom validation on that submission, and then when your validation passes, allow the submission to be handled. You may also want to tell the form that an error occurred within the Form submission and then provide the error. To do this, you will need to provide the options.hooks.beforeSubmit
callback, which works as follows.
<formio src='https://examples.form.io/example' options='{
"hooks": {
"beforeSubmit": function(submission, callback) {
console.log(submission);
// Do something asynchronously.
setTimeout(function() {
// Callback with a possibly manipulated submission.
callback(null, submission);
}, 1000);
}
}
}'></formio>
You may also wish to provide your own custom error.
<formio src='https://examples.form.io/example' options='{
"hooks": {
"beforeSubmit": function(submission, callback) {
console.log(submission);
// Do something asynchronously.
setTimeout(function() {
// Callback with a possibly manipulated submission.
callback({
message: "Something bad happened.",
component: null
}, null);
}, 1000);
}
}
}'></formio>
To update the form or the submission within the Angular renderer, you will need to pass along the refresh input property when rendering the form. The value of the refresh property will be an event emitter that will emit a FormioRefreshValue value that will update either the submission or the form.
As an example, if you wish to dynamically alter the form after it is rendered, you can do the following.
<formio [form]="myForm" [refresh]="refreshForm"></formio>
@Component({
...
...
})
export class MyComponent implements OnInit {
ngOnInit() {
this.myForm = {
components: [....];
};
this.refreshForm = new EventEmitter();
}
changeForm() {
this.myForm.components.push({
type: 'textfield',
label: 'New Field',
key: 'newField',
input: true
});
this.refreshForm.emit({
form: this.myForm
});
}
}
If you wish to update both the form and submission, you can provide it as follows.
@Component({
...
...
})
export class MyComponent implements OnInit {
ngOnInit() {
this.myForm = {
components: [....];
};
this.refreshForm = new EventEmitter();
}
changeForm() {
this.myForm.components.push({
type: 'textfield',
label: 'New Field',
key: 'newField',
input: true
});
this.refreshForm.emit({
form: this.myForm,
submission: {
data: {
newField: 'Testing'
}
}
});
}
}
With the <formio>
directive, you can register for a number of different events that fire as the Form is being used and submitted. These events can be attached with the typical Angular 2 way using the following syntax.
<formio src="https://examples.form.io/example" (submit)="onSubmit($event)"></formio>
The following events are provided.
Name | Description |
---|---|
(submit) | Called when the form is submitted. The submission object is passed to the callback function. |
(render) | Called when the form is done rendering. |
(beforeSubmit) | Called before a submission is made. The submission object is passed to the callback function. Note: If you need to manipulate the data, or even provide custom validations, then you should use the options.hooks.beforeSubmit handler instead. See documentation above. |
(change) | Called when the form has been changed as in when someone is filling it out. |
(invalid) | Called when the form is invalid. |
(nextPage) | Called when the form is in Wizard mode and goes to the next page. |
(prevPage) | Called when the form is in Wizard mode and goes to the previous page. |
(customEvent) | Called when the form contains a Button configured with a custom event and is pressed. |
(errorChange) | Called when the form errors change. |
(formLoad) | Called when the form is done loading. |
(ready) | Called when the form renderer is ready. This returns the Form instance object to the callback function. |
The Form.io renderer also provides a way to introduce your own custom components within the renderer / builder. To see an example of how this works, please take a look at the Angular Demo application. This application introduces the CheckMatrix component which can be seen @ https://github.com/formio/angular-demo/blob/master/src/app/components/CheckMatrix.js.
To register this component, you simply need to add the following to your main app.module.ts file.
import './CheckMatrix';