Skip to main content

Complete API Reference

This comprehensive guide covers every public export, interface, type, and method available in MLForm.

Table of Contents

  1. Main Export
  2. Core Types
  3. Field Strategies
  4. Output Strategies
  5. Extension Base Classes
  6. Utility Types
  7. Import Paths

Main Export

MLForm Class

The main class for creating and managing dynamic forms with ML capabilities.

import { MLForm } from 'mlform';

const mlForm = new MLForm(backendUrl: string);

Constructor

constructor(backendUrl: string)

Creates a new MLForm instance.

Parameters:

  • backendUrl (string) - The URL of your backend API for ML predictions (can be any string, only used if outputs defined)

Example:

const mlForm = new MLForm('https://api.example.com/predict');

Methods

toHTMLElement()

async toHTMLElement(
data: Signature,
container: HTMLElement
): Promise<HTMLElement>

Renders the form into a DOM container element and sets up all event listeners.

Parameters:

  • data (Signature) - The form schema with inputs and outputs
  • container (HTMLElement) - The DOM element where the form will be mounted

Returns: Promise<HTMLElement> - The container element with the rendered form

Throws:

  • Error if schema is invalid or unsupported field types are used

Example:

const schema = {
inputs: [
{ type: 'text', title: 'Name', required: true }
],
outputs: []
};

const container = document.getElementById('form-container')!;
await mlForm.toHTMLElement(schema, container);

register()

register(descriptor: FieldStrategy | ReportStrategy): void

Registers a custom field or output strategy to extend MLForm functionality.

Parameters:

  • descriptor (FieldStrategy | ReportStrategy) - Custom strategy implementation

Throws:

  • Error if strategy type already exists (use update() instead)

Example:

import { FieldStrategy } from 'mlform/extensions';

class ColorPickerStrategy extends FieldStrategy {
constructor() {
super('color', ColorSchema, () => import('./color-field'));
}

buildControl(field) {
return { tag: 'color-field', props: { value: field.value } };
}
}

mlForm.register(new ColorPickerStrategy());

update()

update(descriptor: FieldStrategy | ReportStrategy): void

Updates an existing registered strategy, replacing the previous implementation.

Parameters:

  • descriptor (FieldStrategy | ReportStrategy) - Updated strategy

Example:

const updatedStrategy = new ColorPickerStrategy();
mlForm.update(updatedStrategy);

unregister()

unregister(descriptor: FieldStrategy | ReportStrategy): void

Removes a registered strategy by its type identifier.

Parameters:

  • descriptor (FieldStrategy | ReportStrategy) - Strategy to remove

Example:

mlForm.unregister(new ColorPickerStrategy());

onSubmit()

onSubmit(
callback: (inputs: Record<string, unknown>, response: Output) => void
): () => void

Subscribes to form submission events. Returns an unsubscribe function.

Parameters:

  • callback - Function called on form submission with:
    • inputs (Record<string, unknown>) - User input values
    • response (Output) - ML model response (if outputs defined)

Returns: () => void - Unsubscribe function to remove the listener

Example:

const unsubscribe = mlForm.onSubmit((inputs, response) => {
console.log('Form submitted:', inputs);
console.log('Prediction:', response);
});

// Later, to stop listening:
unsubscribe();

validateSchema()

async validateSchema(data: Signature): Promise<unknown>

Validates a schema against the current registry before rendering.

Parameters:

  • data (Signature) - Schema to validate

Returns: Promise<unknown> - Zod safe-parse result with success and error fields

Example:

const validation = await mlForm.validateSchema(schema);

if (!validation.success) {
console.error('Schema validation errors:', validation.error);
} else {
await mlForm.toHTMLElement(schema, container);
}

schema()

schema(): object

Generates a JSON Schema (draft 2020-12) for your current registry configuration.

Returns: object - JSON Schema representation of your form

Use Cases:

  • API documentation generation
  • Schema validation tools
  • Introspection for testing

Example:

const jsonSchema = mlForm.schema();
console.log(JSON.stringify(jsonSchema, null, 2));

// Can be used with tools like https://www.jsonschemavalidator.net/

Properties

lastInputs

readonly lastInputs: Record<string, unknown> | null

Gets the most recent form submission inputs. Returns null if no submission yet.

Type: Record<string, unknown> | null

Example:

const previousInputs = mlForm.lastInputs;
if (previousInputs) {
console.log('Last name entered:', previousInputs['Full Name']);
}

lastResponse

readonly lastResponse: Output | null

Gets the most recent ML model response. Returns null if no outputs defined or no submission yet.

