Skip to content

How to create new questionnaire component (FRONTEND)

Jekabs Karklins edited this page Feb 7, 2023 · 5 revisions

This document will guide you through creating a new component for the questionnaire 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. https://github.com/UserOfficeProject/user-office-core/wiki/How-to-create-new-questionnaire-component-(BACKEND)

Update FieldConfig GraphQL fragment

Let's start by adding a new section in FieldConfig fragment to the src/graphql/template/fragment.fieldConfig.graphql This should correspond to the 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 a 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 questionnaire engine to the component.

Here are the field names and descriptions 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 questionnaire and visible by the user (more on this below)
questionForm () => FormComponent A form used in the administration panel to define a question (more on this below)
questionTemplateRelationForm () => FormComponent A form used in the administration panel to define a question template relation (more on that below)
renderers Renderers 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 behavior. If you want to exclude your question from review completely you can set renderers to undefined
createYupValidationSchema CreateYupValidation | null Yup validation rules for the answer
getYupInitialValue GetYupInitialValue; Initial value for Yup validation framework
searchCriteriaComponent FC UI component that controls filter for searching questionnaire by 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 questionnaire. Could be set to false for special-purpose components
icon JSX.Element The icon for the 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 questionnaire for the user to collect an answer. To communicate to the outside world the questionnaire 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 https://formik.org/docs/api/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

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 the whole template dispatch could be used for more advanced communication to the questionnaire 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 questions related to the template. This form's 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 the icon and name from the component definition to render the menu item.

Next steps

  • Backend
    Learn more on how to implement the backend side of the questionnaire component
  • Validation library
    It is recommended to implement a validation schema for your new component in the validation library.
  • Questionnaire ERD
    Learn more about the underlying data structure of the Questionnaire