Skip to main content

Creating React form application

In order to start creating your own Form application, we first need to make sure we register a Webpack entrypoint in your Python UI package's webpack.py script.

Webpack registration

This file has a similar role to usual package.json, here you specify a path to the JS module handling form-related tasks, and any NPM dependencies it might need to be installed.

# my_app_ui/theme/webpack.py

from invenio_assets.webpack import WebpackThemeBundle

theme = WebpackThemeBundle(
__name__,
"assets",
default="semantic-ui",
themes={
"semantic-ui": dict(
entry={
# ...
"my_app_ui_forms": "./js/my_app_ui/forms/index.js",
},
dependencies={
"some-cool-form-input": "^1.0.0",
},
#...
)
}
)

The entrypoint name my_app_ui_forms must correspond to what you used in your Jinja template.

Form app initialization

Now we need to provide an index.js file in a path according to the Webpack entrypoint. According to the example above, we will place it at /my_app_ui/theme/assets/semantic-ui/js/my_app_ui/forms/index.js.

Notice there are few shortcuts that Invenio makes for you when resolving Webpack entrypoints. It automaticaly prepends the assets folder and the current theme of semantic-ui to the relative paths.

Your index.js might look as simple as this

import { createFormAppInit } from "@js/oarepo_ui/forms";
import { DepositForm } from "./DepositForm"

export const overriddenComponents = {
"FormApp.layout": DepositForm,
};

createFormAppInit(overriddenComponents);

As described in Overview, this initializes form application and provides it with any configuration and user overriden components (currenty only a layout of a form can be overriden).

Form app layout component

In the example above, we specified that a custom DepositForm component will be used as a form app layout. Here is an example of such compnonent.

// DepositForm.jsx
import React from "react";
import { useFormConfig, useOnSubmit, submitContextType } from "@js/oarepo_ui";
import { BaseForm } from "react-invenio-forms";
import { Container } from "semantic-ui-react";
import { MyRecordValidationSchema } from "./MyRecordValidationSchema";


export const DepositForm = () => {
const { record, formConfig } = useFormConfig();
const context = formConfig.createUrl? submitContextType.create : submitContextType.update
const { onSubmit, submitError } = useOnSubmit({
apiUrl: formConfig.createUrl || formConfig.updateUrl,
context: context,
onSubmitSuccess: (result) => {
console.log('Saved!', result)
}
onSubmitError: (error) => {
console.log('Submit failed!', error)
}
});

return (
<Container>
<BaseForm
onSubmit={onSubmit}
formik={{
initialValues: record,
validationSchema: MyRecordValidationSchema,
validateOnChange: false,
validateOnBlur: false,
enableReinitialize: true,
}}
>
<pre>Add your deposit form fields here 👇</pre>
</BaseForm>
</Container>
);
};

Even though this example uses Formik for form state management and React-Invenio-Forms component library, you should be able to provide your very own Form implementation here without this dependencies.