-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update "Example form.js" document #212
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,9 +5,22 @@ | |
Use this example `form.js` file to build a basic form. For more information about `form.js`, see "[Creating a form config file](creating-a-form-config-file.md)." | ||
|
||
```js | ||
{ | ||
// Because pages must be unique across all chapters, it's safer to store them in an object | ||
const formPages = { | ||
pageOne: 'pageOne' | ||
} | ||
|
||
// Since field IDs are repeated in the form config and must be unique throughout the form, | ||
// it's safer and more convenient to store them in an object | ||
const formFields = { | ||
fieldOne: 'fieldOne', | ||
viewFieldTwo: 'view:fieldTwo', | ||
viewGroup: 'view:artificialGroup' | ||
} | ||
|
||
const formConfig = { | ||
// Prefix string to add to the path for each page. | ||
urlPrefix: '', | ||
urlPrefix: '/', | ||
|
||
// The introduction page component. To exclude an introduction page, remove this component. | ||
introduction: IntroductionComponent, | ||
|
@@ -16,95 +29,107 @@ Use this example `form.js` file to build a basic form. For more information abou | |
confirmation: ConfirmationComponent, | ||
|
||
// The prefix for Google Analytics events that are sent for different form actions. | ||
trackingPrefix: '', | ||
trackingPrefix: 'unique-ga-id-', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a PR in #196 that moves this out to the app, in which case |
||
|
||
// The title of the form, rendered on all pages. | ||
title: '', | ||
|
||
// The subtitle of the form, usually the form number. The subtitle is rendered on all pages when there's also a title. | ||
subTitle: '', | ||
|
||
// Schema definitions that can be referenced on any page. These are added to each page's schema in the reducer code, so that you don't have to put all of the common fields in the definitions property in each page schema. For more information on definitions, see schema.definitions below. | ||
// Schema definitions that can be referenced on any page. These are added to each page's schema in the reducer code, so that you don't have to put all of the common fields in the definitions property in each page schema. For more information on definitions, see `schema.definitions` below. | ||
defaultDefinitions: {}, | ||
|
||
// When a user begins completing a pre-filled form, this function is called after data migrations are run for pre-filled data in order to make necessary updates to the data or form schema ahead of time. | ||
prefillTransformer: (pages, formData, metadata ) => { pages, formData, metadata } | ||
prefillTransformer: (pages, formData, metadata ) => { pages, formData, metadata }, | ||
|
||
// The object that contains the configuration for each chapter. Each property is the key for a chapter. | ||
// The object that contains the configuration for each chapter. | ||
chapters: { | ||
// Each property is the key for a chapter. | ||
chapterOne: { | ||
|
||
// The title of the chapter. | ||
title: '', | ||
// The title of the chapter. Rendered near the top of the page, under the segmented controller | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would change |
||
title: '', | ||
|
||
// The object that contains the pages in each chapter. Each property is the key for a page, and should be unique across chapters. | ||
pages: { | ||
// The object that contains the pages in each chapter. | ||
pages: { | ||
// Each property is the key for a page, and should be unique across chapters. | ||
[formPages.pageOne]: { | ||
|
||
// The URL for the page. | ||
path: 'some-path', | ||
// The URL for the page. Must be unique across all pages in all chapters. | ||
path: 'some-path', | ||
|
||
// The title of the page that renders on the review page. | ||
title: '', | ||
// This can also be a function that receives the current data as a parameter. | ||
title: formData => `A title for ${formData.thing}`, | ||
|
||
// Any initial data that should be set for the form. | ||
initialData: { | ||
field1: 'Default string' | ||
}, | ||
|
||
// Specifies that a page will turn its schema into a page for each item in an array, such as an array of children with a page | ||
// for each child. The schema/uiSchema for this type of page should be built as usual for an array field. | ||
showPagePerItem: true, | ||
// The path to the array. | ||
arrayPath: 'children', | ||
// Items in the array that should not have a page. | ||
itemFilter: () => true, | ||
// You must specify a path with an :index parameter. | ||
path: 'some-path/:index', | ||
|
||
// The JSON schema object for the page, following the JSON Schema format. | ||
schema: { | ||
type: 'object', | ||
// A schema's properties refer to definitions. For example: | ||
// "homePhone": { "$ref": "#/definitions/phone" } | ||
// In the configuration file, the definition for `phone` must be added into definitions in order to be parsed correctly and added to `homePhone`. | ||
definitions: {}, | ||
properties: { | ||
field1: { | ||
type: 'string' | ||
}, | ||
// Fields of type `string`, `boolean`, `number`, and `array` that begin with `view:` are excluded from data that's sent to | ||
// the server. Instead, their children are merged into the parent object and sent to the server. Use these to exclude fields | ||
// from being sent to the server, such as a question that's only used to reveal other questions, or to group related | ||
// questions together to be conditionally revealed that aren't in an object in the schema. | ||
'view:field2': { | ||
type: 'string' | ||
// The title of the page that renders on the review page when this chapter is expanded. | ||
title: '', | ||
// This can also be a function that receives the current data as a parameter: | ||
// title: formData => `A title for ${formData.thing}`, | ||
|
||
// Any initial data that should be set for the form. | ||
initialData: { | ||
[formFields.fieldOne]: 'Default string' | ||
}, | ||
'view:artificialGroup'{ | ||
|
||
// Specifies that a page will turn its schema into a page for each item in an array, such as an array of children with a page | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should add a header comment that clarifies that the following group of things are used for array fields only. The additional |
||
// for each child. The schema/uiSchema for this type of page should be built as usual for an array field. | ||
showPagePerItem: true, | ||
// The path to the array. | ||
arrayPath: 'children', | ||
// Items in the array that should not have a page. | ||
itemFilter: () => true, | ||
// You must specify a path with an :index parameter. | ||
path: 'some-path/:index', | ||
|
||
// The JSON schema object for the page, following the JSON Schema format. | ||
schema: { | ||
type: 'object', | ||
// A schema's properties refer to definitions. For example: | ||
// "homePhone": { "$ref": "#/definitions/phone" } | ||
// In the configuration file, the definition for `phone` must be added into definitions in order to be parsed correctly and added to `homePhone`. | ||
definitions: {}, | ||
// Set an array of fields on this page that are required | ||
required: [ | ||
[formFields.fieldOne] | ||
] | ||
properties: { | ||
// `view:artificialGroup` is flattened. `subField1` and `subField2` are siblings of `field1` when sent to the API. | ||
subField1: { | ||
[formFields.fieldOne]: { | ||
type: 'string' | ||
}, | ||
subField2: { | ||
type: 'boolean' | ||
// Fields of type `string`, `boolean`, `number`, and `array` that begin with `view:` are excluded from data that's sent to | ||
// the server. Instead, their children are merged into the parent object and sent to the server. Use these to exclude fields | ||
// from being sent to the server, such as a question that's only used to reveal other questions, or to group related | ||
// questions together to be conditionally revealed that aren't in an object in the schema. | ||
[formFields.viewFieldTwo]: { | ||
type: 'string' | ||
}, | ||
[formFields.viewGroup]: { | ||
type: 'object', | ||
properties: { | ||
// `view:artificialGroup` is flattened. `subField1` and `subField2` are siblings of `[formFields.fieldOne]` when sent to the API. | ||
subField1: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we want to stick with putting all fields in an object, |
||
type: 'string' | ||
}, | ||
subField2: { | ||
type: 'boolean' | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
}, | ||
|
||
// See "About the `schema` and `uiSchema` objects" below. | ||
uiSchema: { | ||
'ui:title': 'My form', | ||
field1: { | ||
'ui:title': 'My field' | ||
// See "About the `schema` and `uiSchema` objects" below. | ||
uiSchema: { | ||
'ui:title': 'My form', | ||
[formFields.fieldOne]: { | ||
'ui:title': 'My field' | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
export default formConfig; | ||
``` | ||
[About the `schema` and `uiSchema` objects](./about-the-schema-and-uischema-objects.md) | ||
[Back to *Building a Form*](./README.md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with the diagnosis that repeating names across all these objects is confusing and error prone. Ideally we should be grouping most of this information in a single object, rather than using the field name as a key to unite far-flung objects. That's related to design changes though, so perhaps this is the best we can do with the current
formConfig
design.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an interesting idea. I agree with what @dmethvin-gov said, that we might be making further design changes to the form config that would change how some of this works. However, in general this change seems a bit prescriptive. It's not necessary for the library to work to put the field names in a separate object, it just potentially makes it less error prone. But I'm not sure if that recommendation belongs in the scope of this library, or should we just leave it up to individual developers to write their form config in whatever way makes most sense to them? If this is the new way Vets.gov is going to be writing their form configs, should this prescription belong in the Vets.gov codebase instead of here?