如何在不影响其他行的情况下删除该行

时间:2019-09-12 11:38:27

标签: vue.js vuejs2 axios vue-component delete-row

我正在创建一个VueJs父组件,该组件可以动态创建行,并且该组件调用另一个可以使用axios填充2个下拉列表的组件。 一类 第二个用于子类别(此下拉列表可能取决于第一个)

这是添加行的第一个组件

<template>
  <div>
    <ul>
      <li v-for="(input, index) in inputs" :key="index">
        <request-part :index="index" :input="input" :inputs="inputs">
        </request-part>
        <hr />
      </li>
    </ul>
    <button
      type="button"
      @click="addRow"
      class="btn font-montserrat-regular btn-success btn-plus bt-radius-add"
    >
      Onderdeel toevoegen
    </button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      category: null,
      selectedFile: null,
      subcategory: null,
      current: 0,
      id: 0,
      inputs: [],
      categories: [],
      subcategories: []
    }
  },
  mounted() {
    axios.get('/api/categories').then(res => {
      this.categories = res.data
    })
  },
  created() {
    this.addRow()
  },
  methods: {
    addRow() {
      this.inputs.push({
        category: '',
        subcategory: '',
        sku: '',
        description: '',
        image: ''
      })
    },
    onFileChanged(event) {
      this.selectedFile = event.target.files[0]
    }
  }
}
</script>

这是填充下拉菜单的第二个组件

<template>
  <div class="border-0">
    <div class="row">
      <div class="col-md-8">
        <div class="form-group ml-2">
          <label class="gray-text-color font-montserrat-regular" :for="part">
            {{ $t('labels.frontend.request.part') }} *
          </label>
          <div class="form-group brd3">
            <select
              :name="'r[' + index + '][category]'"
              :id="category + index"
              class="form-control light-gray-background arrow-select-position request-input"
              v-model="input.category"
              @change="onchangeCategorie"
              required
            >
              <option :value="null" disabled selected>
                {{ $t('labels.account.create.selectCategory') }}
              </option>
              <option
                v-for="(option, index1) in categories"
                :value="index1"
                :key="index1"
              >
                {{ option }}
              </option>
            </select>
          </div>
          <div class="form-group brd3">
            <select
              :name="'r[' + index + '][subcategory]'"
              :id="subcategory + index"
              class="form-control light-gray-background arrow-select-position request-input"
              v-model="input.subcategory"
              required
            >
              <option :value="null" disabled selected>
                {{ $t('labels.frontend.request.subCategory') }}
              </option>
              <option
                v-for="(option, index1) in subcategories"
                :value="index1"
                :key="option.id"
              >
                {{ option }}
              </option>
            </select>
          </div>
        </div>
      </div>
      <div class="col-md-4">
        <div class="form-group">
          <label class="gray-text-color font-montserrat-regular" :for="sku">
            {{ $t('labels.frontend.request.articleNumber') }}
          </label>
          <input
            type="text"
            :name="'r[' + index + '][sku]'"
            :id="'sku' + index"
            v-model="input.sku"
            class="form-control light-gray-background request-input"
          />
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-9">
        <div class="form-group" style="margin-right:-40px">
          <input
            type="text"
            :name="'r[' + index + '][description]'"
            v-model="input.description"
            class="form-control light-gray-background input-width-mobile request-input"
            placeholder="Toelichting (optioneel)"
          />
        </div>
      </div>
      <input
        :id="'image' + index"
        :name="'r[' + index + '][image]'"
        type="file"
        class="camera-button inputfile"
        :change="input.image"
        accept="image/*"
        @change="onFileChanged"
      />
      <label :for="'image' + index">
        <img
          src="../../../../../resources/assets/images/cameraIcon.png"
          alt="Camera icon"
          class="camera-button-position"
        />
      </label>
      <div class="pr-l-200 ft-14 mr-3">
        <label>{{ $t('labels.frontend.request.image') }}</label>
      </div>
      <div id="preview">
        <img v-if="url" :src="url" alt="no Image." />
        <button
          v-if="url != null"
          type="button"
          @click="url = null"
          class="btn fa fa-trash btn-default bt-radius"
        ></button>
      </div>
    </div>
    <button
      type="button"
      @click="deleteRow(index)"
      class="btn btn-danger fa fa-trash bt-radius"
    ></button>
  </div>
</template>

<script>
export default {
  props: {
    part: {
      type: String,
      default: null
    },
    sku: {
      type: String,
      default: null
    },
    description: {
      type: String,
      default: null
    },
    image: {
      type: String,
      default: null
    },
    index: {
      type: Number,
      default: 0
    },
    input: {
      type: Object,
      default: () => ({})
    },
    inputs: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      test: null,
      category: null,
      selectedFile: null,
      subcategory: null,
      categories: [],
      subcategories: [],
      url: null
    }
  },
  mounted() {
    axios.get('/api/categories').then(res => {
      this.categories = res.data
    })
  },
  methods: {
    deleteRow(index) {
      console.log(index)
      this.$delete(this.inputs, index)
    },
    onFileChanged(event) {
      this.selectedFile = event.target.files[0]
      this.input.image = this.selectedFile
      this.url = URL.createObjectURL(this.selectedFile)
    },
    onchangeCategorie(e) {
      axios.get('/api/categories/' + e.target.value).then(res => {
        this.subcategories = res.data
      })
    }
  }
}
</script>
<style>
#preview {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: auto;
}
#preview img {
  max-width: 200px;
  max-height: 200px;
  border-radius: 5px;
  border: 1px solid lightgray;
}
</style>

当我尝试从上到下删除第一行或任何行时,所有子类别都消失了。 当我从下到上删除行时,效果很好

1 个答案:

答案 0 :(得分:0)

您的问题是由以下事实引起的:您的行没有适当的稳定的唯一ID,而是在:key指令中将其数组索引用作v-for。这是有问题的原因,是当您使用.$delete()从数组中删除一个元素时,所有后面的元素都向下移动到一个新的较低索引,从而使数组保持连续。

解决方案是您的行一个唯一的ID。一个简单的全局计数器就可以了:

var counter = 0;  // global counter for row IDs (or anything else that needs one)

export default {
  // ...
  methods: {
    addRow() {
      this.inputs.push({
        category: '',
        subcategory: '',
        sku: '',
        description: '',
        image: '',
        id: ++counter  // this gives each row a distinct ID number
      })
    },
  // ...
}

然后,您可以将此唯一ID用作:key指令中的v-for

  <li v-for="(input, index) in inputs" :key="input.id">
    <request-part :index="index" :input="input" :inputs="inputs">
    </request-part>
    <hr />
  </li>
相关问题