Reputation: 323
I have a key inside my components data that may be initialised as null or have some strings inside. I want to be able to create as many associatedKeys as I want, while also allowing for it to be initialised as null or with multiple values. The problem I'm having is that each time I am pressing the button to add a new input field, the page is re rendering and the data is then reset once initialised again.
I have been looking at this article, I have placed a debugger inside the addKeys function and am getting the error message this.licence.associatedKeys.$set is not a function
. I don't understand this error and am not sure how to add elements to the associatedKeys array
<template>
<div>
<form>
<label>Associated Keys</label>
<button v-on:click="addNewKey">Add new key</button>
<div v-for="(k,index) in licence.associatedKeys" :key="k">
<input type="text" :value="k" @input="licence.associatedKeys[index]=$event.target.value">
</div>
</form>
</div>
</template>
<script>
import util from '~/assets/js/util'
export default {
methods: {
addNewKey() {
this.licence.associatedKeys.$set(this.licence.associatedKeys, null)
}
},
data: () => ({
licence: {
associatedKeys: []
}
})
}
</script>
Upvotes: 2
Views: 64
Reputation: 5075
Have a look at event modifiers, specifically this example:
<!-- the submit event will no longer reload the page -->
<form v-on:submit.prevent="onSubmit"></form>
I think this is what you need to stop the page reloading.
As for the undefined error: you can try to use the instance itself, i.e.
this.$set('license.associatedKeys[' + this.license.associatedKeys.length + ']', null);
Also, you probably misread the documentation, the .$set
and .$add
methods on nested data properties take key and value arguments. So, you should have written
this.licence.associatedKeys.$set(this.licence.associatedKeys.length, null)
Upvotes: 1
Reputation: 35724
the reason you get a redirect is that you have a button inside a form. While other browsers don't, Chrome will treat it as a redirect by default. The easiest way to resolve it is to define an action action="#"
that way, you don't have to handle every button to prevent default action.
@input
is fine, but vue has a lot of built-in functionality, such as v-model
that will automatically bind value, showing and updating it on change.
you don't need to use $set
when you're pushing (plus you set it on the vue instance and not the value (this.$set(this.myVal, 'myKey', null)
instead of this.myVal.myKey.$set(null)
)
finally, if you want key-value pair stored in an array, you need two objects the key and the value
new Vue({
el: "#app",
methods: {
addNewKey() {
//this.licence.associatedKeys.$set(this.licence.associatedKeys, null)
this.licence.associatedKeys.push({key:null, val:null});
}
},
data: () => ({
licence: {
associatedKeys: []
}
})
})
body {background: #20262E;padding: 20px;font-family: Helvetica;}
button {padding: 8px 16px;border-radius: 20px;border: none;}
#app {background: #fff;border-radius: 4px;padding: 20px;transition: all 0.2s;}
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
<div>
<form action="#">
<label>Associated Keys</label>
<button v-on:click="addNewKey">Add new key</button>
<div v-for="(k,index) in licence.associatedKeys" :key="k">
<input type="text" v-model="k.key">
<input type="text" v-model="k.val">
</div>
</form>
</div>
<pre>{{this.licence}}</pre>
</div>
Upvotes: 1