How to create new questionary component - frontend
This document will guide you through creating a new component for questionary in user office software. Whenever the example code is provided it will be provided for a component called Interval
You should start by reading the other part of this guide which talks about creating backend functionality. How to create new questionary component - backend
Update FieldConfig GraphQL fragment
Let's start by adding new section in FieldConfig fragment to the src/graphql/template/fragment.fieldConfig.graphql
This should correspond to fields you added in the backend earlier
Example
... on IntervalConfig {
units
small_label
required
tooltip
}
Add a new folder for your component
Create a new folder in src/components/questionary/questionaryComponents where to keep all component files. e.g. Interval
Create Definition
In the folder, you just created, create a new file e.g. IntervalDefinition.ts
This file will be your component definition and it conforms with the QuestionaryComponentDefinition
interface
This definition file is used as a facade single entry point from the questionary engine to the component.
Here are the field names and description the definition has
Property | Type | Description |
---|---|---|
dataType | DataType | The enum value from DataType |
name | string | A human readable name |
questionaryComponent | (props: BasicComponentProps) => JSX.Element | null | The main component that is rendered in the questionary and visible by user (more on this below) |
questionForm | () => FormComponent<Question> | A form used in administration panel to define a question (more on this below) |
questionTemplateRelationForm | () => FormComponent<QuestionTemplateRelation> | A form used in administration panel to define a question template relation (more on that below) |
renderers | {questionRenderer: (props: { question: Question;}) => JSX.Element | null; answerRenderer: (props: { answer: Answer }) => JSX.Element | null;} | null | Rendering of the question and answer that is displayed in the review, you can import and use the |
createYupValidationSchema | ((field: Answer) => object) | null | Yup validation rules for the answer |
readonly | boolean; | if true then no answer will be produced. This could be set to true for special or decorative components |
creatable | boolean; | if true then the question can be added to a questionary. Could be set to false for special purpose components |
icon | JSX.Element | The icon for component |
After specifying the component definition you need to register it by adding the reference in the registry
array variable in src/components/questionary/QuestionaryComponentRegistry.tsx
const registry = [
booleanDefinition,
dateDefinition,
embellishmentDefinition,
...
intervalDefinition,
];
Create QuestionaryComponent
This is the main component shown in the questionary to the user to collect an answer.
To communicate to the outside world the questionary component accepts props of type BasicComponentProps
interface BasicComponentProps {
answer: Answer;
onComplete: (evt: React.ChangeEvent<any>, newValue: any) => void;
touched: any;
errors: any;
}
the answer
is the object containing information about the answer, including the question. This data type is generated on the server and is located in SDK in the client
call onComplete
when the user enters the answer. This could be finishing entering text or selecting an option in the dropdown, etc. After calling onComplete
the whole form will be re-rendered.
touched and errors are properties coming from Formik, so you can use these to display errors or perform UI tweaks. You can read more about it here <Formik /> | Formik
Create QuestionForm
This is the form used in the administration panel to render the form that configures questions.
Essentially component can be anything you want.
To communicate to the outside world the QuestionForm accepts props of type FormProps<Question>
interface FormProps<ValueObjectType> {
field: ValueObjectType;
template: Template;
dispatch: React.Dispatch<Event>;
closeMe: () => any;
}
the field is of type Question which contains data like question text, datatype, etc...
template
an object containing whole template
dispatch
could be used for more advanced communication to the questionary engine. To save the question dispatch event
dispatch({
type: EventType.UPDATE_QUESTION_REQUESTED,
payload: {
field: { ...props.question, ...form },
},
}
closeMe - request window to be closed
You can have anything you like here but there are few React components to make constructing this form much easier.
QuestionFormShell
a wrapper that wraps your content in formik form,
includes form buttons
dispatches save event when saving
closes the window when done
accepts yup validation form for your fields that are specified as children
TitledContainer
visually groups multiple related inputs together
accept the label as a parameter
Create QuestionTemplateRelationForm
NOTE: This form is very similar to QuestionForm and there is a plan to reduce the duplicated code between the two
QuestionTemplateRelationForm is used in the administration panel to render the form that configures question related to the template.
This form purpose is:
override the default values that were specified in the Question.
specify a dependency on other questions if needed. See FormikUICustomDependencySelector
Check your component
By adding your component to the component registry in the step above component should show up in the template editor under the Add question
menu. It will use icon and name from component definition to render the menu item.