Introduction
Overview
The widget itself is a heavy event-driven component. It does not directly persist or own domain data. Instead, it notifies the host application when something needs to occur (create, update, delete, load, close, etc).
The host application is responsible for:
- Storing data
- Persisting chnages
- Validating operations
- Enforcing business rules
- Returning the final result back to the widget
All communication from the widget to the host happens through the
Why This Interface Exists
The
- Be framework-agnostic
- Avoid direct data persistence
- Remain decoupled from backend APIs
- Work with any storage mechanism (REST, GraphQL, local state, IndexedDB, etc.)
This separation ensures:
- Clear ownership of data in the host application
- Full control over validation and business logic
- Predictable, testable integration patterns
Core Design Pattern
Every callback in
- Receives domain data required to perform the operation
- Receives an onResponsefunction
- Must call onResponse(result) when the operation completes
There are no promises requires by the widget contract.
The onResponse Contract
Every callback includes:
onResponse: (result: DIQ_Result) => void
The
Example structure:
interface DIQ_Result {
ok: boolean;
message?: string;
}
- ok: true- operation succeeded
- ok: false- operation failed
- message- optional context (error details, validation feedback, etc)
Interface Definition
export interface DimensionIQWidgetCallbacks {
onProjectNew: (
project: DIQ_Project,
onResponse: (result: DIQ_Result) => void
) => void;
onProjectClose: (
project: DIQ_Project,
onResponse: (result: DIQ_Result) => void
) => void;
onDrawingAdd: (
drawing: DIQ_Drawing,
onResponse: (result: DIQ_Result) => void
) => void;
}
Example Implementation
const callbacks: DimensionIQWidgetCallbacks = {
onProjectNew: (project, onResponse) => {
try {
saveProjectToDatabase(project);
onResponse({
ok: true
});
} catch (error) {
onResponse({
ok: false,
message: "Failed to create project"
});
}
},
onDrawingAdd: (drawing, onResponse) => {
api.createDrawing(drawing)
.then(() => {
onResponse({ ok: true });
})
.catch(() => {
onResponse({
ok: false,
message: "Unable to add drawing"
});
});
}
};
Important Rules
1. Always Call onReponse
Failing to call
- UI lock states
- Incomplete operations
- Desynchronized state
2. The Widget is Stateless for Persistence
The widget assumes:
- The host owns the data
- The host determines success/failure
- The host enforces business rules
The widget only reacts to the result.
3. The Validation Belongs to the Host
If an operation is invalid:
onResponse({
ok: false;
message: "Project name already exists"
});
The widget will display the message appropriately.
Event Flow Example
User Action: Create new project


Host persists project

Host calls

Widget updates internal state
If failed:

Host calls

Widget cancels operation and displays feedback
Integration Guidelines
- Ensure all callbacks terminate by calling onResponse
- Keep persistence logic outside the widget
- Do not mutate objects unexpectedly after passing them back
- Treat callbacks as transactional boundaries
Summary
It ensures:
- Clean separation of UI and data
- Deterministic state transitions
- Full host control over business logic
- Predictable event-driven architecture
This interface allows