Skip to content

Form System Quick Reference

🎯 Visual Overview: Frontend ↔ Engine Connection

APPLICATION-FRONTEND                    CREATIVE-ENGINE
═══════════════════════                ═══════════════════

📁 Form Block Structure                 📁 Form Rendering
├── FormConfiguration.vue              ├── CreativeFormBlock.vue
├── FormInputConfiguration.vue         ├── FormInputBase.vue
└── Form/configs/                      └── components/
    ├── TextInputConfiguration.vue         ├── FormTextInput.vue
    ├── EmailInputConfiguration.vue        ├── FormEmailInput.vue
    ├── PhoneInputConfiguration.vue        ├── FormPhoneInput.vue
    └── [Type]InputConfiguration.vue       └── Form[Type]Input.vue

📁 Data Layer                          📁 Data Layer
├── constants/inputTypes.ts            ├── utils/constants.ts (BLOCKS)
├── Blocks/data/types.ts               ├── payload-v2/index.ts
└── Blocks/data/defaults.ts            └── stores/formStore.ts

🔗 File Relationships Map

1. Block Registration

Frontend: constants/blocks.ts          Engine: utils/constants.ts
├── BLOCKS.FORM = 'formProperties'  →  ├── BLOCKS.FORM = 'formProperties'
└── BLOCKS.FORM_INPUT = 'formInput' →  └── BLOCKS.FORM_INPUT = 'formInput'

2. Type Definitions

Frontend: Blocks/data/types.ts         Engine: payload-v2/index.ts
├── FormProperties interface        →  ├── FormProperties interface
├── FormInputProperties interface   →  ├── FormInputProperties interface
└── Input type unions               →  └── CreativeBlocks interface

3. Default Values

Frontend: Blocks/data/defaults.ts      Engine: stores/formStore.ts
├── formDefaults object            →   ├── getFormProperties()
├── formInputDefaults object       →   ├── validateInput()
└── blockDefaults map              →   └── Default validation rules

4. Input Type System

Frontend: constants/inputTypes.ts      Engine: components/Form[Type]Input.vue
├── INPUT_TYPES constant           →   ├── Individual input components
├── getInputTypeDefinition()       →   ├── Type-specific validation
└── Short codes (T, E, P, etc.)    →   └── Rendering logic per type

⚡ Quick Development Workflow

Adding New Input Type

  1. Frontend → Add to inputTypes.ts INPUT_TYPES
  2. Frontend → Create [Type]InputConfiguration.vue
  3. Frontend → Register in FormInputConfiguration.vue
  4. Engine → Create Form[Type]Input.vue component
  5. Engine → Add validation in formStore.ts
  6. Engine → Register in FormInputBase.vue

Styling Form Elements

  1. Frontend → Update configuration components
  2. Engine → Update style computed properties
  3. Both → Follow style system architecture patterns

Debugging Form Issues

  1. Data Flow: Frontend Vuex → Engine DataStore (iframe)
  2. Real-time: Changes save but need iframe reload
  3. Validation: Check formStore.ts validation logic
  4. Rendering: Check individual Form[Type]Input components

🎨 Style System Integration

Form Block Styling

Frontend: FormConfiguration.vue        Engine: CreativeFormBlock.vue
├── Uses configurationLogic mixin   →  ├── Direct DataStore access
├── Border/Background sections      →  ├── Computed styles property
└── updateValue() pattern           →  └── Template style binding

Form Input Styling

Frontend: [Type]InputConfiguration     Engine: Form[Type]Input.vue
├── Individual style sections       →  ├── StyleAndClassNameMixin
├── Type-specific properties        →  ├── Input-specific styling
└── Validation configuration        →  └── Error state handling

🔧 Key Patterns

Data Updates

  • Frontend: updateValue(property, value) via mixin
  • Engine: Direct DataStore property access
  • Communication: Iframe postMessage (limited real-time)

Subblock Management

  • Pattern: getSubBlocks(parentBlock) utility
  • Sorting: By order property
  • Identification: blockName + blockType + parent

Type-Aware Numbering

  • Per-type counters: T1, T2, E1, E2, P1, P2
  • Persistent: Survives reordering/deletion
  • Display: "Text Input #1", "Email Input #2"

🔄 Modern Vue Syntax Guidelines

Both Application-Frontend and Creative-Engine use Vue 2.7.16 with TypeScript and Vite, which supports modern Vue 3-like syntax while maintaining Vue 2 compatibility.

Template Syntax

vue
<!-- ✅ CORRECT: Modern Vue 2.7 syntax (no 'this') -->
<template>
  <div>
    <h2>{{ title }}</h2>
    <div :class="{ active: isActive }">
      {{ message }}
    </div>
    <button @click="handleClick">
      {{ buttonText }}
    </button>
  </div>
</template>

<!-- ❌ AVOID: Legacy Vue 2 syntax (with 'this') -->
<template>
  <div>
    <h2>{{ this.title }}</h2>
    <div :class="{ active: this.isActive }">
      {{ this.message }}
    </div>
    <button @click="this.handleClick">
      {{ this.buttonText }}
    </button>
  </div>
</template>

Script Section

