Skip to content

Step-Level Hooks

Each step can have its own lifecycle hooks that override the global hooks for that specific step. This allows you to run different callbacks depending on which step is being highlighted.

Available Step-Level Hooks

MethodWhen Called
onHighlightStarted($callback)Before this step's element is highlighted
onHighlighted($callback)After this step's element is highlighted
onDeselected($callback)When this step's element is deselected
onNextClick($callback)Overrides the Next button click for this step only
onPrevClick($callback)Overrides the Previous button click for this step only
onCloseClick($callback)Overrides the Close button click for this step only
onPopoverRender($callback)Called after this step's popover DOM is rendered

Note: onNextClick, onPrevClick, and onCloseClick at the step level override the default navigation for that step only. When you override navigation you must call opts.driver.moveNext() / opts.driver.movePrevious() manually if you still want the user to advance.

Method Signatures

php
$step->onHighlightStarted(string $callback);
$step->onHighlighted(string $callback);
$step->onDeselected(string $callback);
$step->onNextClick(string $callback);
$step->onPrevClick(string $callback);
$step->onCloseClick(string $callback);
$step->onPopoverRender(string $callback);

Parameters

  • $callback (string): The name of a JavaScript function or inline JavaScript expression.

Example

php
use RealRashid\LaravelDriverJs\Facades\DriverJs;

DriverJs::addStep('#header')
    ->title('Welcome!')
    ->description('This is the main header.')
    ->onHighlightStarted('headerBeforeHighlight')
    ->onHighlighted('headerAfterHighlight')
    ->onDeselected('headerDeselected');

DriverJs::addStep('#nav')
    ->title('Navigation')
    ->description('Use these links to navigate.')
    ->onHighlightStarted('navBeforeHighlight')
    ->onHighlighted('navAfterHighlight');

DriverJs::tour('onboarding')
    ->step('#content', 'Content', 'Main content area.')
    ->step('#footer', "That's it!")
    ->render();

Then in your JavaScript:

javascript
function headerBeforeHighlight(element, step, opts) {
    console.log('About to highlight the header');
}

function headerAfterHighlight(element, step, opts) {
    console.log('Header highlighted');
    // Maybe add a CSS class to the element
    element?.classList.add('tour-highlighted');
}

function headerDeselected(element, step, opts) {
    console.log('Header deselected');
    // Clean up
    element?.classList.remove('tour-highlighted');
}

function navBeforeHighlight(element, step, opts) {
    console.log('About to highlight navigation');
}

function navAfterHighlight(element, step, opts) {
    console.log('Navigation highlighted');
}

Hook Resolution Order

Step-level hooks take priority over global hooks. The resolution order is:

  1. Step-level hook (e.g., $step->onHighlightStarted())
  2. Global config hook (e.g., DriverJs::onHighlightStarted())
  3. Default Driver.js behavior (no callback)

If a step has a step-level hook defined, the global hook for that same event is not called for that step. Other steps without step-level hooks will still use the global hook.

Practical Use Case: Tracking Step Views

A common use case for step-level hooks is tracking analytics for individual steps:

php
DriverJs::addStep('#header')
    ->title('Welcome!')
    ->onHighlighted("function(el, step, opts) { analytics.track('tour_step_viewed', { step: 'header' }); }");

DriverJs::addStep('#nav')
    ->title('Navigation')
    ->onHighlighted("function(el, step, opts) { analytics.track('tour_step_viewed', { step: 'navigation' }); }");

DriverJs::addStep('#footer')
    ->title("That's it!")
    ->onHighlighted("function(el, step, opts) { analytics.track('tour_step_viewed', { step: 'footer' }); }");

DriverJs::tour('onboarding')->render();

That's it! You're now equipped to use step-level hooks with Laravel Driver.js.

Step-Level Button Hooks

You can also override navigation behaviour for individual steps using onNextClick, onPrevClick, onCloseClick, and onPopoverRender:

php
use RealRashid\LaravelDriverJs\Facades\DriverJs;

DriverJs::addStep('#payment-form')
    ->title('Payment Details')
    ->description('Fill in your card details.')
    ->onNextClick('validatePaymentStep')  // validate before allowing next
    ->onCloseClick('warnBeforeClose');

DriverJs::tour('checkout-tour')->render();
javascript
function validatePaymentStep(element, step, opts) {
    const form = document.querySelector('#payment-form');
    if (!form.checkValidity()) {
        form.reportValidity();
        return; // block navigation — do NOT call moveNext()
    }
    opts.driver.moveNext(); // validation passed, advance
}

function warnBeforeClose(element, step, opts) {
    if (confirm('Exit the checkout guide?')) {
        opts.driver.destroy();
    }
}

Step-Level onPopoverRender

Use onPopoverRender to modify the popover DOM after it is created for a specific step:

php
DriverJs::addStep('#dashboard')
    ->title('Your Dashboard')
    ->onPopoverRender('addDashboardBadge');
javascript
function addDashboardBadge(popover, opts) {
    const badge = document.createElement('span');
    badge.className = 'new-badge';
    badge.textContent = 'NEW';
    popover.title.prepend(badge);
}

When using addSteps(), the equivalent array keys are on_next_click, on_prev_click, on_close_click, and on_popover_render.