Lazy Loading

CBWIRE supports lazy loading for components that might delay the initial page load.

Consider a component StockTicker that fetches real-time stock data, a process that can be slow:

// ./wires/StockTicker.cfc
component extends="cbwire.models.Component" {

    data = {
        "stockValue": nil()
    };
    
    function mount() {
        // Simulate slow API call for stock data...
        data.stockValue = getStockValue("AAPL"); // Hypothetical function
    }

    function renderIt() {
        return template( "wires.stockticker" );

    }
}
<!-- wires/stockticker.cfm -->
<div>
    Current AAPL stock value: #stockValue#
</div>

Without lazy loading, this component would slow down the page load. To enable lazy loading:

#wire( name="StockTicker", lazy=true )#

With lazy loading, CBWIRE skips the component during the initial load. Once visible, it loads the component via a network request.

Lazy requests are isolated and not bundled as with Request Bundling, allowing each to load independently and quickly when the page loads, maintaining performance.

Placeholder

By default, CBWIRE inserts an empty <div></div> before a component fully loads. To improve user experience and indicate loading, you can implement a placeholder() method in your component to display custom HTML, such as loading spinners.

Consider a component FinancialReport that processes a slow data query:

// ./wires/FinancialReport.cfc
component extends="cbwire.models.Component" {

    data = {
        "totalRevenue": ""
    };
    
    function mount() {
        // Simulate a slow database query...
        data.totalRevenue = getRevenue(); // Hypothetical function
    }

    function placeholder() {
        return view( "spinner" );

    }

    function renderIt() {
        return template( "wires.financialreport" );
    }
}
<!-- wires/spinner.cfm -->
<div>
    <!-- Loading spinner -->
    <svg>...</svg>
</div>

This setup ensures users see a loading spinner until FinancialReport is fully loaded.

The placeholder and the main component must use the same type of root element, like a div.

Loading Outside the Viewport

Normally, lazy-loaded components only load once within the browser's viewport (e.g., when a user scrolls down). If you'd like to load all components immediately after the page is ready, pass "on-load" to the lazy parameter:

#wire( name="StockTicker", lazy="onLoad" )#;

This way, StockTicker will fully load after the page is ready without needing to be visible in the viewport.

Passing Parameters

You can treat lazy-loaded CBWIRE components like normal ones by passing data to them from outside. Consider this example where a parent component passes user details into a UserActivity component:

<input type="text" wire:model="username">
<input type="number" wire:model="days">

#wire(
    name="UserActivity",
    params={
        "username": username,
        "days": days
    }, 
    lazy=true
)#

In mount(), the component can utilize the passed-in data:

component extends="cbwire.models.Component" {

    data = {
        "activities": []
    };

    function mount( params ) {
        // Perform an expensive query...
        data.activities = getUserActivities( params.username, params.days);
    }

    function placeholder() {
        return "<div><svg>Loading activities...</svg></div>";
    }

    function renderIt() {
        return template( "wires.useractivity" );
    }
}

Lazy components will temporarily store passed-in data on the client side until fully loaded. For instance, the username and days properties will be serialized and re-queried on the next request, ensuring a smooth user experience.

Because of this, it's important to only pass parameters with lazy-loaded components that can be serialized and read by JavaScript.

Disabling Request Isolation

By default, CBWIRE handles each lazy-loaded component request separately. However, if you want to bundle all updates into a single network request, disable the isolation behavior using lazyIsolate=false:

// ./wires/UserActivity.cfc
component extends="cbwire.models.Component" {
    lazy = true;
    lazyIsolate = false;
    // Other component methods...
}

Now, if there are multiple UserActivity components on the same page, their updates will be grouped into a single network request when the page loads.

Last updated