Components

BoxLang components are reusable blocks of code that extend the language's capabilities without modifying the parser.

BoxLang components are reusable blocks of code that extend the language's capabilities without modifying the parser. They provide a powerful way to create custom language constructs, encapsulate complex logic, and build modular applications. They are analogous to web components. Here is a super simple example of a component that outputs a greeting:

Greeting.bxm

<bx:output>
    <h1>Hello, #attributes.yourname ?: "None Passed"#!</h1>
</bx:output>

Now I can call it in my BoxLang script:

// In a BoxLang script
bx:_greeting yourname="World";

Or in a BoxLang template:

<bx:_greeting yourname="World">

This will output:

<h1>Hello, World!</h1>

This simple example illustrates how components allow you to encapsulate functionality and reuse it across your BoxLang applications. Components can be as simple or complex as needed, and they can include attributes, logic, and even nested content.

📋 Table of Contents

Why Components Matter

Components solve common development challenges:

  • Eliminate Code Duplication: Write once, use everywhere

  • Extend the Language: Create custom block constructs that feel native

  • Encapsulate Logic: Keep complex operations contained and testable

  • Cross-Context Usage: BoxLang components work seamlessly in both script and template contexts

Basic Principles

Component Syntax

Components can be called using either script-based or template-based syntax according to where they are being used:

Script Context:

Template Context:

Component Execution Flow

When BoxLang encounters a component call, it follows this process:

Core and Module Components

Core Components

BoxLang ships with many core components that extend the language with framework capabilities. You can find them in the reference section.

Module Components

Any BoxLang module can also register and collaborate with components to the runtime.

Core and module components are registered with the runtime and don't go through the discovery process. They leverage the core Component Service to achieve this.

Creating Custom Components

Custom components are user-defined components written in BoxLang that will allow you to extend the language with your own features. It will also allow you to create expressive contributions to the templating language.

Custom components can be created using two approaches:

  • Template-based components (.bxm files): Use BoxLang's templating syntax

  • Script-based components (.bxs files): Use pure BoxLang script syntax

Basic Custom Component Structure

Let's start with simple examples using both approaches:

Template-based Component

File: components/greeting.bxm

Script-based Component

File: components/greeting.bxs

Component Input: The attributes Scope

All data passed to your component is available in the attributes scope. Both template and script-based components can validate and process these attributes. Note that the attribute name name is reserved and is only used when invoking components via bx:component .

Template-based Component with Attributes

Script-based Component with Attributes

Component Content: The thisComponent Scope

When components have start and end tags, BoxLang provides the thisComponent scope to manage content and execution. This works the same way in both template and script-based components.

The thisComponent scope contains:

  • executionMode: "start" or "end"

  • hasEndTag: boolean indicating if component has closing tag

  • generatedContent: Content between start and end tags

Template-based Component with thisComponent

File: components/boldWrapper.bxm

Script-based Component with thisComponent

File: components/boldWrapper.bxs

Usage (same for both):

Complex Component with Start/End Logic

Here's an advanced component demonstrating the full execution cycle, shown in both template and script syntax:

Template-based Version

File: components/section.bxm

Script-based Version

File: components/section.bxs

Usage (same for both template and script versions):

Custom Component Discovery

Custom component discovery is a hierarchical lookup process that occurs when BoxLang encounters a component call that isn't a registered core or module component.

Discovery Configuration

BoxLang component locations can be defined globally or on a per-app basis.

Global Configuration (boxlang.json):

Application Configuration (Application.bx):

File Extensions Searched

During discovery, BoxLang looks for files with these extensions in order:

  1. .bxm (BoxLang template)

  2. .bxs (BoxLang script)

  3. .cfc (CFML component - for compatibility)

  4. .cfm (CFML template - for compatibility)

Calling Custom Components

Method 1: Using bx:component

Script Syntax:

Template Syntax:

Method 2: Convention-Based Calling

BoxLang looks for a component file matching the name after bx::

Script Syntax:

Template Syntax:

Component Scopes Deep Dive

The attributes Scope

Contains all attributes passed to the component call:

The variables Scope

A localized scope for the component's internal logic:

The caller Scope

Provides access to the calling context (use sparingly):

The thisComponent Scope

Manages component execution and content:

Associating Subtag Data with Base Tags

BoxLang provides the bx:associate component to create relationships between child components and their parent components. This powerful feature allows you to build hierarchical component structures where child components can pass data up to their parent components.

How Component Association Works

When you use bx:associate inside a child component, it creates a data structure in the parent component that contains all the associated data from its children. This enables complex component hierarchies like forms with fields, menus with items, or layouts with sections.

Basic Association Syntax

Script Syntax:

Template Syntax:

Simple Example: Menu with Menu Items

Parent Component: menu.bxm

Child Component: menuItem.bxm

Usage:

Advanced Example: Form with Form Fields

Parent Component: form.bxm

Child Components:

formField.bxm

formOption.bxm

formAction.bxm

Usage:

Key Points About bx:associate

1. Data Collection Names

The dataCollection attribute specifies the name of the array that will be created in the parent component's thisComponent scope.

2. Automatic Array Creation

If the specified collection doesn't exist, BoxLang automatically creates it as an empty array.

3. Attribute Inheritance

All attributes from the child component are automatically added to the collection item.

4. Execution Timing

Association happens during the child component's execution, so data is available when the parent reaches its "end" execution mode.

5. Nested Associations

You can have multiple levels of association for complex hierarchies.

Advanced Pattern: Tab Container

Parent Component: tabContainer.bxm

Child Component: tab.bxm

Usage:

This association pattern enables powerful component composition where child components contribute data to their parents, creating flexible and reusable component hierarchies.

Advanced Component Patterns

Component Composition

Components can call other components for powerful composition:

Conditional Component Loading

Best Practices

1. Always Use bx:param for Attribute Validation

Template-based components:

Script-based components:

2. Use Descriptive Component Names

3. Document Your Components

Template-based components:

Script-based components:

4. Minimize Use of caller Scope

Template-based components:

Script-based components:

Migration from CFML Custom Tags

BoxLang components provide enhanced functionality over CFML custom tags:

CFML Custom Tags
BoxLang Components

<cf_customTag>

<bx:_customTag>

<cfmodule template="path">

<bx:component template="path">

Template context only

Script and template contexts

attributes scope

attributes scope

caller scope

caller scope

thisComponent scope

thisComponent scope

Limited discovery

Enhanced discovery system

Key Advantages in BoxLang:

  • Components work seamlessly in both script and template contexts

  • Enhanced parameter validation with bx:param

  • Improved discovery system with multiple lookup paths

  • Better error handling and debugging support

Last updated

Was this helpful?