0

I have been trying to learn Vuex recently so that my data and unfinished form data are not lost when I navigate between routes. In Vuex's page there is a simple management example about incrementing and decrementing a value but I have trouble adapting this example to what I need. I have a simple component which takes username and password from the user. Since I will use this method everywhere in my project, I want to use this method in checkboxes, select elements and generally all form elements. Let's say the user typed for the username input and left the password one and navigate between different routes, components and came back to the first component. I want username input field is to be filled with the one the user typed earlier. I think I need two way data binding because I also do some validations for every input element in my project and they are all connected with a unique data with v-model.

I tried to create the store.js file and and a state inside of it. When I declare a state as username and set it to something static like "Jason", I am able to use it in my component as this.$store.state.username But here is my question; How do I set the

state : {
 username: 'Jason'
}

something dynamic so that it changes everytime the username input field is typed. Here is my username input;

<input v-model="userData.username" type="text" />

data() {
      return {
        userData: {
          username: "",
        },
      };
    },

When the user types something, username is updated in the data. I want this to change in the state in Vuex, so even if the route or component has changed, I will be able to use that data when I return. I am not sure if I understand the usage correctly. Am I missing something? Can you help me? Thanks in advance!

Store.js

state:{
    cloud_user:""
 },
 mutations:{
    set_userName(state, val){
      state.cloud_user = val
    }
 }

Computed

computed: {
  set_username:{
    set(val){
      this.$store.commit("set_username", val)
    },
    get(){
      return this.$store.state.username
    }
  }
}
 

Currently I am having the following error

[Vue warn]: Method "computed" has type "object" in the component definition. Did you reference the function correctly?

And plus, have this error too;

[Vue warn]: Property or method "set_username" is not defined on the instance but referenced during render.
Yasin Demirkaya
  • 243
  • 6
  • 22

1 Answers1

2

Actually you don't need to use the data() prop. But you need use the computed and you should use the setter.

template

<input v-model="set_userName" type="text" />

script

<script>
  export default {
    computed: {
      set_username:{
        set(val){

        },
        get(){
          
        }
      }
    }
  }
</script>

vuex.store

 state:{
    userName:""
 },
 mutations:{
    set_userName(state, val){
      state.userName = val
    }
 }

And what we have done. We created computed property, then set the value to vuex AND get the newly setted data from vuex.

The key point lies in the mutations part. You are setting the current value by set(val) and commiting it to the mutation as val in the set_userName(state, val), then giving that val to the state.

UPDATED

Also adding a more proper way to mutate a state. Not by directly from the setter, but by actions.

Right below the mutations:{} create actions.

 state:{
    userName:""
 },
 mutations:{
    set_userName(state, val){
      state.userName = val
    }
 },
 actions:{
    PATCH_CURRENT_VALUE({commit}, payload){
      this.commit("set_userName", payload)
    }
 }

Now you should change the computed:{}

 computed: {
      set_username:{
        set(val){
           this.$store.dispatch("PATCH_CURRENT_VALUE", val)
        },
        get(){
           return this.$store.state.username
        }
      }
  }
firefly
  • 876
  • 2
  • 15
  • 42
  • can I use computed property as an object by definition? – Yasin Demirkaya Jan 05 '21 at 13:35
  • yes, this how you apply a setter in computed prop. – firefly Jan 05 '21 at 13:46
  • I did exactly like you explained and now I am having an error that says "Method "computed" has type "object" in the component definition. Did you reference the function correctly?" – Yasin Demirkaya Jan 05 '21 at 13:47
  • problem is in your computed: {} because you are writing the setter wrongly. please check the answer's computed prop. I implement the setter inside the `set_userName:{}` but your setter(set and get) don't have the parent. – firefly Jan 05 '21 at 13:58
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/226873/discussion-between-yasin-demirkaya-and-yepsolutely). – Yasin Demirkaya Jan 05 '21 at 14:04
  • Updated again. Still having that error with a new one. I double checked it but if there is still a problem, I think I can't see :) – Yasin Demirkaya Jan 05 '21 at 14:05
  • did you wrote the whole `computed` prop inside `methods:{}` ??? computed is not a method! you must wrote it outside the `methods:{}` – firefly Jan 05 '21 at 14:07
  • it is outside of the method. Now I dont get the error but when I type something inside the input field it triggers this one; [vuex] unknown mutation type: set_username – Yasin Demirkaya Jan 05 '21 at 14:08
  • change the v-model with this `v-model="set_username"` – firefly Jan 05 '21 at 14:12
  • Finally I managed to do that :) Can you give me an email address or something so that I can reach you in person to ask some questions about Vuex? I don't want to trash the comment section of this question :) – Yasin Demirkaya Jan 05 '21 at 14:14
  • glad to hear that. I also added a more proper way to update the state and used `ACTIONS:{}` you can check it out and try it. I am sorry but can't give email address if you stuck anything else ask a question here. and feel free to link to there. By the way don't forget to check this as **answer** if it solved your problem. – firefly Jan 05 '21 at 14:27
  • Can I use this way to keep the information of a checbox or a radio button status? When a checbox is checked, I want it to stay checked all the time even if I navigate between routes. And about your update to your answer, what did you mean by saying PATCH_CURRENT_VALUE? – Yasin Demirkaya Jan 05 '21 at 16:57
  • Yes, you can use it on every form type. About the action: In the first answer I was directly commiting the mutation. But you can mutate the state by actions. And this topic explains it: https://github.com/vuejs/vuex/issues/587 – firefly Jan 06 '21 at 00:59
  • Now, I'm applying this method on all my form elements, but there is another issue I am curious about. Yes, when navigating between routes and returning to the first route, the data in the input fields do not disappear, or a checkbox that I checked remains checked when I came back, but I want the page to remain in its final state when the page is closed and reopened. How can I do that? Even if refresh the page, the states are gone. I want them to be kept even if the page is fully closed and opened maybe 2 hours later. – Yasin Demirkaya Jan 06 '21 at 08:06
  • if I understand correctly; you have a default state for **username** and when page reloaded or routed to different component and came back, you want to put default state again. HARD REFRESH is turn the vuex state to the default. but changing component doesn't effect the vuex state. and keeps last updated text in the input, checkbox or etc... if you want to change updated input text to default state everytime component is opened. THEN use the `mounted(){ this.$store.commit("set_username", "your default text") }` as you see. now we are changing the vuex state everytime component mounted. – firefly Jan 06 '21 at 08:38
  • if above comment is not clear enough, then please open a question topic and feel free to link me there... – firefly Jan 06 '21 at 08:39
  • Let's say the user checks a checkbox to enable the username and password field and typed for those fields, clicked save, and closed the browser. I still want to see that checkbox is checked and username and password fields are filled with the data that's been typed earlier. Even one week later. I found a plugin called vue-persistedstate to do that. All the input fields are empty by default, there is no problem with that. I just want to keep every information even when the page is hard refreshed. – Yasin Demirkaya Jan 06 '21 at 09:27
  • `vue-persistedstate` is for registering the states into localStorage... if you really want to keep updated data no matter what. then you need a backend and save the updated profile fields into DB. if you don't want a backend/database then I prefer that you should go with the localStorage... in your case it's `persistedstate` module. no other option. – firefly Jan 06 '21 at 09:56
  • The Store.js file is getting bigger, is there a way to group the states separately for each component? Different state and mutations tags for every route maybe? – Yasin Demirkaya Jan 06 '21 at 10:06