Type: Output | null

Example:

const prediction = mlForm.lastResponse;
if (prediction?.outputs?.[0]) {
console.log('Last prediction:', prediction.outputs[0].prediction);
}

Core Types

Signature

The main interface for defining form schemas.

interface Signature {
inputs: Array<BaseField> // Field definitions
outputs: Array<BaseModel> // Model output definitions
}

Properties:

  • inputs - Array of input field configurations
  • outputs - Array of ML model output configurations (optional, defaults to [])

Example:

const signature: Signature = {
inputs: [
{ type: 'text', title: 'Name', required: true },
{ type: 'number', title: 'Age', min: 0, max: 120, required: true }
],
outputs: [
{ type: 'classifier', title: 'Category' }
]
};

BaseField

Base properties shared by all field types.

interface BaseField {
type: string // Field type identifier
title: string // 1-100 chars, displayed to user
description?: string // 1-500 chars, helper text
required?: boolean // Defaults to true
}

Constraints:

  • title must match regex /^\S.*\S$/ (non-empty, no leading/trailing spaces)
  • description must be 1-500 characters if provided
  • All other properties are type-specific

BaseModel

Base properties shared by all model types.

interface BaseModel {
type: string // 'classifier' or 'regressor'
title?: string // Optional display title
execution_time?: number // Inference time in milliseconds
}

Output

Response structure from ML backend.

interface Output {
outputs?: Array<{
type: 'classifier' | 'regressor'
prediction: string | number
confidence?: number
probabilities?: Record<string, number>
confidence_interval?: [number, number]
std_deviation?: number
execution_time?: number
}>
}

Field Strategies

All built-in field strategies are available in mlform/strategies.

import {
TextStrategy,
NumberStrategy,
BooleanStrategy,
CategoryStrategy,
DateStrategy
} from 'mlform/strategies';

TextStrategy

Handles text input with validation.

const strategy = new TextStrategy();
mlForm.register(strategy);

Field Properties:

  • type: 'text'
  • title: string
  • description?: string
  • required?: boolean
  • value?: string - Initial value
  • placeholder?: string
  • minLength?: number
  • maxLength?: number
  • pattern?: string - Regex pattern

NumberStrategy

Handles numeric input with range constraints.

const strategy = new NumberStrategy();
mlForm.register(strategy);

Field Properties:

  • type: 'number'
  • title: string
  • description?: string
  • required?: boolean
  • value?: number - Initial value
  • min?: number
  • max?: number
  • step?: number - Default: 1
  • placeholder?: string
  • unit?: string - Label like 'USD', 'kg'

BooleanStrategy

Handles checkbox/toggle inputs.

const strategy = new BooleanStrategy();
mlForm.register(strategy);

Field Properties:

  • type: 'boolean'
  • title: string
  • description?: string
  • required?: boolean
  • value?: boolean - Initial checked state

CategoryStrategy

Handles select/dropdown inputs.

const strategy = new CategoryStrategy();
mlForm.register(strategy);

Field Properties:

  • type: 'category'
  • title: string
  • description?: string
  • required?: boolean
  • options: string[] - Available choices (required)
  • value?: string - Initial selection (must be in options)

DateStrategy

Handles date picker inputs.

const strategy = new DateStrategy();
mlForm.register(strategy);

Field Properties:

  • type: 'date'
  • title: string
  • description?: string
  • required?: boolean
  • value?: string - Initial date (ISO 8601)
  • min?: string - Earliest date (ISO 8601)
  • max?: string - Latest date (ISO 8601)
  • step?: number - Day increment (default: 1)

Output Strategies

All built-in output strategies are available in mlform/strategies.

import {
ClassifierStrategy,
RegressorStrategy
} from 'mlform/strategies';

ClassifierStrategy

Renders classification model outputs.

const strategy = new ClassifierStrategy();
mlForm.register(strategy);

Output Properties:

  • type: 'classifier'
  • title?: string
  • execution_time?: number
  • mapping?: string[] - Label mappings
  • probabilities?: number[][] - Probability matrix
  • details?: boolean - Show detailed info

RegressorStrategy

Renders regression model outputs.

const strategy = new RegressorStrategy();
mlForm.register(strategy);

Output Properties:

  • type: 'regressor'
  • title?: string
  • execution_time?: number
  • values?: number[] - Related values
  • unit?: string - Unit label
  • interval?: [number, number] - Confidence interval

Extension Base Classes

For creating custom strategies, extend these base classes from mlform/extensions.

import {
FieldStrategy,
ReportStrategy,
FieldElement
} from 'mlform/extensions';

