Переключение текста в каждой ячейке b-таблицы в поле ввода и обратно - PullRequest
0 голосов
/ 22 февраля 2020

Новичок в vue и до сих пор мне это нравится. В основном, пытаясь использовать таблицы BV, чтобы создать Excel как макет таблицы. Когда я щелкаю по тексту ячейки, я хочу, чтобы он был заменен полем ввода и вернулся к тексту при размытии. Насколько я понимаю, сортировка по полям ввода не работает, поэтому скрытие казалось лучшим вариантом.

Этот код технически работает (не знаю, как на самом деле запустить его в редакторе кода SO), но я стараюсь не иметь поле isHidden для каждого поля. В настоящее время мне потребуется isHiddenStartTime и isHiddenEndTime плюс 1 для каждого другого поля. Учитывая, что только один флаг должен быть нужен одновременно, это выглядит грязно.

new Vue({
  el: "#app",
  data() {
    return {
      fields: [
        {
          key: 'startTime',
          sortable: true
          },
        {
          key: 'endTime',
          sortable: true
        }
      ],
      port: [
        {
          "portNumber": 1,
          "startTime": "00:00:00.00",
          "endTime": "21:59:59.01",
          "isHidden": false,
          "hiddenType": ""
        }, 
        {
          "portNumber": 7,
          "startTime": "00:00:00.00",
          "endTime": "22:59:59.00",
          "isHidden": false,
          "hiddenType": ""
        }
      ]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.5.0/dist/bootstrap-vue.js"></script>

<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css" />

<div id="app">
  <b-table  :items="port" :fields="fields" striped fixed responsive="sm">
    <template v-slot:cell(endTime)="{ item }">
      <div v-if="!item.isHidden" @click="item.isHidden = true">
        {{ item.endTime }}
      </div>
      <div v-else>
        <b-form-input 
          v-model="item.endTime" 
          @blur="item.isHidden = false" 
          placeholder="Enter end time" 
          autofocus
        ></b-form-input>
      </div>
    </template>
  </b-table>
</div>

Я пытался добавить hiddenType с именем поля, добавляемого при щелчке, но v-if запускается до щелчка. Если я использую тот же флаг (port.isHidden), вся строка изменяется. Если я поставлю флажок в полях, весь столбец изменится. Учитывая, что это список, я не вижу правильного способа использования ref.

Опять же, новый для просмотра, все вопросы имеют смысл, я просто не могу найти чистый способ заставить его работать.

1 Ответ

2 голосов
/ 22 февраля 2020

Вместо того, чтобы иметь свойство isHidden для каждого поля, вы можете создать свойство, содержащее текущее поле, которое вы редактируете.

В приведенном ниже примере я создаю свойство isEditingField и задаю что до key столбца, так что либо startTime, либо endTime. Затем при размытии я просто снова удаляю свойство из объекта с помощью $delete.

Важно, чтобы вы использовали $set для создания нового свойства, если оно еще не существует в объекте, иначе оно не будет быть реактивным. Вы можете прочитать больше об этом [здесь]. (https://vuejs.org/v2/guide/reactivity.html#Change -Detection-Caveats )

Вы также можете заметить, что я использую v-slot:cell() без указания поля. Это связано с тем, что это резервный слот, в который вставляются все поля, которые не специально выделены. Таким образом, в этом случае он будет учитываться для всех слотов без необходимости создавать определенный c один для каждого.

new Vue({
  el: "#app",
  data() {
    return {
      fields: [
        {
          key: 'startTime',
          sortable: true
          },
        {
          key: 'endTime',
          sortable: true
        }
      ],
      port: [
        {
          "portNumber": 1,
          "startTime": "00:00:00.00",
          "endTime": "21:59:59.01",
          "hiddenType": ""
        }, 
        {
          "portNumber": 7,
          "startTime": "00:00:00.00",
          "endTime": "22:59:59.00",
          "hiddenType": ""
        }
      ]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.5.0/dist/bootstrap-vue.js"></script>

<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css" />

<div id="app">
  <b-table  :items="port" :fields="fields" striped fixed responsive="sm">
    <template v-slot:cell()="{ item, field: { key } }">
      <div v-if="item.isEditingField == key">
        <b-form-input 
          v-model="item[key]" 
          @blur="$delete(item, 'isEditingField')" 
          placeholder="Enter end time" 
          autofocus
        ></b-form-input>
      </div>
      <div v-else @click="$set(item, 'isEditingField', key)">
        {{ item[key] }}
      </div>
    </template>
  </b-table>
</div>
...