js
// Script section MUST still use 'this'
export default {
  computed: {
    formattedTitle() {
      return this.title.toUpperCase(); // 'this' required
    },
  },
  methods: {
    handleClick() {
      this.isActive = !this.isActive; // 'this' required
    },
  },
};

Component Setup

ts
// Modern defineComponent style
import { defineComponent } from 'vue';

export default defineComponent({
  name: 'FormInput',
  emits: ['update', 'validate'], // Explicitly declare emitted events
  props: {
    value: { type: String, default: '' },
  },
  // Rest of component...
});

Key Benefits

  1. Future Compatibility: Closer to Vue 3 composition API style
  2. Cleaner Templates: Less verbose without this in templates
  3. Emits Declaration: Better documentation of component events
  4. TypeScript Support: Improved type checking with defineComponent

All new form system components should follow this modern syntax pattern.

🚀 Implementation Strategy

Phases of Development

Phase 1: Foundation    Phase 2: Components    Phase 3: Integration
├── BaseInput.vue     ├── TextInput.vue      ├── Dynamic Loading
├── ValidationHelpers ├── NumberInput.vue    ├── Component Map
└── Common Props      └── DateInput.vue      └── Cleanup

Phase 1: Foundation Components

  1. Create validation helpers for each input type in validationHelpers.ts

    typescript
    export const validateTextInput = (value, rules) => { ... }
    export const validateNumberInput = (value, rules) => { ... }
  2. Build BaseInputConfiguration component with:

    • Common input properties (label, placeholder)
    • Shared styling sections (background, border, layout)
    • Font settings for both label and input
    • Base template structure with slots for type-specific content

Phase 2: Type-Specific Components

Each component focuses solely on its unique validation requirements:

ComponentFileValidation Fields
TextInputConfigurationTextInputConfiguration.vueminLength, maxLength, pattern
NumberInputConfigurationNumberInputConfiguration.vuemin, max, step
DateInputConfigurationDateInputConfiguration.vuemin (date), max (date)
SelectInputConfigurationSelectInputConfiguration.vueoptions list

Phase 3: Integration

Update main container component to use dynamic loading:

vue
<component :is="inputConfigurationComponent" :block-data="blockData" :path="path" />

<script>
computed: {
  inputConfigurationComponent() {
    const type = this.blockData.type || 'text'
    const componentMap = {
      'text': 'TextInputConfiguration',
      'number': 'NumberInputConfiguration',
      // ... other mappings
    }
    return componentMap[type] || 'TextInputConfiguration'
  }
}
</script>

Migration Strategy

  1. Incremental Approach: Start with text inputs (most common)
  2. Maintain Compatibility: Ensure all existing form configurations work
  3. Progressive Rollout: Add one input type at a time
  4. Testing Focus: Unit test each component before integration

Plan

Phase 1: Decide what should be included and excluded

  • [x] Remove success message from form block and keep on child level

  • [x] Remove error message from block and keep on child level

  • [x] Remove success and error message from defaults in AF

  • [x] Remove success and error message from defaults in CE

  • [x] Make imports in @FormInputConfiguration.vue correct

  • [x] Make imports in @BaseInputConfiguration.vue correct

  • [x] Make imports in same order as in @AddBlockTool.vue

  • [x] Reorder imports and components object correct in order of appearance

  • [] Make the @FormConfiguration.vue styling work

    • [] Layout
      • [x] Alignment
        • [x] Connect FlexAlignmentSection horizontalAlignment/verticalAlignment to form block flexDirection/alignItems/justifyContent props
        • [x] Ensure alignment values map correctly to CSS flex properties in CreativeFormBlock.vue
      • [x] Offset
        • [x] Connect PositionSection x/y coordinates to form block position styles
        • [x] Update position type (relative/absolute) handling in CreativeFormBlock styles
      • [x] Padding
        • [x] Properly bind PaddingSection values to form block padding styles
        • [x] Ensure padding values with units (px/%) are correctly processed in CreativeFormBlock
      • [x] Size (Add this to the form block)
        • [x] Add SizeSection component with width/height bindings to FormConfiguration.vue
        • [x] Ensure size values are properly applied in CreativeFormBlock's computed styles
      • [x] Gap
        • [x] Connect GapSection value to form block's gap style property
        • [x] Add support for both px and % units for gap in CreativeFormBlock.vue
      • [] Border: set default as curved
      • [x] Effects
        • [x] Connect BoxShadowSection settings to form block shadow styles
        • [x] Connect RotationSection rotation value to form block transform style
        • [x] Connect them both to render

    Phase 2: Finish form submit button styles

  • [x] Remove optional from all styles in defaults.ts

  • [x] Check for text/font defaults and use it under styles object if it looks right

  • [x] Add better FormSubmitButtonTextSection logic

  • [x] Add engine support for fontStyleDefaults

    • [x] Make text align work
  • [x] Uncomment FormSubmitButtonLayoutSection

  • [x] Make FormSubmitButtonLayoutSection work

Phase 2.5: Add title styling

  • [] Add title styling to FormConfiguration.vue
  • [] Commit FormConfiguration.vue
  • [] Commit related components

Phase 4: Make sure reordering of input blocks actually reorders them in DOM as well

Phase 5: Add default styles to input blocks

  • [] Add default styles to input blocks

Internal documentation