Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Computed properties still empty, when state is changed #41

Open
meliborn opened this issue Sep 10, 2018 · 9 comments
Open

Computed properties still empty, when state is changed #41

meliborn opened this issue Sep 10, 2018 · 9 comments

Comments

@meliborn
Copy link

Not sure it's a vuex-map-fields problem but...
I have a simple form and submit button. I do axios call to send data to the server. The problem is, when I type something into form input, property still empty, when store is up to date.
I'm using chrome plugin to debug values:
111
Here is a store:

222
So when I submit the form it always clear filled values. What's wrong?

@maoberlehner maoberlehner self-assigned this Sep 10, 2018
@maoberlehner
Copy link
Owner

Hey @meliborn,

without seeing any code, there is nothing I can do for you ;)

Please provide a reduced test case (you can use https://codesandbox.io/ for example) or at least copy and paste the relevant code (the computed section of your component and the getters and mutations sections of your store). Thanks!

@meliborn
Copy link
Author

@maoberlehner

computed: {
    companyExist(){
      return this.$store.state.company.current.id;
    },
    ...mapFields('company', [
      'current.name',
      'current.description',
      'current.company_type',
    ]),
  },
// initial state
import { getField, updateField } from "vuex-map-fields";
import { LOAD_COMPANY } from "@/store/action-types";
import { SET_COMPANY } from "@/store/mutation-types";
import axios from "axios";

export default {
  namespaced: true,
  state: {
    current: {}
  },
  getters: {
    getField
  },
  mutations: {
    updateField,
    [SET_COMPANY](state, company){
      state.current = company;
    }
  },
  actions: {
    [LOAD_COMPANY](state) {
      axios.get("/company").then(company => {
        state.commit(SET_COMPANY, company.data);
      });
    }
  }
};

@maoberlehner
Copy link
Owner

maoberlehner commented Sep 25, 2018

Please try to set default values for the properties you want to access and let me know if it worked, thx.

// initial state
import { getField, updateField } from "vuex-map-fields";
import { LOAD_COMPANY } from "@/store/action-types";
import { SET_COMPANY } from "@/store/mutation-types";
import axios from "axios";

export default {
  namespaced: true,
  state: {
    current: {
      name: '',
      description: '',
      company_type: '',
    }
  },
  getters: {
    getField
  },
  mutations: {
    updateField,
    [SET_COMPANY](state, company){
      state.current = company;
    }
  },
  actions: {
    [LOAD_COMPANY](state) {
      axios.get("/company").then(company => {
        state.commit(SET_COMPANY, company.data);
      });
    }
  }
};

@anikolaev
Copy link

I faced with the same issue. Setting default values fixes that but sometimes it needs to set values dynamically, using data from API. Another option is to initialize state.current with the object but it owerwrites another properties which is not good in my case and it needs to add another mutation.

I would prefer that the library itself would check the existence of property in updateField() and if it doesn't exist add the value as reactive:

  if (!state.hasOwnProperty(field.path)) {
    Vue.set(state, field.path, field.value)
  } else {
    state[field.path] = field.value
  }

I can do that in my own updateField() wrapper but for deep properties it would require the same processing that already exists inside updateField().

What about considering adding some flag for updateField() which would switch on creation of reactive properties. Or maybe just make it a default behavior as that is rather typical scenario. If the property doesn't exist at the moment of updating the value it will not work as reactive one.

@anikolaev
Copy link

It could look like this:

function updateField(state, { path, value }, makeReactive = false) {
  path.split(/[.[\]]+/).reduce((prev, key, index, array) => {
    if (array.length === index + 1) {
      if (makeReactive && !prev.hasOwnProperty(key)) {
        Vue.set(prev, key, value)
      } else {
        prev[key] = value
      }
    }

    return prev[key]
  }, state)
}

I used it instead of librarian one and it works for plain and object properties. Haven't checked with arrays yet.

@maoberlehner
Copy link
Owner

This could be an interesting addition to the code. I'd take a look at a pull request if somebody invests their time into that. 👍

@Uelb
Copy link

Uelb commented Oct 25, 2018

Is it possible to add this case to the readme for now ? I actually struggled to understand where the issue was and I faced the exact same case. If I have time next week, I'll try to open a PR with a solution.

@smith153
Copy link

smith153 commented Dec 9, 2018

Yes, this would be a great feature. I have many forms that are 100+ variables, really don't want to have to add defaults for every single one (and whether some fields are even shown depends on values of other variables, so you really don't have a concept of "defaults" in this case). Seems like an easy fix... though I suppose we could just wait for vue 2.6+ as I hear the requirement of forcing defaults will be removed...

fusionbeam pushed a commit to fusionbeam/vuex-map-fields that referenced this issue Feb 28, 2019
@leewisestamp
Copy link

Eagerly looking forward to this feature!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants