Frontend Context System

Last Updated: May 19, 2025

This document provides an overview of the context system in the frontend architecture of the Typus Development Framework.

Introduction

The context system in the Typus frontend provides a structured way to manage and share state, dependencies, and functionality across components. It enables clean separation of concerns while ensuring components have access to the data and services they need.

Core Concepts

What is Context?

In the Typus framework, a context is a container that:

  1. Holds state (data)
  2. Provides methods (functionality)
  3. Manages dependencies (services)
  4. Handles lifecycle events

Contexts are designed to be hierarchical, allowing for inheritance and overriding of values at different levels of the component tree.

Context Types

The framework provides several types of contexts:

Application Context

The application context is the top-level context that is available throughout the entire application. It contains:

  • Global state
  • Core services
  • Application configuration
  • Authentication state
  • Theme settings

Page Context

Each page has its own context that inherits from the application context. The page context contains:

  • Page-specific state
  • Navigation information
  • Layout configuration
  • Page-level services

Component Context

Components can create and use their own contexts, which inherit from their parent context (usually the page context). Component contexts contain:

  • Component-specific state
  • Local services
  • Event handlers
  • Computed values

DSX Contexts

When using the DSX system, contexts play a crucial role in managing data and behavior:

  • DSX Page Context: Created for each DSX page, containing the page's data model and operations
  • DSX Block Context: Each block in a DSX page can have its own context, either shared with the page or isolated
  • DSX Component Context: Individual components within blocks can access their parent block's context or create isolated contexts

Context Hierarchy

Contexts in the Typus frontend follow a hierarchical structure:

Application Context

Page Context

Component Context

Component Context

Nested Component Context

This hierarchy allows for:

  • Inheritance: Child contexts inherit properties and methods from parent contexts
  • Overriding: Child contexts can override inherited values
  • Isolation: Contexts can be isolated to prevent inheritance when needed

Using Contexts

Creating a Context

Contexts are typically created using composables:

// Example of creating a component context
const componentContext = useComponentContext({
  initialState: {
    count: 0,
    items: []
  },
  methods: {
    increment() {
      this.state.count++
    },
    addItem(item) {
      this.state.items.push(item)
    }
  }
})

Accessing Context

Components can access their context or parent contexts:

// Access the current component's context
const context = useCurrentContext()

// Access the page context
const pageContext = usePageContext()

// Access the application context
const appContext = useAppContext()

Context in DSX

In DSX pages, contexts are automatically created based on configuration:

const pageConfig = {
  // ...
  contextConfig: {
    model: UserModel, // DSL model binding
    mode: FormMode.EDIT,
    recordId: userId
  },
  blocks: [
    {
      // This block uses the page context
      components: [/* ... */]
    },
    {
      // This block has an isolated context
      contextConfig: {
        scope: ContextScope.ISOLATED,
        model: UserPreferencesModel
      },
      components: [/* ... */]
    }
  ]
}

Context Features

Reactive State

All context state is reactive, meaning changes to the state automatically trigger UI updates in components that depend on that state.

Method Binding

Methods defined in a context are automatically bound to that context, allowing them to access and modify the context's state.

Dependency Injection

Contexts can inject dependencies from parent contexts or from the dependency injection container:

const context = useComponentContext({
  inject: ['userService', 'notificationService'],
  methods: {
    async saveUser() {
      await this.userService.save(this.state.user)
      this.notificationService.success('User saved')
    }
  }
})

Lifecycle Hooks

Contexts provide lifecycle hooks that allow for setup and cleanup operations:

  • onContextCreated: Called when the context is first created
  • onContextMounted: Called when the component using the context is mounted
  • onContextBeforeUnmount: Called before the component using the context is unmounted
  • onContextUnmounted: Called when the component using the context is unmounted

Context and DSL Integration

The context system integrates seamlessly with the DSL (Domain-Specific Language) system:

  • DSL models can be bound to contexts
  • Context methods can perform DSL operations
  • DSL events can trigger context updates
  • Context state can be synchronized with DSL data

This integration is particularly powerful in DSX pages, where the context automatically handles data loading, saving, and synchronization based on the configured DSL model.

Best Practices

Context Granularity

  • Application Context: Use for truly global state and services
  • Page Context: Use for state shared across components on a page
  • Component Context: Use for state specific to a component and its children
  • Isolated Context: Use when a component needs to be self-contained

State Management

  • Keep context state focused and minimal
  • Use computed values for derived state
  • Consider using Pinia stores for complex global state

Performance Considerations

  • Avoid deep nesting of contexts when possible
  • Be mindful of reactive dependencies to prevent unnecessary re-renders
  • Use isolated contexts for performance-critical components

Conclusion

The context system in the Typus frontend provides a powerful and flexible way to manage state and functionality across components. By leveraging contexts, developers can create clean, maintainable code with clear separation of concerns while ensuring components have access to the data and services they need.

The integration with DSX and DSL systems makes the context system particularly powerful for building dynamic, data-driven interfaces with minimal code.

WARNING

Failed to fetch dynamically imported module: https://typus.dev/assets/RecursiveNavItem-Cep7andh.js

{ "stack": "AppError: Failed to fetch dynamically imported module: https://typus.dev/assets/RecursiveNavItem-Cep7andh.js\n at https://typus.dev/assets/index-DS79FI73.js:315:420\n at dn (https://typus.dev/assets/vue-vendor-Ct83yDeK.js:13:1385)\n at We (https://typus.dev/assets/vue-vendor-Ct83yDeK.js:13:1455)\n at Ws.t.__weh.t.__weh (https://typus.dev/assets/vue-vendor-Ct83yDeK.js:14:7364)\n at jt (https://typus.dev/assets/vue-vendor-Ct83yDeK.js:13:1866)\n at v (https://typus.dev/assets/vue-vendor-Ct83yDeK.js:14:4019)\n at https://typus.dev/assets/vue-vendor-Ct83yDeK.js:14:4097" }