wawanopoulos
wawanopoulos

Reputation: 9804

VueJS: v-model on <span> element ? How to handle that?

I have this simple component displaying user info:

<div class="m-card-user__details">
  <span class="m-card-user__name m--font-weight-500">
    {{ firstname }} {{ lastname }}
  </span>
  <a class="m-card-user__email m--font-weight-300 m-link">
    {{ loginEmail }}
  </a>
</div>

Script

<script>
export default {
  data () {
    return {
      loginEmail : this.$store.getters.user.loginEmail,
      firstname: this.$store.getters.user.firstName,
      lastname: this.$store.getters.user.lastName,
    }
  }
};
</script>

Problem is that if another component change the value of the firstname property in the VueX store, I see that the value is well updated on the store but not on my component here..

How can i set the 2 ways bindings on a element ?

Upvotes: 1

Views: 10245

Answers (2)

Dominik Bucher
Dominik Bucher

Reputation: 1509

You can also directly use $store in your template.

<div class="m-card-user__details">
  <span class="m-card-user__name m--font-weight-500">
    {{ $store.getters.user.firstName }} {{ $store.getters.user.lastName }}
  </span>
  <a class="m-card-user__email m--font-weight-300 m-link">
    {{ $store.getters.user.loginEmail }}
  </a>
</div>

I haven't tried if this works with getters, but I don't see a reason why it wouldn't. Now you could maybe argue it's an anti-pattern, but I'd prefer it over having a computed property solely for this purpose.

See also https://github.com/vuejs/vuex/issues/306.

Edit: Because you mention 2-way binding: You shouldn't do this to update the $store, use actions and mutations instead. In this case, it's fine as it's essentially a 1-way binding where the state flows to the innerHTML of your <span>s.

Upvotes: 0

Fusseldieb
Fusseldieb

Reputation: 1374

Attaching a store variable directly to data() will break the 2-way-binding.

Use a computed property for that, like:

computed: { 
  loginEmail() { 
    return this.$store.getters.user.loginEmail;
  }
} 

and then use the computed on the span, like {{ loginEmail }}, as you would normally.


Improvement: If you want, you can return the entire ...getters.user (as a object) with computed, like:

computed: { 
  user() { 
    return this.$store.getters.user;
  }
} 

and then use it on your span like {{ user.loginEmail }} and so on.

This will save you some lines, increase readability and possibly a tiny bit of performance.

Upvotes: 4

Related Questions