Skip to main content
Canvas Editor provides a comprehensive set of form controls for creating interactive documents. Controls can collect user input, validate data, and maintain state within the document.

Control Types

Checkbox

Multi-select options with checkboxes

Radio

Single-select options with radio buttons

Text Input

Free-form text entry fields

Date Picker

Calendar-based date selection

Select

Dropdown selection lists

Number

Numeric input with optional calculator

Checkbox Controls

Create checkbox controls with multiple value options:
import Editor, { ControlType, ElementType } from '@hufe921/canvas-editor'

const editor = new Editor(container, {
  main: [{ value: '' }]
})

// Insert checkbox control
editor.command.executeInsertElementList([
  {
    type: 'control',
    value: '',
    control: {
      type: ControlType.CHECKBOX,
      code: 'checkbox_1',
      value: null,
      valueSets: [
        { value: 'Option 1', code: 'opt1' },
        { value: 'Option 2', code: 'opt2' },
        { value: 'Option 3', code: 'opt3' }
      ]
    }
  }
])

Checkbox Configuration

{
  type: 'control',
  value: '',
  control: {
    type: ControlType.CHECKBOX,
    code: 'preferences',
    value: null,
    flexDirection: FlexDirection.COLUMN,
    valueSets: [
      { value: 'Email notifications', code: 'email' },
      { value: 'SMS notifications', code: 'sms' },
      { value: 'Push notifications', code: 'push' }
    ]
  }
}

Radio Controls

Create radio button groups for single-selection:
editor.command.executeInsertElementList([
  {
    type: 'control',
    value: '',
    control: {
      type: ControlType.RADIO,
      code: 'gender',
      value: null,
      valueSets: [
        { value: 'Male', code: 'm' },
        { value: 'Female', code: 'f' },
        { value: 'Other', code: 'o' }
      ]
    }
  }
])
Radio controls automatically enforce single selection - selecting a new option deselects the previous one.

Text Input Controls

Create text input fields:
editor.command.executeInsertElementList([
  {
    type: 'control',
    value: '',
    control: {
      type: ControlType.TEXT,
      code: 'full_name',
      value: null,
      placeholder: 'Enter your full name',
      minWidth: 200,
      prefix: '[',
      postfix: ']'
    }
  }
])

Text Control Options

{
  type: ControlType.TEXT,
  code: 'username',
  value: null,
  placeholder: 'Username'
}

Date Picker Controls

Create date selection controls:
editor.command.executeInsertElementList([
  {
    type: 'control',
    value: '',
    control: {
      type: ControlType.DATE,
      code: 'birth_date',
      value: null,
      dateFormat: 'YYYY-MM-DD',
      placeholder: 'Select date'
    }
  }
])
The date picker displays a calendar interface when activated, allowing users to select dates visually.

Select Controls

Create dropdown selection controls:
editor.command.executeInsertElementList([
  {
    type: 'control',
    value: '',
    control: {
      type: ControlType.SELECT,
      code: 'country',
      value: null,
      placeholder: 'Select country',
      valueSets: [
        { value: 'United States', code: 'us' },
        { value: 'Canada', code: 'ca' },
        { value: 'United Kingdom', code: 'uk' },
        { value: 'Australia', code: 'au' }
      ]
    }
  }
])

Multi-Select

{
  type: ControlType.SELECT,
  code: 'languages',
  value: null,
  isMultiSelect: true,
  multiSelectDelimiter: ', ',
  valueSets: [
    { value: 'English', code: 'en' },
    { value: 'Spanish', code: 'es' },
    { value: 'French', code: 'fr' },
    { value: 'German', code: 'de' }
  ]
}

Number Controls

Create numeric input with optional calculator:
editor.command.executeInsertElementList([
  {
    type: 'control',
    value: '',
    control: {
      type: ControlType.NUMBER,
      code: 'quantity',
      value: null,
      placeholder: '0'
    }
  }
])
{
  type: ControlType.NUMBER,
  code: 'age',
  value: null
}

Setting Control Values

Set Single Control Value

// Set control value by code
editor.command.executeSetControlValue({
  code: 'full_name',
  value: 'John Doe'
})

// Set by control ID
editor.command.executeSetControlValue({
  id: 'control_uuid',
  value: 'Jane Smith'
})

Set Multiple Control Values

editor.command.executeSetControlValueList([
  { code: 'full_name', value: 'John Doe' },
  { code: 'email', value: '[email protected]' },
  { code: 'age', value: '30' }
])

Getting Control Values

// Get all control values
const allControls = editor.command.getControlValue()

// Get specific control by code
const nameControl = editor.command.getControlValue({ code: 'full_name' })

