@cfl/table-forms v1.1.0
Table Forms JavaScript
This package provides the necessary components to render forms from the True North Web Forms Connector.
The JavaScript comes in two flavours:
- a library that defines a function that renders the form, intended for use standalone on an existing web site
- a module that provides React components, which can be used to add the web form to an existing React app
Versioning and compatibility
This package is compatible with True North Web Forms Connector 1.47.0.
If there is no newer version of this package, later versions of the Connector may safely be assumed to be compatible. If there is a newer version of this package, consult that version's README.md for further information.
JSON data compatible with this package will start with:
{
"$schema": "https://schemas.corefiling.com/tnc/0.5.0/webforms.schema.json",
Rendering a form using JavaScript
This section describes how to add a form to an existing web page.
Make dist/bundle.js
and dist/bundle.css
available at some convenient URL (there are non-minified versions of the bundles named bundle.dev.js
and bundle.dev.css
that may be useful during debugging). In this example let’s assume https://cdn.example.com/table-forms/bundle.js
.
In the head of the HTML document add a link to the stylesheet:
<link rel="stylesheet" href="https://cdn.example.com/table-forms/bundle.css" />
In the body of the HTML document include the outer element of the form and submit button:
<div id="form-placeholder">Loading …</div>
At the end of the document, reference the JavaScript assets for React and for this project:
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<script crossorigin src="https://cdn.example.com/table-forms/bundle.js"></script>
There are various ways to make the JSON artefacts describing the table and form state available. For example it might be fetched client-side using XMLHttpRequest
or fetch
APIs. Another approach suitable to server-side rendered pages is to retrieved the JSON server-side and embed it as script element(s):
<script type="application/json" id="tableSpec">
{ … JSON data … }
</script>
And at the end the glue code that replaces the contents of the placeholder element with the form and supplies a routine for dealing with submission.
<script>
const spec = JSON.parse(document.getElementById('tableSpec').innerText);
const context = { … };
tableForm.tableForm({
taxonomy: spec.taxonomy,
tables: spec.tables,
values: values, // Optional: Values tha replace the defaults (e.g., from partially filled in form).
context: context, // Optional
element: document.getElementById('form-placeholder'),
onSubmit: handleSubmit,
onSave: handleSave, // Optional: Function for saving partially filled in form.
});
function handleSubmit(submission) {
return fetch('/path/to/submissions', {
method: 'POST',
body: JSON.stringify(submission),
…
});
}
</script>
The context object supplies aspects of the facts that are not part of the form itself, and looks like this:
{
entity: { scheme: 'http://standards.iso.org/iso/17442', identifier: 'TEST0WEB0FORMS000082' },
currency: 'USD',
period: { start: '2021-01-01', end: '2021-12-31' },
decimals: 'INF', // Or a number of decimal places
}
Replacing only part of a form
This section describes how to handle the situation where the form
element needs to include application-specific elements.
The JavaScript is largely similar except there needs to be a table-placeholder
element somewhere in the form, and the glue code is different.
<form onsubmit="handleSubmit" id="the-form">
…
<div id="table-placeholder-1">Loading …</div>
…
<input type="submit">
</form>
A table from the spec is added with code like this:
tableForm.tableFormItems({
element: document.getElementById('table-form-placeholder-' + i),
table: spec.tables[i], // One of the tables from the spec.
values: values.tables[i], // Optional: Values tha replace the defaults (e.g., from partially filled in form).
name: 't' + i, // Optional: Names this table uniquely within the scope of the form.
});
The JSON object to submit to the backend is extracted from the form data using the function tableForm.submissionFromForm
:
function handleSubmit(e) {
e.preventDefault();
const submission = tableForm.submissionFromForm(namedTables, document.getElementByuId('the-form'), spec.taxonomy, context);
… send to backend …
}
The parameters are:
Parameter | Description |
---|---|
namedTables | An array of objects with keys name and table , corresponding to earlier call(s) to tableForm.tableFormItems . |
formElement | HTMLFormElement instance that the table forms are part of. If this call is being made in the submit event handler of the form, this will be e.target . |
taxonomy | Information about the taxonomy, obtained from the web-form-data spec. |
context | Information required to turn the values in to facts, described above. |
The context can be acquired from some external source or could conceivably be made part of the form.
Using the component in a React app
If the customer web app is written in React it can use the components directly. Start with installing it:
yarn add --dev @cfl/table-forms # or npm install …
Now, having acquired the JSON through some method or other, instantiate the TableForm
component:
import { TableForm } from '@cfl/table-forms';
<TableForm
taxonomy={spec.taxonomy}
context={…}
table={spec.tables}
defaultValues={values.tables}
className="… optional CSS classes …"
style={… optional CSS directives …}
onSubmit={submission => …}
onSave={submission => …}
onCancel={() => …}
/>
This generates the form with Submit button. Save and Cancel buttons are added if the corresponding event handler is supplied.
For more fine-grained control of the layout of the form, there is the TableFormItems
component. This is used nested within a form
element.
It will normally be used as a controlled component, with values
and onChange
properties:
<TableFormItems {...spec.tables[i]} name={`table${i}`} values={values} onChange={newValues => setValues(newValues)} />
To use it uncontrolled, instead optionally supply defaultValues
:
<TableFormItems {...spec.tables[i]} name={`table${i}`} defaultValues={spec.values.tables[i]} />
This displays the form, but with its state held within the DOM elements, extracting the user data will require using submissionFromForm
.
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago