I just started working with Vue.js and I'm facing some issues with the Vue.js reactive datasources.
The following code should be able to add and remove a row containing a textfield and a textarea in the parent element.
ElementsView.vue
<template>
<div>
<label></label>
<br>
<small class='text-muted'></small>
<br>
<div class='marks_content'>
<div class='row' v-for="(item, index) in marks" v-bind:key="index">
<div class='col-md-12 mark_header_container'>
<div class="numerator-element">
<span class="numerator-content">{{ index + 1 }}</span>
</div>
<div class="remove-button" v-on:click="removeMark(index)">
</div>
</div>
<div class='col-md-6'>
<TextField :element-id='"term_textfield" + index' :message="item.term" type='text' placeholder="Kenmerk / element / fase"></TextField>
</div>
<div class='col-md-6'>
<TextField :element-id='"desc_textfield" + index ' :optional="true" :message="item.description" type='text' placeholder="Beschrijving (optioneel)" multiline="true"></TextField>
</div>
</div>
</div>
<div class='row'>
<div class='col-md-6'>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="order_check">
<label class="form-check-label" for="order_check">Volgorde van belang (bij fases)</label>
</div>
</div>
<div class='col-md-6 right_column'>
<a href="#" v-on:click="addMark">Nieuwe rij toevoegen</a>
</div>
</div>
</div>
</template>
<script>
import TextField from './TextField.vue'
export default {
props: ['elements'],
name: 'ElementsView',
components: {
TextField
},
data() {
return {
marks: [{}]
}
},
mounted() {
if (this.elements) {
if (this.elements.length > 0) {
this.marks = this.elements;
}
}
},
methods: {
addMark: function (e) {
this.marks.push({ 'term': '', 'description': ''}); //I thought the issue might be related to having undefined values, so I changed it to empty strings
},
removeMark: function(index) {
//this.marks = [{ 'term': 'term1', 'description': 'desc1'}, { 'term': 'term12', 'description': 'desc13'}]
this.marks.splice(index, 1);
}
}
}
</script>
TextField.vue
<template>
<div class="form-group">
<label v-if="title" :for="elementId">{{title}}</label>
<textarea v-if="multiline" v-bind:class="{ optional: optional }" rows="1" :type="type" class="form-control" :id="elementId" :aria-describedby="elementId + '_help'" :placeholder="placeholder" v-model="messageValue"></textarea>
<Input :value="message" v-bind:class="{ optional: optional }" v-else rows="1" :type="type" class="form-control" :id="elementId" :aria-describedby="elementId + '_help'" :placeholder="placeholder"/>
<small v-if="help" :id="elementId + '_help'" class="form-text text-muted">{{help}}</small>
</div>
</template>
<script>
import autosize from 'autosize';
export default {
props: ['elementId', 'type', 'title', 'help', 'placeholder', 'multiline', 'message', 'optional'],
name: 'TextField',
data() {
return {
messageValue: this.message
}
},
mounted() {
var root = this.$el;
var textAreas = root.getElementsByTagName("TextArea");
if (textAreas.length > 0) {
var area = textAreas[0];
autosize(area);
}
}
}
</script>
I want to have an empty row at the starting point, indicated by the marks: [{}] in the code. Whenever a user wants to add a new row a new empty json object is added to the array. This works fine, however deleting the object causes errors.
The array consist of empty objects that are not bind to any input in the row elements, therefore the array consists of empty JSON objects. Because of this I would expect the interface to rerender the number of row elements - 1 after an element is deleted and do not show any text that was written by the user earlier.
This is not the case, the input that the user earlier entered remains visible even though the new objects are empty. This happens for both the addMark function (which is not problem, but not what I expected) and happens for the removeMark function (I see a random row disappear).
Originally I assumed that it was necessary to update the data that the list relies on before mutating it as this would force it to be redrawn with the array from the data object.
In order to test this assumption, I tried to assign a different array in the removeMark function (just for testing purposes) and see what happens. When the input is not modified this seems to work partly but when the input is modified this new array value is being overwritten.
Can someone please point out what I'm doing wrong?