Collaborative Editing

Development & Custom Extensions

Learn how Custom Interfaces integrate with Collaborative Editing in Directus.

Collaborative Editing works out-of-the-box for most Custom Interfaces.

Unlike the previous extension-based implementation, you do not need to add specific data attributes to your components. The system automatically handles presence, field locking, and synchronization through the v-form and form-field wrappers.

How it Works

When your Custom Interface is rendered within a Directus Form:

  1. Automatic wrapping: Your interface is wrapped by the form-field component.
  2. Event Detection: The wrapper listens for standard DOM focusin and focusout events bubbling up from your component.
  3. State Management: When your component receives focus, the wrapper automatically notifies the collaboration system to "lock" the field for other users and display your avatar.

Requirements for Custom Interfaces

For your custom interface to fully support collaborative editing, ensure the following:

1. Event Bubbling

Your component should allow focus and blur (or focusin/focusout) events to bubble up to the parent. This is standard behavior for native HTML inputs (<input>, <textarea>, etc.).

2. Standard Value Emission

Ensure your component emits the update:modelValue event when data changes, as per standard Vue 3 component design. This ensures real-time updates are propagated to other connected users.

emit('update:modelValue', newValue);

3. Read-Only State

Respect the disabled prop. When a field is locked by another user, Directus passes disabled: true to your interface. Ensure your component visually reflects this state and prevents user interaction.

defineProps({
    disabled: {
        type: Boolean,
        default: false,
    },
    // ...
});

Troubleshooting

If your interface is not triggering the "locked" state for other users:

  • Check Event Bubbling: If you use event.stopPropagation() on focus events, the wrapper will not detect the user's presence.
  • Focusable Elements: Ensure the element that users interact with is actually focusable (e.g., has a tabindex if it's not a native input).

Helper Utilities

Directus provides built-in utilities to help manage focus states in complex interfaces.

v-prevent-focusout Directive

Use this directive to prevent the focusout event from bubbling when interacting with specific elements (like dropdowns, modals, or drawers) that are part of your interface but might technically sit outside the DOM hierarchy or trigger a blur.

<!-- Prevents losing the "locked" state when clicking inside this drawer -->
<v-drawer v-prevent-focusout="isOpen" ...>
  ...
</v-drawer>

useFocusin Composable

If your component doesn't have a native input to trigger focus (e.g., a purely visual selector), you can use useFocusin to manually dispatch focus events.

import { useFocusin } from '@/composables/use-focusin';

const { active, focus, blur } = useFocusin(containerRef);

// Manually trigger 
focus();

Advanced Implementation

If you are building complex interfaces that do not rely on standard focus events (e.g., a canvas-based editor), you may need to manually trigger focus events or manage the disabled state more aggressively. However, for most use cases, no specific "Collaborative Editing" code is required.

Get once-a-month release notes & real‑world code tips...no fluff. 🐰