How to create new questionary component - backend
This document will guide you though creating new questionary component. After finishing this, you want to go and check the frontend part that's required for creating a component. How to create new questionary component - frontend
Add new Enum to the DataType
Let's start by opening src/models/Template.ts the DataType enum and add your new DataType. For this example we will call our DataType INTERVAL
export enum DataType {
BOOLEAN = 'BOOLEAN',
DATE = 'DATE',
EMBELLISHMENT = 'EMBELLISHMENT',
...
INTERVAL = 'INTERVAL',
}
Create a new file for the component
Create new file under src/models/questionTypes e.g. IntervalDefinition.ts
Here add the definition of the component. The definition should contain an object conforming to the interface Question residing in src/models/questionTypes/QuestionRegistry.ts
Example
export const intervalDefinition: Question = {
dataType: DataType.INTERVAL,
getDefaultAnswer: field => {
return {
min: 0,
max: 0,
unit: null,
};
},
validate: (
field: QuestionTemplateRelation,
value: { min: number; max: number; unit: string | null }
) => {
...
},
createBlankConfig: (): IntervalConfig => {
const config = new IntervalConfig();
config.small_label = '';
config.required = false;
config.tooltip = '';
config.property = '';
config.units = [];
return config;
},
};
Here are the fields that must be defined:
Property | Type | Description |
---|---|---|
dataType | DataType | The enum value from DataType |
validate | (field: QuestionTemplateRelation, value: any) => boolean | Perform validation rules before persisting data into the database |
createBlankConfig | () => any | Function that returns config initial values |
getDefaultAnswer | (field: QuestionTemplateRelation) => any | Returns the answer value for the question that is not answered yet |
After creating component definition, register your component by adding a new entry to the registry array in src/models/questionTypes/QuestionRegistry.ts
const registry = [
booleanDefinition,
dateDefinition,
embellishmentDefinition,
...
intervalDefinition,
];
Add new data type in the database
Create new SQL database patch in db_patches
DO
$$
BEGIN
IF register_patch('AddIntervalDataType.sql', 'firstnamelastname', 'Adding new question type', 'xxxx-xx-xx') THEN
BEGIN
INSERT INTO question_datatypes VALUES('INTERVAL');
END;
END IF;
END;
$$
LANGUAGE plpgsql;
Add new FieldConfig
Your component will probably have unique config parameters that you want the administrator to configure, and that can vary from question to question. To define a config add a new type in src/resolvers/types/FieldConfig.ts.
For example: If we want to be able to configure units
and property
field for our component, then it could look something like this
@ObjectType()
export class IntervalConfig extends ConfigBase {
@Field(() => [String], { nullable: true })
units: string[] | null;
@Field(() => String)
property: string;
}
Note that decorators in this class are not specific to the questionary component but rather TypeGraphQL annotations.
Next, we need to add this config to the FieldConfig GraphQL UnionType, which comes as a requirement for TypeGraphQL
export const FieldConfigType = createUnionType({
name: 'FieldConfig',
types: () => [
BooleanConfig,
DateConfig,
EmbellishmentConfig,
FileUploadConfig,
...
IntervalConfig,
],
});
Next steps
Now when the backend part is done, go ahead and implement frontend part and also add support for your new type in the user-office-factory: