Skip to content

Commit

Permalink
Merge pull request #5575 from formio/fio-4112
Browse files Browse the repository at this point in the history
FIO-4112: Integrate @formio/core validation engine to renderer + many other code cleanup.
  • Loading branch information
brendanbond committed Apr 23, 2024
2 parents 5a2d49b + 715ab01 commit f96bf94
Show file tree
Hide file tree
Showing 128 changed files with 5,095 additions and 6,495 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@
"program": "${workspaceFolder}/node_modules/.bin/mocha",
"args": ["-b", "-t", "0", "'${file}'"],
"console": "integratedTerminal",
}
},
]
}
181 changes: 181 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,187 @@ All notable changes to this project will be documented in this file
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased: 5.0.0]

### New Features

#### New package name
The first thing that you will notice with the 5.x renderer is the package name has changed from **formiojs** to **@formio/js**. This is to be more consistent with the naming conventions that we are starting to use with all of our externally facing libraries. This change is as follows:

##### Before 5.x
```
npm install --save formiojs
```

##### After 5.x
```
npm install --save @formio/js
```

##### Before 5.x
```js
import { Formio } from 'formiojs';
```

##### After 5.x
```js
import { Formio } from '@formio/js';
```

All other libraries and modules within this package remain the same. The following still works as expected.

```js
// This still works as it did in < 5.x. The only thing that changes is @formio/js name.
import { Formio, Components } from '@formio/js';
```

#### Bootstrap 5 Support
The 5.x renderer now supports, and defaults to Bootstrap 5 for the base template. We have also moved the templates from the renderer to their own repository which can be found @ https://github.com/formio/bootstrap. If you wish to use the 5.x renderer with Bootstrap 4, that is also supported but the following code will need to be included within your application.

```js
import { Formio } from '@formio/js';
import bootstrap4 from '@formio/bootstrap/bootstrap4';
Formio.use(bootstrap4);
```

This is a **Breaking Change** so please see the section below for more information about this change.

#### New Validation Engine
The 5.x renderer incorporates our new Core validation engine found @ https://github.com/formio/core/tree/master/src/process. This process can be briefly described within the pull request notes @ https://github.com/formio/formio.js/pull/5317. This will also improve our Iso-morphic behavior for our renderer validation and significantly improve memory and processor consumption for server-side form validations. This feature does have a **Breaking Change** which is described below.

#### Improved render build sizes
With the 5.x version of the renderer/builder, there has been much effort into reducing the size of the build for the renderer. While the full renderer is still "large" and over the 1mb goal, we still have been able to trim a lot of size from the renderer/builder as follows.

- formio.form.min.js ~ 1.2mb => ~30% size reduction
- formio.form.min.js ~ 1.4mb => ~30% size reduction
- formio.min.js (SDK) ~ 235k => ~50% size reduction

#### New lazy-loading Embedding method.
One of the more exciting new additions to the 5.x renderer is the new lazy-loading process for adding the renderer to your application. There is a new file that is included with the 5.x renderer called "formio.embed.js". This file is tiny coming in at ~10kb. What this file does, however, is make it so that you can bundle a lazy-loading renderer within your application without increasing the build sizes of your application.

To use the new lazy-loading features, you will need to change your imports from the following to the new embed source as the following illustrates.

##### Before 5.x
```js
import { Formio } from 'formiojs';
```

##### After 5.x using Embed code.
```js
import { Formio } from '@formio/js/embed';
```

Anywhere you use the Formio.createForm or the Formio.builder methods, this functionality will then add a simple "loader" where the form will render, while then loading the full code to perform the rendering. All of the code that you are used to still functions as you would expect. For example, the following code still works.

```js
import { Formio } from '@formio/js/embed';

// Before, this would require a +1mb renderer to be bundled with your application to embed a form into a page. Now with the "embed" code, this will only incur a 10kb code penalty and show a loader symbol while the full renderer is lazy-loaded into the application. This improves usability so your application can quickly load and the form will show a loader while the user waits for the renderer to download and form to render.
Formio.createForm(document.getElementById('formio'), 'https://examples.form.io/example').then(function(form) {
form.submission = {
data: {
firstName: 'Joe',
lastName: 'Smith'
}
};
});
```

The following methods are able to be used within this embedded renderer.

- Formio.createForm
- Formio.builder
- Formio.use
- Formio.setBaseUrl
- Formio.setProjectUrl

If you wish to have code that is executed after the library has been lazy loaded, you can use the following code.

```js
import { Formio as FormioEmbed } from '@formio/js/embed';

FormioEmbed.formioReady.then(function(Formio) {
// This will be the TextField components.
console.log(Formio.Components.components.textfield);
});
```

#### "childComponents" and improved performance with getComponent method.
The 5.x renderer introduces a new "flat-map" of all component instances and their paths with the "childComponents" map. It can be used as follows.

