简体   繁体   中英

VueJS/Vuetify - @change set loading=“true” on input

I'm trying to create a method, which is triggered by @change on multiple inputs.

I need to set loading="true" for the target input until axios finishes the request (PATCH).

NOTE:

There are multiple v-select on the page and I want to set loading=true just for the one particular target - the current input/select.


EXAMPLE:

If the user selects an option in the first select in the example below, the inlineUpdate method is called which modifies the target to looks like this <v-select loading="true" @change="$root.inlineUpdate"...

and then, after the update is finished, it removes the loading attribute.


I suppose I need event argument passed into the method but it doesn't work.

It passes just a value so I can't recognize which input should I set as being loaded.

 <v-select @change="$root.inlineUpdate" ...
 <v-select @change="$root.inlineUpdate" ...
 <v-select @change="$root.inlineUpdate" ...
 <v-text-field @change="$root.inlineUpdate"...

 inlineUpdate(event){
              console.log(event)
              console.log(event.target)
             # here I need to set loading="true" for the input
             axios.post(...).finally(() => { // remove the loading })
             # stop loading
            },

logs

>>> house
>>> undefined

Is there a way to make this work?

You need to create a separate variable that handles loading for only the v-select . So we create one called isSelectLoading , which defaults to false. Then, when we begin our API call process, we set it to true and once the promise resolves we set it back to false .

<v-select label="Typ nehnuteľnosti" :loading="isSelectLoading"  @change="$root.inlineUpdate" ...

...
 data: () => ({
   isSelectLoading: false
 }),
 methods: {
   inlineUpdate(){
     this.isSelectLoading = true;
     axios.put("/some/url", ...)
        .then(apiResponse => { //do some stuff })
        .catch(apiError => { //oh no! })
        .finally(() => { this.isSelectLoading = false });
   },
 }

Update for multiple v-selects

You need a way to keep track of which components are loading. We will handle that with an array called isSelectLoading . It will be in our data property, and we are defaulting the loading state to false .

You also need a way to know which v-select is being changed. To take care of that, we will create another variable called activeSelect . We will bind this to our v-select via the @click event listener.

Then, when we change a selection from any of our selects, we can update our loading state only for that v-select !

 <v-select 
    @change="inlineUpdate" 
    @click="activeSelect = 0"
    :loading="isSelectLoading[0]"...
 <v-select 
    @change="inlineUpdate" 
    @click="activeSelect = 1"
   :loading="isSelectLoading[1]"...
 <v-select 
    @change="inlineUpdate" 
    @click="activeSelect = 2"
    :loading="isSelectLoading[2]"...
 <v-text-field
    @change="inlineUpdate" 
    @click="activeSelect = 3"
    :loading="isSelectLoading[3]"...

 ...
  data: () => ({
    activeSelect: null,
    items: ["a", "b", "c"],
    isSelectLoading: [false, false, false]
  }),
 methods: {
   inlineUpdate(){
     this.toggleLoading(this.activeSelect);
     axios.put("/some/url", ...)
        .then(apiResponse => { //do some stuff })
        .catch(apiError => { //oh no! })
        .finally(() => { this.toggleLoading(this.activeSelect); });
   },
   toggleLoading(index) {
     this.isSelectLoading[index] = !this.isSelectLoading[index]
   }

In this example it's a bit trivialized; in real code, we could put these inside of a <template v-for="(item, index) in selects">... , where selects would have the required fields/properties in order to generate your select components. You would replace the hard-coded indexes with the value of index for the event bindings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM