КРЕАТИВНЫЕ САЙТЫ И ПРИЛОЖЕНИЯ,
КАЧЕСТВЕННЫЕ WEB-УСЛУГИ
phone

SwTable

Компонент SwTable представляет собой
динамическую таблицу
с поддержкой сложных заголовков.

SwTable

Компонент SwTable — динамическая таблица с вложенными заголовками, объединением ячеек (rowspan / colspan), кастомизацией через слоты, подсветкой строк и столбцов при наведении, изменением ширины колонок и фиксацией крайних колонок при горизонтальном скролле. The SwTable component is a dynamic table with nested headers, cell merging (rowspan / colspan), slot-based customization, row and column hover highlighting, column resizing, and sticky edge columns during horizontal scroll. Колонки описываются дочерним компонентом SwTableColumn. Columns are defined with the child SwTableColumn component.

Свойства SwTable / SwTable Properties

ИмяТипПо умолчаниюЗначения/Описание
dataArrayrequiredДанные таблицы — массив объектов.
resizableBooleantrueРазрешить изменение ширины колонок перетаскиванием края заголовка.
maxWidthString | NumberМаксимальная ширина контейнера таблицы. При переполнении — горизонтальный скролл и активация fixed-колонок.

События SwTable / SwTable Events

ИмяПараметрыdОписание
column-resize{ prop, width }Срабатывает после изменения ширины колонки (в px).

Свойства SwTableColumn / SwTableColumn Properties

ИмяТипПо умолчаниюЗначения / Описание
propStringКлюч поля в объекте строки. Поддерживает вложенные пути: speed.midl.
labelString''Заголовок колонки.
widthString | Number'auto'Ширина колонки, например 180 или '180px'.
heightString | Number'auto'Минимальная высота ячейки заголовка.
resizableBooleanРазрешить ресайз конкретной колонки. По умолчанию наследует resizable таблицы.
minWidthString | Number48Минимальная ширина при ресайзе (px).
fixedString'left' | 'right' — фиксация колонки при горизонтальном скролле.

SwTableColumn без prop используется как групповой заголовок; внутри него задаются дочерние SwTableColumn. A SwTableColumn without prop is a group header; place child SwTableColumn components inside it.

Подсветка при наведении / Hover highlight

  • Row — при наведении на строку в tbody подсвечиваются все её ячейки (учитывается rowspan).
  • Column — при наведении на ячейку заголовка подсвечивается весь столбец; для группового заголовка с colspan — все вложенные колонки.

Стили подсветки заданы в component-sw.css (классы row-hover, col-hover).

Фиксированные колонки / Fixed columns

Фиксация включается, когда одновременно: 1. задан max-width у SwTable; 2. у колонок указан fixed="left" или fixed="right"; 3. суммарная ширина таблицы превышает контейнер. Групповой заголовок фиксируется, если все его дочерние колонки имеют одинаковое значение fixed.

Слоты / Slots

#<prop> — именованный слот для конкретной колонки (приоритет выше cell). Параметры: { row, $index, value } #cell — универсальный слот для всех колонок (default-слот занят SwTableColumn). Параметры: { row, $index, column, value }

  • row — весь объект строки данных
  • $index — индекс строки (начиная с 0)
  • column — имя колонки (prop)
  • value — значение ячейки

Пример использования / Example Usage

Базовый пример с вложенными колонками:

<script>
    let table = [
        {city:{label:'Moscow', rowspan:2},district:'Center',speed:{max:80,min:50,midl:70}},
        {city:'Moscow',district:'MRCR',speed:{max:130,min:90,midl:120}},
    ]
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="table">
  <sw-table-column label="Label">
      <sw-table-column label="City" prop="city"/>
      <sw-table-column label="District" prop="district"/>
  </sw-table-column>
  <sw-table-column label="Speed" prop="speed.midl"/>
</sw-table>

Ресайз колонок:

<script setup>
const users = [
  { name: 'Иван', age: 25 },
  { name: 'Мария', age: 30 },
  { name: 'Петр', age: 35 }
]

function onColumnResize({ prop, width }) {
  console.log(prop, width)
}
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="users" @column-resize="onColumnResize">
  <sw-table-column prop="name" label="Имя" width="180px" />
  <sw-table-column prop="age" label="Возраст" width="100px" />
  <sw-table-column
    prop="actions"
    label="Действия"
    width="150px"
    :resizable="false"
  />
