Skip to main content

Controlling Flicking

Patterns and best practices for controlling Flicking programmatically, responding to events, and handling errors.

Framework-Specific Guides

For detailed information on accessing methods and handling events in your framework, see:


Method Patterns​

Common patterns for controlling Flicking programmatically. See the Flicking API for complete method reference.

Sequential Navigation​

// Navigate through panels in sequence
async function autoNavigate() {
for (let i = 0; i < flicking.panelCount; i++) {
await flicking.moveTo(i, 1000);
await new Promise(resolve => setTimeout(resolve, 2000));
}
}

Conditional Navigation​

// Only move if not already at the target
async function moveToIfNeeded(targetIndex) {
if (flicking.index !== targetIndex) {
await flicking.moveTo(targetIndex);
}
}

Handling Interruptions​

// Handle animation interruptions gracefully
async function safeNext() {
try {
await flicking.next();
console.log("Successfully moved to next panel");
} catch (error) {
if (error.code === ERROR_CODE.ANIMATION_ALREADY_PLAYING) {
console.log("Animation already in progress, skipping");
} else if (error.code === ERROR_CODE.ANIMATION_INTERRUPTED) {
console.log("Animation interrupted by user");
} else {
throw error; // Re-throw unexpected errors
}
}
}

Event Patterns​

Understanding Flicking's event system. See Event Interfaces for complete event reference.

Event Timeline​

Understanding when events fire is crucial for building responsive UIs. Here's the complete timeline of events during user interaction:

User starts dragging
↓
[holdStart] ← Touch/mouse down
↓
[moveStart] ← Movement begins
↓
[move] ← Continuously fired during movement
↓
[willChange] ← BEFORE panel index changes (cancellable)
↓
[changed] ← AFTER panel index changes
↓
[moveEnd] ← Movement animation ends
↓
[holdEnd] ← Touch/mouse up

Key Events​

Panel Change Events

  • willChange - Fired BEFORE panel changes (cancellable with e.stop())
  • changed - Fired AFTER panel changes

Movement Events

User Input Events

Other Events


Event Usage Patterns​

Syncing Multiple Flicking Instances​

const flicking1 = new Flicking("#carousel1");
const flicking2 = new Flicking("#carousel2");

flicking1.on(EVENTS.CHANGED, (e) => {
flicking2.moveTo(e.index);
});

flicking2.on(EVENTS.CHANGED, (e) => {
flicking1.moveTo(e.index);
});

Progress Tracking​

let startPosition = 0;

flicking.on(EVENTS.MOVE_START, (e) => {
startPosition = e.axesEvent.pos.flick;
});

flicking.on(EVENTS.MOVE, (e) => {
const currentPosition = e.axesEvent.pos.flick;
const distance = currentPosition - startPosition;
console.log("Dragged distance:", distance);
});

Conditional Panel Change​

flicking.on(EVENTS.WILL_CHANGE, (e) => {
// Require minimum drag distance
if (Math.abs(e.axesEvent.delta.flick) < 50) {
e.stop();
console.log("Drag distance too small, preventing change");
}
});

Error Handling Patterns​

Flicking throws FlickingError instances with ERROR_CODE constants. See FlickingError API for complete error reference.

Graceful Degradation​

async function safeNavigation(targetIndex) {
try {
await flicking.moveTo(targetIndex);
return true;
} catch (err) {
if (err instanceof FlickingError) {
switch (err.code) {
case ERROR_CODE.ANIMATION_ALREADY_PLAYING:
// Queue the action for later
setTimeout(() => safeNavigation(targetIndex), 300);
return false;

case ERROR_CODE.INDEX_OUT_OF_RANGE:
console.warn("Invalid index, moving to first panel");
await flicking.moveTo(0);
return false;

case ERROR_CODE.ANIMATION_INTERRUPTED:
// User interrupted, that's okay
return false;

default:
throw err;
}
}
throw err;
}
}

Debounced Navigation​

let navigationTimeout = null;

function debouncedNext() {
if (navigationTimeout) {
clearTimeout(navigationTimeout);
}

navigationTimeout = setTimeout(async () => {
try {
await flicking.next();
} catch (err) {
if (err instanceof FlickingError &&
err.code === ERROR_CODE.ANIMATION_ALREADY_PLAYING) {
// Retry after animation completes
debouncedNext();
}
}
}, 100);
}

User-Friendly Error Messages​

function getUserFriendlyMessage(error) {
if (!(error instanceof FlickingError)) {
return "An unexpected error occurred";
}

switch (error.code) {
case ERROR_CODE.ANIMATION_ALREADY_PLAYING:
return "Please wait for the current animation to complete";

case ERROR_CODE.INDEX_OUT_OF_RANGE:
return "The requested panel does not exist";

case ERROR_CODE.ANIMATION_INTERRUPTED:
return "Navigation was interrupted";

case ERROR_CODE.NO_ACTIVE:
return "No panels available";

default:
return error.message;
}
}

// Usage
try {
await flicking.moveTo(targetIndex);
} catch (err) {
showToast(getUserFriendlyMessage(err));
}