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
| Method | When 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, andonCloseClickat the step level override the default navigation for that step only. When you override navigation you must callopts.driver.moveNext()/opts.driver.movePrevious()manually if you still want the user to advance.
Method Signatures
$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
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:
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:
- Step-level hook (e.g.,
$step->onHighlightStarted()) - Global config hook (e.g.,
DriverJs::onHighlightStarted()) - 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:
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:
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();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:
DriverJs::addStep('#dashboard')
->title('Your Dashboard')
->onPopoverRender('addDashboardBadge');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.