2

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>
1
  • there's a couple issues here, but can you write what your ideal result would be? Commented Sep 12, 2018 at 14:55

2 Answers 2

1

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>

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your answer and fiddle, it was very easy to see what was going on after. I had completely overlooked chrome refreshing the page on pressing a button inside a form and wasn't sure if I could/how to use v-model inside a loop. Keep up the good work
1

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.