bpmn-io / form-js

View and visually edit JSON-based forms.
https://bpmn.io/toolkit/form-js/
Other
414 stars 107 forks source link

Provide API to the editor to decide which form field/component types are exposed in form creation #237

Open christian-konrad opened 2 years ago

christian-konrad commented 2 years ago

Is your feature request related to a problem? Please describe

There are 2 current problems:

  1. When we add new components, properties and behaviour changes to form.js, we can only benefit from it in newest execution targets (tasklist). For older ones, the Modeler needs to check for compatibility. Currently, the approach is to throw linting errors for the respective unsupported items, but the items are still exposed in the properties panel and component selection, which leads to frustration when using an updated Modeler for a older task list version (you place a component on your form just to be told by the Modeler that this is not ok).

  2. To allow extensibility in the core of form.js, the embedding client needs control over which form fields can be used when editing and creating forms. This allows a stable set of exposed form field types even when new field types are added to form.js.

This enables innovating on form.js by adding new components without the risk of exposing unwanted components to already embedding clients on a version bump.

Describe the solution you'd like

On form editor instantiation, the developer should be able to provide a whitelist of form field/component types that should be exposed in the editor.

On target version select in the Desktop Modeler, the whitelist should be updated accordingly to the embedded forms editor and it should refresh accordingly, only exposing supported components and properties. (A strategy to resolve components in the schema that needs to be removed or only hidden if you downgrade the execution version is still TBD in terms of UX and compatibility)

Something like this naive approach (better some adapter to get components and props per target version)

const formEditor = new FormEditor({
  container: document.querySelector('#form-editor'),
  availableComponentTypes: ['textfield', 'number',  'checkbox', ...],
  availableProperties: ...
});

and some way to notify the formEditor of whilelist changes

nikku commented 2 years ago

Is this a duplicate of https://github.com/bpmn-io/form-js/issues/123, if not, what differentiates it?

dfulgham commented 2 years ago

@christian-konrad Got this working so far, but what do you want it to do if the imported Schema contains not valid components?

const formEditor = formEditorRef.current = new FormEditor({
      renderer: {
        compact: true
      },
      availableComponentTypes:['button','select']
    });

in the example below I only passed in 'button' and 'select'

image

Also created types:


/** from types.d.ts */

export type ComponentTypes =
  'checkbox'|
  'number'|
  'radio'|
  'select'|
  'textfield'|
  'text' |
  'button'

/** from FormEditor,js */

/**
 * @typedef { import('../../../types').ComponentTypes} ComponentTypes
 */

@typedef { {
 *   properties: FormEditorProperties,
 *   availableComponentTypes: ComponentTypes[]
 *   schema: Schema
 * } } State

/** from Pallete.js */

/**
 * @typedef { import('../../../types').ComponentTypes} ComponentTypes
 *
 * @typedef { {label:string,type:ComponentTypes}} PalletComponents
 */

/**
 * @type { PalletComponents[] } types
 */
