/
How to create new questionary component - frontend

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

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 defaultRenderer for this field for the default behaviour. If you want to exclude your question from review completely you can set renderers to undefined

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.