logdog90
@logdog90

Возможно ли добавить кнопки в массив динамически и навешать на них клик?

Как добавить в данные вложенный массив с кнопками и повесить на них обработчик клика?

<template>
  <div class="employees">
    <table class="employees-table">
      <thead class="employees-header">
        <tr class="employees-row">
          <th class="employees-column" v-for="title in titles" :key="title.id">
            {{ title.label }}
          </th>
        </tr>
      </thead>
      <tbody class="employees-body">
        <tr
          class="employees-row"
          v-for="employee in employees"
          :key="employee.id"
        >
          <td
            class="employees-column"
            v-for="title in titles"
            :key="title.id"
            :data-label="title.label"
          >
            {{ employee[title.key] }}
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  data: () => ({
    titles: [
      { key: "name", label: "ФИО" },
      { key: "department", label: "Отдел" },
      { key: "position", label: "Должность" },
      { key: "hostname", label: "Имя ПК" },
      { key: "username", label: "Учётка" },
      { key: "actions", label: "Действия" }
    ],
    employees: [
      {
        name: "Пупкин Иван Петрович",
        department: "Отдел маркетинга",
        position: "Контент-менеджер",
        hostname: "of-vl-mar-001",
        username: "mar.001",
        actions: [] // Здесь должны быть кнопки, например редактировать и удалить 
      },
      {
        name: "Макиевская Ольга Николаевна",
        department: "Отдел маркетинга",
        position: "Дизайнер",
        hostname: "of-vl-mar-002",
        username: "mar.002",
        actions: [] // Здесь должны быть кнопки, например редактировать и удалить
      }
    ],
  }),
};
</script>

<style scoped>
.employees {
  display: flex;
  justify-content: center;
}

table {
  border: 1px solid #ccc;
  border-collapse: collapse;
  margin: 30px 0 0 0;
  padding: 0;
  width: 100%;
  table-layout: fixed;
}

table tr {
  border: 1px solid #4c9bf4;
  padding: 0.35em;
}

table th,
table td {
  padding: 0.625em;
  text-align: center;
}

table th {
  background-color: rgba(0, 113, 240, 0.7);
  font-size: 0.85em;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #fff;
}

.bi-x-circle-fill {
  color: red;
}

.bi-pencil-square {
  color: rgba(124, 124, 124, 0.7);
}

@media screen and (max-width: 600px) {
  table {
    border: 0;
    margin-top: 20px;
  }

  table thead {
    border: none;
    clip: rect(0 0 0 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
  }

  table tr {
    border-bottom: 3px solid rgba(0, 113, 240, 0.7);
    display: block;
    margin-bottom: 0.625em;
  }

  table td {
    border-bottom: 1px solid rgba(0, 113, 240, 0.7);
    display: block;
    font-size: 0.8em;
    text-align: right;
  }

  table td::before {
    /*
    * aria-label has no advantage, it won't be read inside a table
    content: attr(aria-label);
    */
    content: attr(data-label);
    float: left;
    font-weight: bold;
    text-transform: uppercase;
  }

  table td:last-child {
    border-bottom: 0;
  }
}
</style>
  • Вопрос задан
  • 104 просмотра
Решения вопроса 1
0xD34F
@0xD34F Куратор тега Vue.js
Действия пусть будут представлены в виде массива строк:

data: () => ({
  employees: [
    { ..., actions: [ 'delete', 'ещё что-то', 'и ещё' ] },
    ...
  ],
  ...

Таблицу оформить как отдельный компонент; для каждого из столбцов выделить отдельный слот, в который будут передаваться данные строки и столбца, их индексы; по умолчанию слоты выводят данные как они есть:

props: {
  columns: Array,
  data: Array,
},

<table>
  <thead>
    <tr>
      <th v-for="(col, colIndex) in columns" :key="col.key">{{ col.label }}</th>
    </tr>
  </thead>
  <tbody>
    <tr v-for="(row, rowIndex) in data" :key="row.id">
      <td
        v-for="col in columns"
        :key="col.key"
        :data-label="col.label"
      >
        <slot
          :name="`column.${col.key}`"
          :col-data="col"
          :col-index="colIndex"
          :row-data="row"
          :row-index="rowIndex"
        >
          {{ row[col.key] }}
        </slot>
      </td>
    </tr>
  </tbody>
</table>

Ну а дальше просто передавайте в слот столбца actions соответствующие кнопки:

<v-table :columns="titles" :data="employees">
  <template #column.actions="{ rowData, rowIndex }">
    <div>
      <button
        v-for="action in rowData.actions"
        v-text="action"
        @click="onActionClick(action, rowData, rowIndex)"
      ></button>
    </div>
  </template>
</v-table>

methods: {
  onActionClick(action, row, index) {
    switch (action) {
      case 'delete':
        this.employees.splice(index, 1);
        return;

      case 'ещё что-то':
        this.сделатьЧтоТоЕщё(row);
        return;
    }
  },
  ...
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы