0

this question is related to Two way data binding with Vuex-ORM

i tried using a watch with deep to handle a user form like this.

<template>
  <div id="app">
    <div style="display: inline-grid">
      <label for="text-1">Text-1: </label>
      <input name="text-1" type="text" v-model="user.name" />

      <label for="text-2">Text-2: </label>
      <input name="text-2" type="text" v-model="user.lastName" />

      <label for="text-3">Text-3: </label>
      <input name="text-3" type="text" v-model="user.birth" />

      <label for="text-4">Text-4: </label>
      <input name="text-4" type="text" v-model="user.hobby" />
    </div>
    <div>
      <h5>Result</h5>
      {{ userFromStore }}
    </div>
  </div>
</template>

<script>
import { mapGetters, mapMutations, mapActions } from "vuex";
export default {
  name: "App",
  computed: {
    ...mapGetters({
      userFromStore: "getUserFromStore",
      messageFromStore: "getMessage",
    }),
    user: function () {
      return this.userFromStore ?? {}; // basically "User.find(this.userId)" inside store getters
    },
  },
  watch: {
    user: {
      handler(value) {
        console.log('called')
      //  this.updateUser(value);
      },
      deep: true,
    },
  },
  methods: {
    ...mapActions({
      fetchUser: "fetchUser",
    }),
    ...mapMutations({
      updateUser: "updateUser",
    }),
  },
  created() {
    this.fetchUser();
  },
};
</script>

problem is my watcher is not watching, no matter what i try. as soon as the data came from Vuex-ORM my component is not able to watch on the getters user

Anyone idea why?

7
  • 1
    How do you mutate your object ? There are some caveats for object modification detection in Vue2: vuejs.org/v2/guide/reactivity.html#For-Objects Commented Apr 22, 2021 at 8:36
  • yeah i removed the mutation inside the watch. The problem is, i don't even come to the point where the mutation gets triggered. the watcher is doing nothing on input changes Commented Apr 22, 2021 at 9:07
  • It's not the mutation inside of the watch, it's the mutation that should trigger the watch that you should look for. Commented Apr 22, 2021 at 9:08
  • 1
    Not sure how vuex ORM works, but why do you not watch for userFromStore directly ? Let's remove the behavior of the computed from the equation. Also, quick tip, you can write all your vuex getters/actions and so on, like this: ...mapGetters(['getUserFromStore']) rather than the object form, if you do not want to rename it. Commented Apr 22, 2021 at 9:12
  • 1
    Maybe this thread can be somehow helpful: github.com/vuex-orm/vuex-orm/issues/197 Commented Apr 22, 2021 at 9:14

1 Answer 1

1

User.find(...) returns a model. The properties of that model are not reactive i.e. you cannot perform two-way data binding on items that are not being tracked. Hence your watcher will not trigger.

My advice would be to push your user data as props to a component that can handle the data programmatically.

Or, by way of example, you can simply handle two-way binding manually:

Vue.use(Vuex)

class User extends VuexORM.Model {
  static entity = 'users'

  static fields() {
    return {
      id: this.number(null),
      name: this.string(''),
      lastName: this.string(''),
      birth: this.string(''),
      hobby: this.string('')
    }
  }
}

const db = new VuexORM.Database()
db.register(User)

const store = new Vuex.Store({
  plugins: [VuexORM.install(db)]
})

User.insert({
  data: {
    id: 1,
    name: 'John',
    lastName: 'Doe',
    birth: '12/12/2012',
    hobby: 'This, that, the other'
  }
})

Vue.component('user-input', {
  props: {
    value: { type: String, required: true }
  },
  template: `<input type="text" :value="value" @input="$emit('input', $event.target.value)" placeholder="Enter text here...">`
})

new Vue({
  el: '#app',
  computed: {
    user() {
      return User.find(1)
    }
  },
  methods: {
    update(prop, value) {
      this.user.$update({
        [prop]: value
      })
    }
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vuex.min.js"></script>
<script src="https://unpkg.com/@vuex-orm/[email protected]/dist/vuex-orm.global.prod.js"></script>

<div id="app">
  <div v-if="user" style="display: inline-grid">
    <label for="text-1">Name: </label>
    <user-input
      id="text-1"
      :value="user.name"
      @input="update('name', $event)"
    ></user-input>

    <label for="text-2">Last name: </label>
    <user-input
      id="text-2"
      :value="user.lastName"
      @input="update('lastName', $event)"
    ></user-input>

    <label for="text-3">D.O.B: </label>
    <user-input
      id="text-3"
      :value="user.birth"
      @input="update('birth', $event)"
    ></user-input>

    <label for="text-4">Hobby: </label>
    <user-input
      id="text-4"
      :value="user.hobby"
      @input="update('hobby', $event)"
    ></user-input>
  </div>
  <pre>User in store: {{ user }}</pre>
</div>

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

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.