FieldStrategy

Base class for custom input field strategies.

import { FieldStrategy } from 'mlform/extensions';
import * as z from 'zod';

export class CustomFieldStrategy extends FieldStrategy {
constructor() {
super(
'custom-type', // type identifier
CustomSchema, // Zod schema for validation
() => import('./custom-field') // Lazy loader
);
}

protected buildControl(field) {
return {
tag: 'custom-field',
props: {
value: field.value,
title: field.title
}
};
}
}

Abstract Methods:

  • buildControl(field: Infer<S>): { tag: string; props: Record<string, unknown> }
    • Maps field config to UI component
    • tag - Custom element tag name
    • props - Properties passed to component

Constructor Parameters:

  • type: string - Unique identifier (e.g., 'color', 'slider')
  • schema: Schema - Zod validation schema
  • loader: () => Promise<unknown> - Dynamic import function

ReportStrategy

Base class for custom ML output strategies.

import { ReportStrategy } from 'mlform/extensions';

export class CustomReportStrategy extends ReportStrategy {
constructor() {
super(
'custom-output',
CustomOutputSchema,
() => import('./custom-report')
);
}

protected buildControl(output) {
return {
tag: 'custom-report',
props: {
prediction: output.prediction,
title: output.title
}
};
}
}

Abstract Methods:

  • buildControl(output: Infer<S>): { tag: string; props: Record<string, unknown> }
    • Maps output config to UI component

FieldElement

Interface for custom field Web Components.

import { FieldElement } from 'mlform/extensions';

Expected Interface:

  • Custom element must dispatch change event with { detail: { value } }
  • Must accept properties: value, title, custom props from strategy

Example:

class ColorField extends HTMLElement {
value: string = '#000000';

connectedCallback() {
this.addEventListener('click', () => {
this.value = '#FF0000';
this.dispatchEvent(new CustomEvent('change', {
detail: { value: this.value },
bubbles: true,
composed: true
}));
});
}
}

customElements.define('color-field', ColorField);

Utility Types

Schema

Generic Zod schema type for validation.

import { type Schema } from 'mlform';
import * as z from 'zod';

const MySchema: Schema = z.strictObject({
type: z.literal('custom'),
title: z.string(),
value: z.optional(z.string())
});

Infer

Extract TypeScript type from Zod schema.

import { type Infer } from 'mlform';
import * as z from 'zod';

const MySchema = z.strictObject({
type: z.literal('custom'),
value: z.string()
});

type MyType = Infer<typeof MySchema>;
// MyType = { type: 'custom'; value: string }

array

Zod array validator (re-exported for convenience).

import { array } from 'mlform';

const schema = array(z.string());

union

Zod union validator (re-exported for convenience).

import { union } from 'mlform';

const schema = union([z.string(), z.number()]);

Import Paths

Main Package

// Default export
import { MLForm } from 'mlform';

// Types
import type { Signature, Output, Base, Infer, Schema } from 'mlform';

Extensions

// Base classes for custom strategies
import { FieldStrategy, ReportStrategy } from 'mlform/extensions';

// Base types and schemas
import {
type BaseField,
BaseFieldSchema,
type BaseModel,
BaseModelSchema
} from 'mlform/extensions';

// UI utilities
import { FieldElement } from 'mlform/extensions';

Strategies

// Built-in field strategies
import {
TextStrategy,
NumberStrategy,
BooleanStrategy,
CategoryStrategy,
DateStrategy
} from 'mlform/strategies';

// Built-in output strategies
import {
ClassifierStrategy,
RegressorStrategy
} from 'mlform/strategies';

Zod (for custom schemas)

// MLForm re-exports common Zod utilities
import { array, union } from 'mlform';

// For full Zod usage, import directly
import * as z from 'zod';

Complete Example: Custom Color Picker Strategy

Here's a complete, production-ready example showing all the imports and API usage:

import * as z from 'zod';
import { MLForm } from 'mlform';
import { FieldStrategy, type Infer } from 'mlform/extensions';