const types = [
  {
    label: 'Text Field',
    type: 'textfield'
  },
  {
    label: 'Number',
    type: 'number'
....
]
christian-konrad commented 2 years ago

123

This issue essentially proposes a component white-list as a way to describe a stable API for form.js users/embedders (like Camunda Modeler). This will be an enabler to add an extension API and for extensions themselves. It does not describe the feature request to add extensions.

christian-konrad commented 2 years ago

@christian-konrad Got this working so far, but what do you want it to do if the imported Schema contains not valid components?

Wow, this has been quick!

This is a great question. Either the components will be shown (and can not be removed) or aren't shown and a warning alert or similar is thrown on opening a schema with components not matching the whitelist. For rendering (not editing) the forms only, it should throw an exception in my opinion.

The expected behavior may depend heavily on the embedding client. We will think about it in a quiet moment. In the middle of April we will gather forces to think about a suitable extension API.

Maybe the best would be to throw an exception on rendering both the editor and the form and let the client decide to force-render.

nikku commented 2 years ago

I do see this issue as a simple way to filter what extensions to support. I don't think it is needed short or mid-term.

What I do think is needed is a general way to extend form-js, to supply custom elements (editing) but also serialize them into the schema and support them during viewing.

We'll take your feature request for "file upload" (https://github.com/bpmn-io/form-js/issues/222) and the related PR (https://github.com/bpmn-io/form-js/pull/231) as a reference. If we do our homework as we create an extension mechanism adding such component shall be easily possible.

However we'll not be able to follow up on this in the next weeks. As @christian-konrad mentioned we'll put this on our potential investment topics in the mid-term.

If you want to work on your end to sketch how an extension mechanism for form-js could look like: We're happy to start the discussion and review your contribution. We won't be able to jump on this topic ourselves for the time being.

dfulgham commented 2 years ago

Well I'm definitely eager to assist with this project, I'm working on a a client front end integration to Camunda and have gone down the road of Form.IO and some other form libraries because we need the file handling aspect of the form. They introduce too much overhead and complexity. And since we are utilizing Camunda it would be very nice to have forms that will also integrate well with the Workflow Engine using form.js

some other options that would be nice, is perhaps adding to the API the ability to decide on how to handle components that are not in the allowed list, i.e. unavailableComponentAction: 'readonly'|'remove'|'allow' etc. Read only would allow changing the position in the form but not the component properties, remove would strip the component from schema, and allow would allow editing of the component but obviously not the ability to add it back if removed.

For rendering (not editing) the forms only, it should throw an exception in my opinion.

I don't this this would be possible as the form schema wouldn't inform the Viewer that their are any issues (edit: unless you mean the formeditor view, in this case i agree it should indicate the issue), obviously if the components just are not available in the Viewer version that is being used, they should error correctly indicating that a component is not available.
Would it be beneficial to include a form-js schema version in the JSON file? and error on mismatch between editor and viewer?

dfulgham commented 2 years ago

some other options that would be nice, is perhaps adding to the API the ability to decide on how to handle components that are not in the allowed list, i.e. unavailableComponentAction: 'readonly'|'remove'|'allow' etc. Read only would allow changing the position in the form but not the component properties, remove would strip the component from schema, and allow would allow editing of the component but obviously not the ability to add it back if removed.

Readonly action:

image

Allow Action:

image

Remove Action (Default, and Camunda Action)

image
nikku commented 2 years ago

Well I'm definitely eager to assist with this project.

Thanks, sounds great!

I'm not sure if we're 100% aligned on the path forward. What I'd start with is #123, an extension mechanism that allows a field such as file upload to be provided.

As a follow up, I'd look into this issue (i.e. given all supported (also extension provided) form components, which are the onces I want my user to see).

As part of #123 we obviously need to solve what you've sketched in https://github.com/bpmn-io/form-js/issues/237#issuecomment-1072018424. If you follow my line of thought (and we add a generic extension mechanism) then the form-js (editor or viewer) will sooner or later encounter elements in a schema that it just does not know. In this case we have only limited options:

Hope this helps.

To sum up my proposal: Sketch a solution for #123 (be able to define file upload as an extension). Follow up with everything else.

Does that make sense?

dfulgham commented 2 years ago

@nikku Are you suggesting the ability for developers to add a form component via the new Form() or new FormEditor() properties, like passing an array of Component Objects into the constructor for example?

Or do you simply want a mechanism to make it easier to integrate new components into the code base? (ie. reorganize the code base and move components (editor and viewer combined) into their own lerna package?

nikku commented 2 years ago

@nikku Are you suggesting the ability for developers to add a form component via the new Form() or new FormEditor() properties, like passing an array of Component Objects into the constructor for example?

I suggest exactly this.

dfulgham commented 2 years ago

@nikku see https://github.com/bpmn-io/form-js/issues/123#issuecomment-1073227631

christian-konrad commented 2 years ago

@nikku I updated the issue description as this is something beneficial for us if we now aim to add more components and properties that are not supported by previous Camunda execution engines

nikku commented 2 years ago

Makes sense as a limitation feature. We should not hide ship and hide experimental fields this way. Moving to backlog.