// Get controls by group
const groupControls = editor.command.getControlValue({ groupId: 'personal_info' })

Control Value Structure

// Returned value structure
[
  {
    type: ControlType.TEXT,
    code: 'full_name',
    value: 'John Doe',        // Current value as string
    innerText: 'John Doe',    // Display text
    zone: EditorZone.MAIN,    // Location in document
    elementList: [...]        // Full element data
  }
]

Control Properties

Update control properties:
// Update single control properties
editor.command.executeSetControlProperties({
  code: 'email',
  properties: {
    placeholder: 'Enter email address',
    underline: true,
    disabled: false
  }
})

// Update multiple controls
editor.command.executeSetControlPropertiesList([
  {
    code: 'first_name',
    properties: { disabled: true }
  },
  {
    code: 'last_name',
    properties: { disabled: true }
  }
])

Control Rules

Apply rules to control behavior:
editor.command.executeInsertElementList([
  {
    type: 'control',
    value: '',
    control: {
      type: ControlType.TEXT,
      code: 'readonly_field',
      value: null,
      disabled: true,        // Disable editing
      deletable: false,      // Prevent deletion
      pasteDisabled: true,   // Disable paste
      hide: false            // Control visibility
    }
  }
])
Controls with deletable: false cannot be removed by users, ensuring required fields remain in the document.

Control Highlighting

Highlight controls based on content:
editor.command.executeSetControlHighlight([
  {
    ruleList: [
      {
        keyword: 'error',
        backgroundColor: '#FFE5E5',
        alpha: 0.5
      },
      {
        keyword: 'warning',
        backgroundColor: '#FFF3CD',
        alpha: 0.5
      }
    ],
    conceptId: 'validation_field'
  }
])
// Jump to next control
editor.command.executeJumpControl()

// Locate specific control
editor.command.executeLocationControl({
  position: LocationPosition.FIRST  // or LAST
})

Removing Controls

// Remove control by code
editor.command.executeRemoveControl({ code: 'temp_field' })

// Remove control by ID
editor.command.executeRemoveControl({ id: 'control_uuid' })

Complete Example

Create a form with multiple control types:
import Editor, { ControlType, FlexDirection } from '@hufe921/canvas-editor'

const container = document.querySelector('.editor')
const editor = new Editor(container, {
  main: [
    { value: 'User Registration Form\n\n', size: 20, bold: true },
    { value: 'Full Name: ' },
    {
      type: 'control',
      value: '',
      control: {
        type: ControlType.TEXT,
        code: 'full_name',
        value: null,
        placeholder: 'Enter full name',
        minWidth: 200
      }
    },
    { value: '\n\nGender: ' },
    {
      type: 'control',
      value: '',
      control: {
        type: ControlType.RADIO,
        code: 'gender',
        value: null,
        valueSets: [
          { value: 'Male', code: 'm' },
          { value: 'Female', code: 'f' }
        ]
      }
    },
    { value: '\n\nInterests: ' },
    {
      type: 'control',
      value: '',
      control: {
        type: ControlType.CHECKBOX,
        code: 'interests',
        value: null,
        flexDirection: FlexDirection.ROW,
        valueSets: [
          { value: 'Sports', code: 'sports' },
          { value: 'Music', code: 'music' },
          { value: 'Reading', code: 'reading' }
        ]
      }
    },
    { value: '\n\nBirth Date: ' },
    {
      type: 'control',
      value: '',
      control: {
        type: ControlType.DATE,
        code: 'birth_date',
        value: null,
        dateFormat: 'YYYY-MM-DD'
      }
    }
  ]
})

// Pre-fill form
editor.command.executeSetControlValueList([
  { code: 'full_name', value: 'Jane Doe' },
  { code: 'gender', value: 'f' },
  { code: 'birth_date', value: '1990-01-15' }
])

// Get all form values
function getFormData() {
  const controls = editor.command.getControlValue()
  const formData = {}
  
  controls.forEach(control => {
    formData[control.code] = control.value
  })
  
  console.log('Form Data:', formData)
  return formData
}

Best Practices

  • Group related controls together
  • Provide clear labels for all controls
  • Use appropriate control types for data (dates use date picker, not text)
  • Set reasonable min/max constraints for checkboxes
  • Use control rules to enforce required fields
  • Implement highlighting for validation errors
  • Provide clear placeholder text as guidance
  • Disable controls when appropriate (calculated fields, etc.)
  • Use consistent styling across controls
  • Provide visual feedback for control states
  • Group related options logically
  • Consider tab order for keyboard navigation

Text Formatting

Style control labels and content

Print & Export

Export filled forms to PDF

Build docs developers (and LLMs) love