</sw-table>

Фиксированные крайние колонки:

<script setup>
const rows = [
  { id: 1, name: 'Иван', email: 'ivan@example.com', note: 'Примечание 1' },
  { id: 2, name: 'Мария', email: 'maria@example.com', note: 'Примечание 2' },
  { id: 3, name: 'Петр', email: 'petr@example.com', note: 'Примечание 3' }
]
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="rows" max-width="520px">
  <sw-table-column prop="id" label="ID" width="70px" fixed="left" />
  <sw-table-column prop="name" label="Имя" width="160px" fixed="left" />
  <sw-table-column prop="email" label="Email" width="200px" />
  <sw-table-column prop="note" label="Примечание" width="180px" fixed="right" />
</sw-table>

Пример с v-for для динамических колонок:

<script setup>
import { ref } from 'vue'

const columns = ref([
  { prop: 'name', label: 'Имя', width: '150px' },
  { prop: 'age', label: 'Возраст', width: '100px' },
  { prop: 'email', label: 'Email', width: '200px' }
])

const tableData = ref([
  { name: 'Иван', age: 25, email: 'ivan@example.com' },
  { name: 'Мария', age: 30, email: 'maria@example.com' },
  { name: 'Петр', age: 35, email: 'petr@example.com' }
])
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="tableData">
  <sw-table-column 
    v-for="column in columns" 
    :key="column.prop"
    :prop="column.prop"
    :label="column.label"
    :width="column.width"
  />
</sw-table>

Пример с кастомизацией через слоты:

<script setup>
import { ref } from 'vue'

const users = ref([
  { id: 1, name: 'Иван Петров', age: 25, status: 'active', email: 'ivan@example.com' },
  { id: 2, name: 'Мария Сидорова', age: 30, status: 'inactive', email: 'maria@example.com' },
  { id: 3, name: 'Петр Иванов', age: 35, status: 'active', email: 'petr@example.com' }
])

const deleteUser = (id) => {
  console.log('Delete user:', id)
}
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="users">
  <sw-table-column prop="name" label="Имя" />
  <sw-table-column prop="age" label="Возраст" />
  <sw-table-column prop="status" label="Статус" />
  <sw-table-column prop="actions" label="Действия" width="150px" />
  
  <!-- Именованный слот для конкретной колонки -->
  <template #name="{ row, value }">
    <strong>{{ value }}</strong>
  </template>
  
  <template #age="{ value }">
    <span style="color: blue">{{ value }} лет</span>
  </template>
  
  <template #status="{ value }">
    <span :style="{ color: value === 'active' ? 'green' : 'red' }">
      {{ value === 'active' ? '✓ Активен' : '✗ Неактивен' }}
    </span>
  </template>
  
  <!-- Default слот для колонки actions -->
  <template #actions="{ row }">
    <button @click="deleteUser(row.id)">Удалить</button>
    <a :href="`mailto:${row.email}`">Написать</a>
  </template>
</sw-table>

Пример с универсальным слотом cell:

<script setup>
import { ref } from 'vue'

const products = ref([
  { name: 'Товар 1', price: 1000, quantity: 5 },
  { name: 'Товар 2', price: 2500, quantity: 3 },
  { name: 'Товар 3', price: 750, quantity: 10 }
])
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="products">
  <sw-table-column prop="name" label="Название" />
  <sw-table-column prop="price" label="Цена" />
  <sw-table-column prop="quantity" label="Количество" />

  <template #cell="{ column, value }">
    <span v-if="column === 'price'" style="font-weight: bold">
      {{ value }} ₽
    </span>
    <span v-else-if="column === 'quantity' && value < 5" style="color: red">
      {{ value }} ⚠️ Мало
    </span>
    <span v-else>{{ value }}</span>
  </template>
</sw-table>

Пример с объединением ячеек (rowspan/colspan):

<script setup>
import { ref } from 'vue'

const complexData = ref([
  {
    city: { label: 'Москва', rowspan: 2 },
    district: 'Центр',
    population: 500000
  },
  {
    city: 'Москва', // будет скрыта из-за rowspan
    district: 'Север',
    population: 300000
  },
  {
    city: { label: 'Общая статистика', colspan: 2 },
    population: 800000
  }
])
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="complexData">
  <sw-table-column label="Город" prop="city" />
  <sw-table-column label="Район" prop="district" />
  <sw-table-column label="Население" prop="population" />
</sw-table>