bpmn-io / form-js Goto Github PK
View Code? Open in Web Editor NEWView and visually edit JSON-based forms.
Home Page: https://bpmn.io/toolkit/form-js/
License: Other
View and visually edit JSON-based forms.
Home Page: https://bpmn.io/toolkit/form-js/
License: Other
Through tab and section control, we can layout many fields in the form,
Is your feature request related to a problem? Please describe
As a Platform Tasklist user, I want to trigger an escalation or error event from my form.
Describe the solution you'd like
Allow custom Events to be thrown within custom elements using the event emitter.
The implementation details could be handled in custom elements which can be used in the Platform, even if Zeebe does not support this functionality yet.
Describe alternatives you've considered
Additional context
This is a nice to have and is not required for the first iteration.
Docs related to the functionality in Camunda Platform:
Rest API:
https://docs.camunda.org/manual/7.14/reference/rest/task/post-bpmn-escalation/
https://docs.camunda.org/manual/7.14/reference/rest/task/post-bpmn-error/
Embedded Forms:
https://docs.camunda.org/manual/7.14/reference/embedded-forms/controls/bpmn-buttons/
The current structure of both the form viewer and editor doesn't allow any extensibility and makes testing features in isolation impossible.
┌──────────────────────────┐ ┌───────────────────────────┐
│ API │ │ API │
│ │ │ │
│ #createForm │ │ #createFormEditor │
│ │ │ │
└──────────────────────────┘ └───────────────────────────┘
┌──────────────────────────┐ ┌───────────────────────────┐
│ form-js-viewer │ │ form-js-editor │
│ │ │ │
│ ┌──────────────────────┐ │ │ ┌───────────────────────┐ │
│ │Rendering │ │ │ │Rendering │ │
│ └──────────────────────┘ │ │ └───────────────────────┘ │
│ │ │ │
│ ┌──────────────────────┐ │ │ ┌───────────────────────┐ │
│ │Event Bus │ │ │ │Event Bus │ │
│ └──────────────────────┘ │ Contains │ └───────────────────────┘ │
│ ├───────────►│ │
│ ┌──────────────────────┐ │ │ ┌───────────────────────┐ │
│ │Element Registry │ │ │ │Element Registry │ │
│ └──────────────────────┘ │ │ └───────────────────────┘ │
│ │ │ │
│ ┌──────────────────────┐ │ │ ┌───────────────────────┐ │
│ │Data Mapping │ │ │ │Data Mapping │ │
│ └──────────────────────┘ │ │ └───────────────────────┘ │
│ │ │ │
└──────────────────────────┘ │ ┌───────────────────────┐ │
│ │Modeling │ │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ │
│ │Palette │ │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ │
│ │Properties Panel │ │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ │
│ │Selection │ │
│ └───────────────────────┘ │
│ │
└───────────────────────────┘
With the diagram-js
-based bpmn-js
and the table-js
-based dmn-js
we have solved these issues using dependency injection. Separating the features into individual DI services makes extensibility and testability possible.
Steps
diagram-js
using didi
Additional questions:
form-js-viewer
and form-js-editor
packages into a single package? bpmn-js
doesn't contain multiple packages and the multiple packages in dmn-js are entirely different.Follow-up issues:
What should we do?
We are going to have a single library called @bpmn-io/form-js
that exports createForm
and createFormEditor
.
Example:
import { createForm, createFormEditor } from "@bpmn-io/form-js";
Therefore we need to
@bpmn-io/form-js
bundles @bpmn-io/form-js-viewer
& @bpmn-io/form-js-editor
)attachTo
and detach
APIDescribe the Bug
When the content of an pre-filled textbox was deleted, the submit event does not contain the form field in data
.
Background: In Platform Tasklist, the Process Variable will not be updated in this scenario. Because we pass all process variables into the form, we cannot reliably check whether a variable was deleted by the absence of it.
Steps to Reproduce
Example:
const schema = {
"type": "default",
"components": [
{
"key": "creditor",
"label": "Creditor",
"type": "textfield"
},
{
"key": "button1",
"label": "Submit",
"type": "button"
}
]
};
const data = {creditor: "foobar"};
const form = createForm({
schema,
data,
container: document.querySelector('#form')
});
form.on('submit', (event) => {
console.log(event.data, event.errors);
});
Expected Behavior
The result should include the field with an empty string.
{creditor: ""}
More generally speaking, every displayed field should yield a result in the submitted form, cf. #54 (comment).
Environment
Related to https://jira.camunda.com/browse/CAM-13333
What should we do?
UMD is the most simple way to integrate the viewer into a website. Provide such distribution.
Why should we do it?
For ease of use and quick demos, we should provide such distribution.
Describe the Bug
HTML inputs are not connected to their labels. The for
and name
are missing and therefore accessibility is not given.
<label class="fjs-form-field-label">Invoice Number</label>
<input class="fjs-input" type="text" disabled="">
Expected Behavior
Expected HTML:
<label for="foo" class="fjs-form-field-label">Invoice Number</label>
<input name="foo" class="fjs-input" type="text" disabled="">
Environment
Is your feature request related to a problem? Please describe
Currently, there is no undo/redo in the form editor.
Describe the solution you'd like
A command stack should be added to the form editor to add undo/redo. I'd argue that the form viewer doesn't need this feature since we do not want to mess with native undo/redo when using a form.
Is your feature request related to a problem? Please describe
Not a problem or a feature request but more of a general question. Are there any plans to support non-web based rendering platforms (like react-native) while still using the core module from form-js ? I think that would be quite useful for people wanting to embed camunda forms in native mobile apps.
Describe the solution you'd like
Looking at the code, it seems 'core' and 'rendering' are already separate modules and definitely looks like a step in the right direction. I feet it would be even better if we moved the 'rendering' module to a separate project and called it something like 'form-js-renderer-web'. That will allow creating other projects like 'form-js-renderer-react', 'form-js-renderer-react-native', 'form-js-renderer-vuejs' etc. It will also avoid accidental web/dom related code seeping into the core module.
Describe alternatives you've considered
Too early to think of alternatives but if I have to, I would probably expose the web based form-js UI on some website and render in my react-native app via webview. This is what we're planning to do in the interim with another library (formiojs) till form-js is ready for adoption.
Additional context
N/A
Is your feature request related to a problem? Please describe
On Zeebe Tasklist if we try to complete a Task that was already completed we receive the updated Task and update the values on the form. To do that we need a way to update the values after the first render.
Describe the solution you'd like
const form = createForm({
// ...
});
form.setData(newData);
// or
form.setProperty('data', newData)
Additional context
Currently I'm using form.setState({ data })
for that, but I assume that it's not public API and not very wise to use it on long term
What should we do?
Prefix the CSS classes with camunda-forms
(or similar) to prevent name clashes with other UI libraries
Why should we do it?
In the Camunda Platform webapps, we use Bootstrap which also uses the column
CSS class for layouting with absolute positioning. This results in all form elements displayed ontop of each other:
The Platform overrides the CSS from bootstrap for camunda-forms, so it's currently fine for us. It would be nicer to have no name clashes :)
Is your feature request related to a problem? Please describe
When importing a schema that contains unknown form fields (form fields that cannot be rendered) a fallback is rendered instead telling the user that the form field cannot be rendered. From an API point of view the user has no way of knowing whether the entire form was rendered successfully.
Describe the solution you'd like
This issue was discussed by @andreasgeier, @philippfromme and @volkergersabeck.
We should do two things:
The API would change from
import { createForm, createFormEditor } from 'form-js';
...
const form = createForm({ container, schema, data });
// Was the form rendered successfully?!
to
import Form, { FormEditor } from 'form-js'; // Viewer is the default export, editor is available, too
...
const form = new Form({ container }):
const { errors, warnings } = await form.importSchema(schema, data); // data is optional
if (errors) {
// Handle errors
}
if (warnings.length) {
// Handle warnings
}
Doesn't need alignment with UX for now, reasonable default is okay.
Additional context
Code freeze of the Camunda Platform that would depend on these changes is March 25th 2021.
Related to #10
Is your feature request related to a problem? Please describe
In Camunda Cockpit, we want to render a preview of the deployed form in the deployment view. As the schema is just a .json
file, we need a way to differentiate between camunda forms and 'regular' JSON.
Describe the solution you'd like
When importing an invalid form, throw an error.
This way, we can react to errors with try-catch blocks:
try {
const form = createForm({
container,
schema: questionableJson,
data
});
} catch (e) {
// Hide the Container
}
Describe alternatives you've considered
I see 2 alternatives which both use validation before invoking createForm
display: "form"
from formsIO.Additional context
Cockpit Deployment view with Form preview:
id
property to formsid
property can be edited trough properties panelAs this property is required only in the context of the Camunda product stack we need to think about whether this should be added to the core or as an extension.
Related to camunda/camunda-modeler#2295.
Will be fixed via #137.
Is your feature request related to a problem? Please describe
In my form I'd like to have the ability to edit list elements.
Example: A list of invoices that are uploaded, a list of items to be double checked.
Describe the solution you'd like
Describe alternatives you've considered
People need to contribute list elements as custom components.
Additional context
Supported by form.io
via the datagrid
component.
Describe the Bug
There exists a number of minor styling issues for markdown rendering:
<br />
tags are inserted, preventing a proper paragraph layout ➡️ users should be able to structure text in multiple paragraphs (#93)Steps to Reproduce
Expected Behavior
See above.
Context
For reference a screenshot highlighting above issues:
For reference a screenshot with a HTML page:
When creating a new properties panel the new entry (respectively its first input) should be focused.
This feature might be available once we refactor the properties panel to use the new properties panel as a basis.
Related to #56.
What should we do?
Add eslint-plugin-react-hooks.
Why should we do it?
Enforces best practices and prevents unexpected behavior.
Similar bpmn-js and its properties panel we should support i18n.
Is your feature request related to a problem? Please describe
On Zeebe a user might have a variable of up to 4MB and because of that there might be cases on Zeebe Tasklist that a task has multiple big variables as initial values on the form which might cause the request to take too long to load or timeout.
To solve that we want to load only a truncated value of each requested variable and only load the full value of the variable when the user focuses on the field
Describe the solution you'd like
Create a new event that's dispatched when the user focuses on the field:
/**
* @type { (event: 'focus', callback: (state: { field: {name: string, type: 'textfield' | 'number' | ... } } ) => void) => void }
*/
form.on('focus', ({ field }) => {
// we can filter by field type so we don't fetch unnecessary variables, like boolean variables for example
if(field.type === 'textfield') {
request(field.name)
}
})
Context
The idea is to use this feature along with #39 and #67 to implement lazy loading of data.
Is your feature request related to a problem? Please describe
form-js viewer instances need to handle form documents created with different form-js editor versions. To achieve that we've settled down on a feature-based compatibility strategy. This means: Older viewers open form documents as long as they only contain supported features. Newer viewers open older form documents (with the exception of major breaking changes).
Describe the solution you'd like
Describe alternatives you've considered
Use the schemaVersion
to detect compatibility. We did decide to explicitly not go that route. However, the schemaVersion
as well as the schemaVersion
baked into the form-js viewer instance can be used to provide a clear error message to the user.
Additional context
Part of versioning strategy, specifically the form-js@x+2
release.
The properties panel has no built-in validation. It should prevent any invalid key (duplicates as well as empty ones).
key
of a fieldkey
of another field to the same valuekey
s are preventedkey
s are preventedform-js
editor shall be valid, i.e. importable again in editor and viewer instances.What should we do?
Form schema documents should be clearly identified from within the document. That identification should include:
Why should we do it?
Allows us to evolve the schema, over time.
Describe the Bug
Only values for form elements that are enabled should be submitted with the form. This is standard in web development.
Steps to Reproduce
import { createForm } from 'camunda-forms';
const schema = {
"components": [
{
"label": "Creditor",
"key": "creditor",
"type": "textfield",
"disabled": true
}
]
};
const form = createForm({
container: document.createElement('div')
schema,
data: {
creditor: 'Lisa'
}
});
Expected Behavior
const {
data
} = form.submit();
expect(Object.keys(data)).to.be.empty;
Environment
Any.
There is currently no way for the user to discover that the static text form field supports Markdown, other than simply trying it out.
We should either
or
Related to #56.
Describe the Bug
When Validation max-length
is set and unset again in the editor, the value persists in the json. This leads the viewer to render a validation error.
Steps to Reproduce
12
){
"type": "default",
"components": [
{
"key": "myVariable",
"label": "Tell me something",
"type": "textfield",
"description": "e.g. say 'Hello, World!'",
"validate": {
"required": false,
"minLength": "",
"maxLength": ""
}
}
]
}
Expected Behavior
maxLength
should not trigger a validation errorAlso please consider: since the existing version of the viewer is already included in platform 7.15 (afaik), we might additionally do the following change:
maxLength
in the propertiesPanel should remove the maxLength
property in the json.Environment
Camunda Modeler Nightly as of 01.04.2021
Is your feature request related to a problem? Please describe
External UI elements should also reflect the current state of the Form, such as dirty or invalid.
In our case, we have a "save" button which stores the current form content in the local storage. This button should only be enabled when the form was modified.
The "Complete" button should be disabled when the input is invalid.
Describe the solution you'd like
Emit an event when FormCore#changed
is triggered that can be subscribed to with form.on('changed', evt =>{})
.
If the event also contains the form validation/errors, we could also disable the submit button for invalid forms.
Describe alternatives you've considered
Have events for 'dirty' or 'invalid'. I don't think this fits in the current design, as a submit is always possible, e.g. never 'invalid'.
Do nothing, external buttons are always enabled and check the validity using the programmatic submit once pressed. This is how we currently implement it and it works fine.
Additional context
This is a nice to have
Is your feature request related to a problem? Please describe
In some environments displayed form data may be to large to load with the form. In such environments lazy loading, i.e. once a form field gets visible or is focused could be a viable option.
Describe the solution you'd like
Describe alternatives you've considered
Is your feature request related to a problem? Please describe
Instances of a form are not reusable the way instances of bpmn-js are. Furthermore, there is no way of distinguishing between instantiation and import errors. The API should be adjusted to separate instantiation and import.
Describe the solution you'd like
Since we have two pieces of data that make up a form the API could look something like this:
import { Form } from '@bpmn-io/form-js';
...
const form = new Form({ container: document });
const {
errors: jsonErrors,
warnings: jsonWarnings
} = await form.importJSON(json, data);
const {
errors: dataErrors,
warnings: dataWarnings
} = await form.importData(data);
The shorthand of using createForm
can be kept to ensure backwards compatibility.
Introduce a new type of field that exists only for layout purposes.
This involves
Questions to answer: Is this going to be a single component, or are there dedicated components for horizontal ("columns") and vertical ("fieldset" #258) stacking?
What should we do?
Implement the form editor designs provided by @andreasgeier.
Is your feature request related to a problem? Please describe
In order to lazy load values for inputs we need to show a loading state on the inputs in case the request takes too long. For more context read #60
Describe the solution you'd like
The library could adopt the concept of a field state and make it possible for the user to change the state of each field:
form.setFieldState('fieldName', 'loading'); // states could be extended to other things like readOnly, etc
// or
form.setField('fieldName', { state: 'loading' });
Describe alternatives you've considered
We could also have a more generic approach like on Bootstrap input addons
const loadingSpinnerElement = createLoadingSpinner();
form.setFieldSuffixAddon('fieldName', loadingSpinnerElement);
// or
form.setField('fieldName', { suffixAddon: loadingSpinnerElement });
What is inside
What is not inside (yet)
versionTag
property to formsversionTag
property can be edited trough properties panelAs this property is required only in the context of the Camunda product stack we need to think about whether this should be added to the core or as an extension.
Related to camunda/camunda-modeler#2295.
Describe the Bug
Using the text component: Every time the form view is refreshed, the textarea loses focus so I can't continue typing my text/markdown and need to click the textarea again and again.
Steps to Reproduce
Expected Behavior
Textarea should keep the focus and text cursor position while refreshing the form view so that I can continue typing text.
Environment
Describe the Bug
In cases where the form has no empty space on the bottom right corner the logo might cover fields
Steps to Reproduce
Create a form schema with only 1 column, 1 or more fields and no submit/reset buttons
Expected Behavior
The logo should never cover any field or button
Environment
What should we do?
It should be possible to toggle a preview mode in the form editor. That mode allows users to simulate the form.
To be clarified: Scope of simulation (including input data and output data or not).
Why should we do it?
This helps people to understand what is needed to integrate the form.
Is your feature request related to a problem? Please describe
On Zeebe Tasklist we would like to hide the bpmn.io logo and submit button (in favor of our own button).
Currently I'm doing that programmatically selecting the classes, but every time the form rerenders the elements disappear and I have to remove them again, which causes them to be visible for a split second.
Describe the solution you'd like
const form = createForm({
properties: {
hiddenElements: ['logo', 'submitButton'],
},
});
Describe alternatives you've considered
Don't provide any API to hide the elements but prevent them from being added again on every rerender
Is your feature request related to a problem? Please describe
In order to provide some feedback to the user by disabling the Task completion button after he/she claims a Task I would like to programmatically validated the form or to be able to retrieve the form errors even though they're not yet visible to the user.
Describe the solution you'd like
const form = createForm({
// ..
});
/*
Option 1 - Programmatically validating the form:
Calling this method triggers all validation functions
and show the errors on the form
*/
form.validate();
// or
/*
Option 2 - Retrieving the errors:
The getState() method returns the validation errors
even if the errors are not yet visible to the user
*/
const {errors} = form.getState();
Describe alternatives you've considered
Do nothing and just wait for the user to change the form or trigger the submission
Additional context
As we talked on this meeting this the reason for these features might not be desirable and I need to sync with the design team, but I'm creating the issue to register the discussion.
Describe the Bug
The Required checkbox in the properties panel isn't working. It's never checked.
Environment
Fields to be added:
Schema:
{
"key": "foo",
"label": "Foo",
"type": "number"
}
Schema:
{
"key": "foo",
"label": "Foo",
"type": "checkbox"
}
Schema:
{
"key": "foo",
"label": "Foo",
"type": "radio",
"values": [
{
"label": "Foo",
"value": "foo"
},
{
"label": "Bar",
"value": "bar"
}
]
}
Schema:
{
"key": "foo",
"label": "Foo",
"type": "select",
"values": [
{
"label": "Foo",
"value": "foo"
},
{
"label": "Bar",
"value": "bar"
}
]
}
Schema:
{
"text": "# Hello World\nThis is __very__ important.",
"type": "text"
}
Is your feature request related to a problem? Please describe
In my form I'd like to show, hide, enable or disable elements based on the state of other elements.
Describe the solution you'd like
Additional context
Handled via a conditional
section in form.io
.
Related to SUPPORT-12025
Related to https://github.com/camunda/product-hub/issues/56
What should we do?
Depends on #19
Following up the refactoring of the viewer import we should:
Describe the Bug
Steps to Reproduce
npm i @bpmn-io/[email protected]
require("@bpmn-io/form-js").createForm
Expected Behavior
Notes
Loading works fine when including it as module: import { createForm } from '@bpmn-io/form-js';
Only importing the form-js-viewer
also works require('@bpmn-io/form-js-viewer').createForm
This is not blocking our release, we just need the viewer, which works
Environment
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.