```js
import { Formio } from '@formio/js';

Formio.createForm(document.getElementById('formio'), 'https://examples.form.io/example').then(function(form) {
// Prints out all child components and their data paths.
console.log(form.childComponents);
});
```

This map is also important to dramatically speed up the heavily used ```getComponent``` method.

```js
Formio.createForm(document.getElementById('formio'), 'https://examples.form.io/example').then(function(form) {
// Now returns the component from map lookup (quick search) vs O^n searching for the component.
const firstName = form.getComponent('firstName');
});
```

### Breaking Changes
- Bootstrap 5 Default Template - With the 5.x version of the renderer, the default template is now **Bootstrap 5** and is found @ https://github.com/formio/bootstrap repo.
- Bootstrap Icons - Now, instead of Font Awesome being the default icon set for our renderer, we are using Bootstrap Icons as the default icon set which is compatible with Bootstrap 5. Of course, you can always change out icon sets, but this is now the default.
- This version implements a new validation system. Within this, there are some changes that you should be aware of.
- In version 4.x, each component would have an error associated with that component as ```component.error```. This has changed
to ```component.errors``` which is an array of errors that are associated with the component. For example, if your custom logic references
the ```component.error.messages``` array, it will need to be changed as follows.

**4.x Renderer**
```js
const textField = form.getComponent('textField');
console.log(textField.error.messages[0]); // Legacy way of getting the text field error for the first error.
```

**5.x Renderer**
```js
const textField = form.getComponent('textField');
console.log(textField.errors[0].message); // 5.x way of getting the error message for the first error.
```
- EditGrid **validateRows** method now returns an array of errors instead of a boolean "true" or "false". If you wish to do the same thing as before 5.x, then you can use the following code.

```js
const isValid = form.getComponent('editgrid').validateRow().length === 0;
```

- In the 5.x renderer, the errors array will always be populated if there are errors in the form. They may not be displayed depending on the "pristine" state of the rendered form, but the error is always populated if there are form errors. This is different in 4.x where the error property would only contain and error if an error is VISIBLE on the form. This means that it is difficult to determine if a form has errors without executing the checkValidity() method with the dirty flag set to "true". You no longer need to do this in the 5.x renderer.

**4.x Renderer**
```js
const textField = form.getComponent('requiredField');
console.log(textField.error); // This would be null even if there was an error, but it was not visible.
```

**5.x Renderer**
```js
const textField = form.getComponent('requiredField');
console.log(textField.errors); // This will be populated with the errors of the textfield even if they are not displayed on the form.
```

- If you wish to show the "visibleErrors", then there is a new property on each component called "visibleComponents".

**4.x Renderer**
```js
const textField = form.getComponent('requiredField');
console.log(textField.errors);
```

**5.x Renderer**
```js
const textField = form.getComponent('textField');
console.log(textField.visibleErrors); // This is the equivalent of the 4.x renderer "errors" array.
```

- With the 5.x renderer, all templates are now stored within a separate repo, and are included as a dependency for this renderer.

