Разработка кастомных дисплеев (Displays) Directus
Display Extension — Vue 3 компонент для отображения значения поля в списке (collection view) и форме просмотра. Если стандартные displays (raw, datetime, boolean, related-values) не подходят, создаётся кастомный.
Когда нужен кастомный Display
- Показывать цветной кружок для поля
colorвместо HEX-строки - Рендерить прогресс-бар для числового поля
progress - Отображать иконку статуса вместо текста
- Форматировать сложные JSON-данные как таблицу
Базовый Display
npx create-directus-extension@latest
# Type: display
# Name: color-display
<!-- src/display.vue -->
<template>
<div class="color-display">
<div
v-if="value"
class="color-swatch"
:style="{ background: value }"
/>
<span class="color-value">{{ value || '—' }}</span>
</div>
</template>
<script setup lang="ts">
defineProps<{ value: string | null }>()
</script>
<style scoped>
.color-display { display: flex; align-items: center; gap: 6px; }
.color-swatch { width: 16px; height: 16px; border-radius: 3px; border: 1px solid rgba(0,0,0,0.1); flex-shrink: 0; }
.color-value { font-size: 12px; font-family: monospace; }
</style>
// src/index.ts
import DisplayComponent from './display.vue'
export default {
id: 'color-display',
name: 'Color Swatch',
icon: 'palette',
description: 'Показывает цвет как цветной кружок',
component: DisplayComponent,
types: ['string'],
options: null, // нет дополнительных настроек
}
Display статуса с иконкой
<template>
<div class="status-display" :class="`status-${value}`">
<v-icon :name="statusConfig[value]?.icon || 'circle'" small />
<span>{{ statusConfig[value]?.label || value }}</span>
</div>
</template>
<script setup lang="ts">
defineProps<{ value: string | null }>()
const statusConfig: Record<string, { icon: string; label: string }> = {
draft: { icon: 'edit', label: 'Черновик' },
review: { icon: 'visibility', label: 'На проверке' },
published: { icon: 'check_circle', label: 'Опубликован' },
archived: { icon: 'archive', label: 'Архив' },
}
</script>
<style scoped>
.status-display { display: flex; align-items: center; gap: 4px; font-size: 12px; }
.status-published { color: var(--success); }
.status-draft { color: var(--warning); }
.status-archived { color: var(--foreground-subdued); }
</style>
Display прогресса
<template>
<div class="progress-display">
<div class="progress-bar">
<div class="progress-fill" :style="{ width: `${percentage}%`, background: color }" />
</div>
<span class="progress-label">{{ value }}{{ suffix }}</span>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
const props = defineProps<{
value: number | null
maxValue?: number
suffix?: string
}>()
const percentage = computed(() =>
Math.min(100, ((props.value || 0) / (props.maxValue || 100)) * 100)
)
const color = computed(() =>
percentage.value >= 80 ? '#4CAF50' : percentage.value >= 50 ? '#FF9800' : '#F44336'
)
</script>
// Регистрация с опциями
export default {
id: 'progress-display',
name: 'Progress Bar',
icon: 'linear_scale',
component: DisplayComponent,
types: ['integer', 'float', 'decimal'],
options: [
{
field: 'maxValue',
name: 'Max Value',
type: 'integer',
meta: { interface: 'input', default_value: 100 },
},
{
field: 'suffix',
name: 'Suffix',
type: 'string',
meta: { interface: 'input', options: { placeholder: '%' } },
},
],
}
Подключение Display к полю
В Settings → Data Model → поле → Interfacе & Display → выбрать Display = Color Swatch или Progress Bar.
Сроки
Разработка 2–3 кастомных displays — 1 день.







