×
Back to book

C#Bot Custom Form Question

How to create, enable, and use a custom form question.

When using forms there will be some cases where the existing question tiles will not support all the features that are needed. Because of this you can add a custom question tile to the application and define your own logic inside of it.

Building a Custom Text Area Question

In this tutorial we are going to be building a custom text area question for a form. All of the questions inside of Reactbot are stored in the clientside/src/Forms/Questions directory. The first step will be to make a new file called TextAreaQuestionTile.tsx there.

Building the Question Tile

All question tiles have the following structure

import * as React from 'react';
import { computed } from "mobx";
import { observer } from 'mobx-react';
import { IQuestionTile, IQuestionTileProps, QuestionTileOptionsProps } from './QuestionTile';
import { TextField } from 'Views/Components/TextBox/TextBox';
import { CheckDisplayConditions } from "../Conditions/ConditionUtils"
import { QuestionType } from 'Forms/Schema/Question';

// The options sidebar for this question
@observer
export class TextAreaQuestionTileOptions extends React.Component<QuestionTileOptionsProps> {
    public render() {
        return (
            <TextField model={this.props.question} modelProperty="title" label="Question Name" />
        );
    }
}

// Any custom props to be passed to the component
export interface ITextAreaQuestionTileProps<T> extends IQuestionTileProps<T> {}

@observer
export class TextAreaQuestionTile<T> extends React.Component<ITextAreaQuestionTileProps<T>> implements IQuestionTile {
    // The display name for the UI of the question tile
    static displayName = 'Text Area';
    // The type of the question that is stored in the form data
    static questionType: QuestionType = 'textarea';
    // The options menu to use when displayed in the sidebar
    static optionsMenu = TextAreaQuestionTileOptions;

    // Used for checking if any custom show logic
    // Currently there is no way to set show logic in the UI
    @computed
    public get isConditionSatisfied() {
        if (this.props.showConditions !== undefined && !this.props.disableShowConditions) {
            return this.props.showConditions.every(condition => CheckDisplayConditions(condition, this.props.model, this.props.schema));
        }
        return true;
    };

    public render() {
        if (this.isConditionSatisfied) {
            // TODO: Render the question here
        } else {
            return null
        }
    }
}

Once this code is placed in the file all that needs to be done is render the question content of the new custom question.

It is important to note the 3 static properties that are defined at the top of the main class. These are used to configure the name and options of the new text area tile.

// The display name for the UI of the question tile
static displayName = 'Text Area';
// The type of the question that is stored in the form data
static questionType: QuestionType = 'textarea';
// The options menu to use when displayed in the sidebar
static optionsMenu = TextAreaQuestionTileOptions;

In the section of the render function that says // TODO: Render the question here replace it with the following content.

return (
    <>
        <p className="question__content">{this.props.title}</p>
        <TextArea
            model={this.props.model}
            modelProperty={this.props.id}
            label={this.props.title}
            labelVisible={false}
            isReadOnly={this.props.isReadOnly} />
    </>
);

This will render a title for the question that is configured in the sidebar as well as a text area. The options for the text area will bind it to the submission model with the id of the question as the key. An invisible label is provided for accessibility reasons as it can be accessed by screen readers. The isReadOnly options is so a view mode can be implemented.

In addition ensure that you add the following import to the top of the file so you can use the text area as well.

import { TextArea } from 'Views/Components/TextArea/TextArea';

Registering the Question Tile

For the application to be able to view the question tile it will need to be registered for the application to read.

In clientside/src/Forms/Questions/QuestionUtils there shall be the following block of code

...

import { CheckboxQuestionTile } from 'Forms/Questions/CheckboxQuestionTile';
import { FormStatementTile } from "Forms/Questions/FormStatementTile";
// % protected region % [Add any further imports here] off begin
// % protected region % [Add any further imports here] end

export const questions = [
    TextQuestionTile,
    NumberQuestionTile,
    CheckboxQuestionTile,
    FormStatementTile,
    // % protected region % [Add any extra question types here] off begin
    // % protected region % [Add any extra question types here] end
];

...

Enable both of the protected regions and place the following contents in each of them

// % protected region % [Add any further imports here] on begin
import { TextAreaQuestionTile } from 'Forms/Questions/TextAreaQuestionTile';
// % protected region % [Add any further imports here] end

and

// % protected region % [Add any extra question types here] on begin
TextAreaQuestionTile,
// % protected region % [Add any extra question types here] end

This will import our new question and register it to the application.

Adding the Type for the Question Tile

The last thing that is needed to be done is to add the type into the schema for the JSON form data. This is located in clientside/src/Forms/Schema/Question.d.ts. In this file there should be the following code block

export type QuestionType = "text"
    | "number" 
    | "checkbox"
    | "statement"
    // % protected region % [Add extra question types here] off begin
    // % protected region % [Add extra question types here] end
    ;

All that needs to be done here is to enable the protected region and put in the type of our new tile.

// % protected region % [Add extra question types here] on begin
| "textarea"
// % protected region % [Add extra question types here] end

Viewing the New Question

Now the code is done we can now view the new question tile. To do this go to the form designer for any form and try to add a new question.

As you can see there is now a text area question listed with all of the built in ones. After selecting the item in the dropdown we can see it appear on the form designer.