## [Unreleased: 5.0.0-rc.40]
### Fixed
- FIO-7525: fixed an issue where new conditional logic based on select boxes does not work
Expand Down
9 changes: 8 additions & 1 deletion _layouts/default.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap/dist/js/bootstrap.min.js"></script>
{% if page.formioFull == nil %}
{% if page.noFormio == nil %}
<script src="{{ site.baseurl }}dist/formio.embed.js"></script>
<script src="{{ site.baseurl }}dist/formio.js"></script>
<script type="text/javascript">
Formio.config.cdnUrls = {
js: {
cdn: '{{ site.baseurl }}dist'
}
};
</script>
{% endif %}
{% endif %}
{% if page.lodash %}
Expand Down
1 change: 1 addition & 0 deletions embed.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './types/Embed';
67 changes: 36 additions & 31 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,37 +1,43 @@
{
"name": "@formio/js",
"version": "5.0.0-rc.27",
"version": "5.0.0-rc.43",
"description": "JavaScript powered Forms with JSON Form Builder",
"main": "lib/cjs/index.js",
"module": "lib/mjs/index.js",
"exports": {
".": {
"import": "./lib/mjs/index.js",
"types": "index.d.ts",
"import": "./lib/cjs/index.js",
"require": "./lib/cjs/index.js"
},
"./sdk": {
"import": "./lib/mjs/Formio.js",
"types": "./types/Formio.d.ts",
"import": "./lib/cjs/Formio.js",
"require": "./lib/cjs/Formio.js"
},
"./utils": {
"import": "./lib/mjs/utils/index.js",
"import": "./lib/cjs/utils/index.js",
"require": "./lib/cjs/utils/index.js"
},
"./form": {
"import": "./lib/mjs/formio.form.js",
"import": "./lib/cjs/formio.form.js",
"require": "./lib/cjs/formio.form.js"
},
"./embed": {
"import": "./lib/mjs/formio.embed.js",
"require": "./lib/cjs/formio.embed.js"
}
"types": "./types/Embed.d.ts",
"import": "./lib/cjs/Embed.js",
"require": "./lib/cjs/Embed.js"
},
"./dist/*": "./dist/*"
},
"types": "index.d.ts",
"files": [
"dist",
"lib",
"types",
"index.d.ts"
"index.d.ts",
"embed.d.ts",
"sdk.d.ts",
"utils.d.ts"
],
"pre-commit": [
"lint"
Expand Down Expand Up @@ -78,21 +84,21 @@
},
"homepage": "https://github.com/formio/formio.js#readme",
"dependencies": {
"@formio/bootstrap": "^3.0.0-rc.20",
"@formio/bootstrap": "^3.0.0-rc.22",
"@formio/choices.js": "^10.2.1",
"@formio/core": "1.3.0-rc.16",
"@formio/core": "^2.1.0-dev.tt.2",
"@formio/text-mask-addons": "^3.8.0-formio.2",
"@formio/vanilla-text-mask": "^5.1.1-formio.1",
"abortcontroller-polyfill": "^1.7.5",
"autocompleter": "^8.0.4",
"bootstrap": "^5.3.0",
"bootstrap": "^5.3.3",
"browser-cookies": "^1.2.0",
"browser-md5-file": "^1.1.1",
"compare-versions": "^6.0.0-rc.2",
"core-js": "^3.32.1",
"core-js": "^3.37.0",
"dialog-polyfill": "^0.5.6",
"dom-autoscroller": "^2.3.4",
"dompurify": "^3.0.5",
"dompurify": "^3.1.0",
"downloadjs": "^1.4.7",
"dragula": "^3.7.3",
"eventemitter3": "^5.0.1",
Expand All @@ -108,20 +114,20 @@
"lodash": "^4.17.21",
"moment": "^2.29.4",
"moment-timezone": "^0.5.44",
"quill": "^2.0.0-dev.3",
"quill": "^2.0.0-rc.4",
"signature_pad": "^4.2.0",
"string-hash": "^1.1.3",
"tippy.js": "^6.3.7",
"uuid": "^9.0.0",
"vanilla-picker": "^2.12.3"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.60.1",
"@typescript-eslint/parser": "^5.60.1",
"ace-builds": "1.23.4",
"@typescript-eslint/eslint-plugin": "^7.6.0",
"@typescript-eslint/parser": "^7.6.0",
"ace-builds": "1.33.0",
"async-limiter": "^2.0.0",
"bootstrap-icons": "^1.10.5",
"bootswatch": "^5.3.0",
"bootswatch": "^5.3.3",
"browser-env": "^3.3.0",
"chai": "^4.3.7",
"chance": "^1.1.9",
Expand All @@ -130,7 +136,7 @@
"esdoc": "^1.1.0",
"esdoc-ecmascript-proposal-plugin": "^1.0.0",
"esdoc-standard-plugin": "^1.0.0",
"eslint": "^8.43.0",
"eslint": "^8.57.0",
"eslint-config-formio": "^1.1.4",
"fetch-mock": "^9.11.0",
"file-loader": "^6.2.0",
Expand All @@ -148,32 +154,31 @@
"gulp-sync": "^0.1.4",
"gulp-watch": "^5.0.1",
"hoek": "^6.1.3",
"jquery": "^3.7.0",
"jsdom": "^22.1.0",
"jsdom": "22.1.0",
"jsdom-global": "^3.0.2",
"karma": "^6.4.2",
"karma": "^6.4.3",
"karma-chrome-launcher": "^3.2.0",
"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"karma-phantomjs-launcher": "^1.0.4",
"karma-webpack": "^5.0.0",
"mocha": "^10.2.0",
"karma-webpack": "^5.0.1",
"mocha": "^10.3.0",
"mock-local-storage": "^1.1.24",
"natives": "^1.1.6",
"power-assert": "^1.6.1",
"pre-commit": "^1.2.2",
"pretty": "^2.0.0",
"pygments-css": "^1.0.0",
"raw-loader": "^4.0.2",
"sass": "^1.63.6",
"sass": "^1.74.1",
"shortcut-buttons-flatpickr": "^0.4.0",
"sinon": "^15.2.0",
"sinon": "^17.0.1",
"string-replace-loader": "^3.1.0",
"ts-loader": "^9.4.4",
"ts-node": "^10.9.1",
"typescript": "~5.0.4",
"webpack": "^5.88.1",
"webpack-bundle-analyzer": "^4.9.0",
"typescript": "5.3.2",
"webpack": "^5.90.3",
"webpack-bundle-analyzer": "^4.10.2",
"webpack-cli": "^5.1.1",
"webpack-node-externals": "^3.0.0",
"webpack-stream": "^7.0.0",
Expand Down
Loading

0 comments on commit f96bf94

Please sign in to comment.