2

Does anybody know of a library or an already described pattern for achieving two way data binding in forms when using Vuex ORM?

I've found a couple of libraries for helping with this with Vuex, but none specifically for Vuex-ORM yet:

John Rix
  • 6,271
  • 5
  • 40
  • 46

2 Answers2

4

I don't think there is any predefined plugin to do this, but you should be able to do the same for typical Vuex states using setter and getter on computed property...?

import User from '@/models/User'

export default {
  computed: {
    user: {
      get () {
        return User.find(1)
      },

      set (value) {
        User.update({
          where: 1,
          data: {
            name: value
          }
        })
      }
    }
  }
}
Kia Ishii
  • 146
  • 1
  • 4
  • Thanks @KiaIshii. I'm hoping to find a way to do this without repeating myself for every field in potentially large forms. Have only recently starting using the Vue ecosystem, but if I come up with a clean solution, I'll be sure to share it for comment! – John Rix Aug 02 '19 at 11:10
  • Thanks! That would be awesome! – Kia Ishii Aug 06 '19 at 12:36
1

Following Kia Ishii's idea, I came up with a function that I invoke to generate computed properties for all fields of a vuex-orm model. Because I use uuids, I can use insertOrUpdate.

This function creates a configuration for a Vue Component that reads and writes fields from a vuex-orm Model. The configuration contains computed properties for all fields of the model, to allow two-way data bindings with the v-model attribute. It also contains a props option with an id field, so the component needs to be associated with a router-view.

import {v4 as uuidv4} from 'uuid';

/**
 * @param {typeof import("@vuex-orm/core").Model} model
 * @returns {{props: Object, computed: Object}}
 * @this {VueComponent}
 */
export default model => {

  const fields = model.fields();
  const computed = {};
  for (const field in fields) {
    if (field !== 'id') {
      computed[field] = {
        get() {
          const item = model.find(this.$props.id);
          return item ? item[field] : fields[field].value;
        },
        set(value) {
          model.insertOrUpdate({
            data: {
              id: this.$props.id,
              [field]: value
            }
          });
        }
      };
    }
  }

  return {
    props: {
      id: {
        type: String,
        default: uuidv4
      }
    },
    computed
  };

};
ahocevar
  • 5,448
  • 15
  • 29
  • Thanks for posting this @ahocevar, looks quite useful. Suggest adding an example of its invocation within a component also. After posting this question, I also came up with a somewhat similar solution, based off of the vuex-map-fields library. I've been wanting to polish it a little before posting it back here, but yours looks good too. – John Rix Feb 10 '20 at 09:31