[Vuejs]-Vue.js 2: How the reusing element logic works in `v-if` `v-else-if` (Why it does not work on nested element)

1👍

In MVVM world the better option is not to rely on framework in sence that it re-uses things like we see it, but to use "VM" and explicitly bind data in component templates. The idea is not to re-use DOM as much as possible (actually, I never rely on that), but "to connect" input values to each other so no matter if they’re re-used or not, visually they’ll always display same data

What you have to do is to define state property in component and attach it to both inputs using "v-model" directive:

<template>
    <div v-if="loginType === 'username'">
        <label>Username: </label>
        <input v-model="userLogin" />
    </div>
    <div v-else>
        <label>Email: </label>
        <input v-model="userLogin" />
    </div>

    <button @click="changeLoginType()">Change Username</button>
</template>

<script>
export default {
    name: 'App',
    data: () => {
        return { loginType: 'email', userLogin: '' };
    },
    methods: {
        changeLoginType() {
            if (this.loginType === 'email') this.loginType = 'username';
            else this.loginType = 'email';
        },
    },
};
</script>

In this scenario no metter which of options you choose, your input value would always take value from component state and changes in input would be reflected in state (so-called 2-way data binding)

Also, interesting thing here is that when I played with initial code sample in newly created application using Vue 3 – input value was always reset when clicking the button and changing login type. So, no matter how it behaves in Vue 2, in newer versions of Vue things could change and previously working code could fail, so it’s definitely better to define things explicitly in terms of long-term project support

0👍

The key attribute is key when using v-for but it also helps with v-if/v-else. It prevents Vue from reusing the same DOM node.
You should try something like this:

<template>
  <div>
    <label for="account">{{ loginType === 'username' ? 'Username' : 'E-mail' }}</label>
    <input id="account" v-model.trim="usernameOrEmail" :type="loginType === 'username' ? 'text' : 'email'">
  </div>
</template>

0👍

As in Vue, You have to pass the inputs value from View to Model or vice versa (two way data binding) and to achieve this you need v-model directive of Vue.

Now, To achieve the requirement you have to just bind the input value to a variable and then reset/clear it on the changeLoginType() method.

Live Demo :

new Vue({
  el: '#app',
  data: {
    loginType: "email",
    inputVal: ''
  },
  methods: {
    changeLoginType() {
      this.inputVal = '';
      this.loginType = this.loginType === 'email' ? 'username' : 'email';
    }
  }
})
<div id="app">
  <div v-if="loginType === 'username'">
    <label>Username: </label>
    <input v-model="inputVal"/>
  </div>
  <div v-else>
    <label>Email: </label>
    <input v-model="inputVal"/>
  </div>
  <button @click=changeLoginType>Change Username</button>
</div>

Leave a comment