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

v-model is confusing #115

Open
JelledFro opened this issue Jul 22, 2019 · 14 comments
Open

v-model is confusing #115

JelledFro opened this issue Jul 22, 2019 · 14 comments

Comments

@JelledFro
Copy link

The component looks and works great, but I found something I think is a bit confusing. I would like to get the initial state from Vuex and set the button to the initial state, then I want to toggle the state with the button and set the new state in Vuex. A simple 2 way binding. v-model is usually great for that, but I found with your component I had to use v-bind, :value & :sync simultaneously for it to work that way. Using just ":value" and ":sync" I couldn't get the button to set the value in my computed property, and using just v-bind I didn't get the initial state. Perhaps you could default ":value" to whatever v-model is and default ":sync" to on to simplify things and make v-model work as most people would probably expect it to? Just a suggestion.

@adam-godfrey
Copy link

I have the exact same problem.

I am looping over a number of rows and creating a toggle switch for each one and it's not picking up the value from v-model

@euvl
Copy link
Owner

euvl commented Oct 29, 2019

Yeah, I did this one before v-model for custom components (non DOM inputs) was a thing, and then someone else added support for v-model 😄 Maybe it is time for v2

@vesper8
Copy link

vesper8 commented Nov 3, 2019

I thought I was losing my mind just now, the toggle-button worked fine in 4 out of 5 of my components and they all had sync set to false (default) and were using a value from the data directive, initialized from a vuex value.. and I was manually setting the vuex on a @change event... a tedious cycle but I hadn't thought of a better way to do it. But for some reason that I still can't figure out, this one component just would not update the :value no matter what I did !?!

I found this issue here and tried out v-model instead, now I'm able to bind the v-model directly to my vuex value and it works perfectly, and this has allowed me to remove quite a bit of code as a result

unsure why the heck it wasn't working before.. and unsure why you had to jump through several hoops to get yours working with a combination of sync and v-bind

I'm uxing vuex-pathify which may be part of the answer

@ButeForce
Copy link

Hi,

I have the same issue and still cannot resolve it, I can get the state using v-model but cannot set the initial status of the toggle to reflect the actual state of the button .

@vesper8 ,

I didn't get if you managed to solved only using v-model ?

@vesper8
Copy link

vesper8 commented Dec 20, 2019

yes it's working fine for me now using v-model

maybe post your code if you're having trouble?

@ButeForce
Copy link

ButeForce commented Dec 20, 2019

Thank you for your quick response,

below is the code, i tried many possibility but failed to get the initial state and v-model working at the same time:

{
`

{{control.control_name}}

`

}

in the script block I'm just using a computed property

computed ()
{

return {

state: false
},

methods : {
async onActivate (controlid, controlname)

    {
      this.$message(" control id :  " + controlid + " controlname : " + controlname + " State: " + this.state );

}

}

@ButeForce
Copy link

ButeForce commented Dec 20, 2019

I dont know why the template code does not appear above

paste it down.

<div v-for="control in scope.row.controls" :key="control.control_name" > <div><toggle-button :value="control.is_activated" @change="onActivate(control.control_id, control.control_name)" v-model="state" :labels="true" color ='#4AB7BD' width="75" height="25" /> <hr></div> </div>

@vesper8
Copy link

vesper8 commented Dec 20, 2019

Hrm well.. I think you're doing something really weird with the computed property.. that's not how you use computed properties. Also, you I think what you want to do is tie the v-model to each of your controls' is_activated. You can't use a single state property for multiple toggle buttons. And that value shouldn't be a computed property anyway.

Here's a small code sample which works perfectly for me, which I believe mimics how you've structured your data. Paste that in and try to learn from it. Hope it helps

Notice how I removed the value attribute. You shouldn't have to use the value attribute if you're using v-model

P.S. to display multi-line code on Github you need to wrap it by groups of 3 ticks. So it's 3 tricks, line break, code, line break, 3 ticks

<template>
  <div>
    <div
      v-for="control in scope.row.controls"
      :key="control.control_name"
    >
      <div>
        <toggle-button
          v-model="control.is_activated"
          :labels="true"
          color="#4AB7BD"
          :width="75"
          :height="25"
          @change="onActivate(control)"
        />
        <hr>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      scope: {
        row: {
          controls: [
            {
              control_id: 1,
              control_name: 'name 1',
              is_activated: false,
            },
            {
              control_id: 2,
              control_name: 'name 2',
              is_activated: true,
            },
          ],
        },
      },
    };
  },

  methods: {
    async onActivate(control) {
      console.log(`Id: ${control.control_id} Name : ${control.control_name} State: ${control.is_activated}`);
    },
  },
};
</script>

@ButeForce
Copy link

dear vesper8 ,

Appreciate your effort and kindness.

actually what I was hoping to achieve is to have the button reflect initial status by reading control.is_activated "which I'm getting it from back-end server trough graphsql , and its being used through slots in the template" , then whenever the user makes a change it will trigger an action based on the new status.

I was using actually normal data() to return the status but the behavior was the same , I'm able to mach every switch to its status if I'm using control.is_activated , but cannot use v-model at the same time.

in this situation I have two states , one which is the devices currently on "either on or off" and i would like to reflect it once the user loads the page , and one which the user will do "switching on or off by selecting the button" afterward , I thought I can do this using value combined with v-model as the documentations says that value to reflect the initial status of the button.

@ButeForce
Copy link

Here is a little update:

what I had to do is actually to get the initial status and put it in an array for each button which is created dynamically , and assign v-model to that item which will be returned from that array , this way every button will have its own status which is fetched initially from the back end server , when the user changes the status of the button it writes back to the same value in that array, I send this value to the @change event so I can take a decision later what the action will be.

the caveat of this is that i have to create a nested loop to push the new values during loading in another array which make the page little bit slower initially.

but the end result is that I have the status initially reflected into the button and in the same time the user can change this value.

@vesper8
Copy link

vesper8 commented Dec 21, 2019

Here is how I handle the exact same situation (having preferences persisted to the backend, then loaded on the front-end, and anytime a user makes a change it gets persisted both on the front and back end).

I use Vuex and vuex-pathify (optional but makes everything cleaner).

On a parent component, prior to loading the component that displays the toggle buttons, I make sure that the preferences have been loaded from my REST API, otherwise I load them and assign them to my Vuex store module. I use vuex-persistedstate plugin to persist the vuex store to localStorage so I don't have to constantly fetch it from the REST API.

Once the preferences are loaded in Vuex, I then load the component displaying the toggle buttons. I only use v-models and I don't need to use a @change event because I bind the v-model directly to my vuex store, which thanks to vuex-pathify handles both getters and setters via the 'sync' function

Then, I add a watcher on the vuex "preferences" object, which contains all the values for all my toggle buttons (and more in my case). In the watcher, whenever any of the preferences change, well the vuex store is automatically updated since it's synced, and then I call a method that does a post to my rest api to make sure the modified preferences are also persisted on the backend

@Aymkdn
Copy link

Aymkdn commented Apr 24, 2020

v-model didn't work for me… To make it work I've had to do the below:

<toggle-button :value="myVar" :sync="true" @change="myVar=$event.value"></toggle-button>

@evsar3
Copy link

evsar3 commented Jun 6, 2020

This must fix:

<toggle-button v-model="myData" sync></toggle-button>

@hobbydev71
Copy link

#115 (comment) could close the issue.

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

No branches or pull requests

8 participants