// Step 1: Define schema
const ColorFieldSchema = z.strictObject({
type: z.literal('color'),
title: z.string().min(1),
description: z.optional(z.string()),
required: z.optional(z.boolean().default(true)),
value: z.optional(z.string().regex(/^#[0-9A-F]{6}$/i)),
allowedColors: z.optional(z.array(z.string().regex(/^#[0-9A-F]{6}$/i)).min(1))
});

type ColorField = Infer<typeof ColorFieldSchema>;

// Step 2: Define custom UI component (in color-field.ts)
class ColorField extends HTMLElement {
value: string = '#000000';
allowedColors: string[] = ['#FF0000', '#00FF00', '#0000FF'];

connectedCallback() {
this.render();
}

render() {
this.innerHTML = this.allowedColors
.map(color => `
<button
data-color="${color}"
style="background: ${color}"
class="${color === this.value ? 'selected' : ''}"
></button>
`).join('');

this.querySelectorAll('button').forEach(btn => {
btn.addEventListener('click', () => {
this.value = btn.dataset.color!;
this.dispatchEvent(new CustomEvent('change', {
detail: { value: this.value },
bubbles: true,
composed: true
}));
});
});
}
}

customElements.define('color-field', ColorField);

// Step 3: Create strategy
class ColorPickerStrategy extends FieldStrategy<typeof ColorFieldSchema> {
constructor() {
super(
'color',
ColorFieldSchema,
() => import('./color-field')
);
}

protected buildControl(field: ColorField) {
return {
tag: 'color-field',
props: {
value: field.value,
allowedColors: field.allowedColors
}
};
}
}

// Step 4: Use in MLForm
async function main() {
const mlForm = new MLForm('https://api.example.com/predict');

// Register custom strategy
mlForm.register(new ColorPickerStrategy());

// Validate schema
const schema = {
inputs: [
{
type: 'text',
title: 'Name',
required: true
},
{
type: 'color',
title: 'Brand Color',
value: '#0066FF',
allowedColors: ['#0066FF', '#FF0066', '#66FF00']
}
],
outputs: []
};

const validation = await mlForm.validateSchema(schema);
if (!validation.success) {
console.error('Invalid schema:', validation.error);
return;
}

// Subscribe to submissions
mlForm.onSubmit((inputs, response) => {
console.log('Form data:', {
name: inputs['Name'],
brandColor: inputs['Brand Color']
});
});

// Render form
const container = document.getElementById('form-container')!;
await mlForm.toHTMLElement(schema, container);

// Access last submission
setTimeout(() => {
if (mlForm.lastInputs) {
console.log('Previously submitted:', mlForm.lastInputs);
}
}, 5000);
}

main();

Public API Summary

ExportTypePurpose
MLFormClassMain form manager
FieldStrategyClassBase for custom input strategies
ReportStrategyClassBase for custom output strategies
TextStrategyClassBuilt-in text field
NumberStrategyClassBuilt-in number field
BooleanStrategyClassBuilt-in boolean field
CategoryStrategyClassBuilt-in category field
DateStrategyClassBuilt-in date field
ClassifierStrategyClassBuilt-in classifier output
RegressorStrategyClassBuilt-in regressor output
BaseFieldSchemaZod SchemaBase field validation
BaseModelSchemaZod SchemaBase model validation
SignatureTypeForm schema structure
OutputTypeML response structure
BaseTypeInput field array
SchemaTypeZod validation schema
InferTypeExtract type from schema
arrayFunctionZod array validator
unionFunctionZod union validator

Error Handling

Common Errors and Solutions

ErrorCauseSolution
"Unsupported field type"Using undefined field typeRegister strategy with mlForm.register()
"Invalid schema"Schema doesn't match signatureUse validateSchema() before rendering
"Type already exists"Registering duplicate typeUse update() instead of register()
"Invalid pattern"Regex pattern in text field is malformedVerify regex syntax in pattern property
"Value not in options"Category value doesn't match optionsEnsure value matches one of options
"Backend connection failed"Invalid URL or network errorCheck backendUrl and server availability

Best Practices

1. Always Validate Schemas

const validation = await mlForm.validateSchema(schema);
if (!validation.success) {
console.error('Schema errors:', validation.error);
return;
}

2. Use TypeScript for Custom Strategies

class MyStrategy extends FieldStrategy<typeof MySchema> {
// Full type safety
}

3. Manage Subscriptions

const unsubscribe = mlForm.onSubmit((inputs) => {
// Handle submission
});

// Clean up when component unmounts
onDestroy(() => unsubscribe());

4. Handle Backend Errors

mlForm.onSubmit((inputs, response) => {
if (!response?.outputs || response.outputs.length === 0) {
console.error('No predictions received');
return;
}

const prediction = response.outputs[0];
if (!prediction.prediction) {
console.error('Invalid response format');
return;
}
});

5. Use Lazy Loading for Components

// ✅ Good: Lazy load
class MyStrategy extends FieldStrategy {
constructor() {
super('my-type', schema, () => import('./my-component'));
}
}

// ❌ Bad: Eager load
import './my-component'; // Imported at top level