Here is the demo response from the API:
[
{
form_name: 'Form One',
name: 'Peter',
email: '[email protected]'
},
{
form_name: 'Form Two',
name: 'John',
email: '[email protected]'
}
]
From that I built a form through v-for
<v-form
v-for="(item, index) in forms" :key="index"
>
<v-btn
:loading="saveLoading"
@click="submit(item)"
>
submit
</v-btn>
</v-form>
I set saveLoading: false,
initially. In the submit(item)
function, I was setting saveLoading: true,
at first. Then at asynchronous function for POST method, I would turned that back to false
. But, the problem is whenever, I click on the submit
button in one form, two submit
buttons in the two form got affected by loading state.
What to do to get the effect in one submit
button for the current form only?
CodePudding user response:
The problem is that you have only one variable. You could do saveLoading1
to saveLoadingN
but that's not very useful. It'll be better to split your forms into sub components:
var forms = [
{
form_name: 'Form One',
name: 'Peter',
email: '[email protected]'
},
{
form_name: 'Form Two',
name: 'John',
email: '[email protected]'
}
];
var Button = Vue.component('v-btn', {
props: [ 'loading' ],
template: `<button :disabled="loading" @click="handleClick">
<slot v-if="!loading"></slot>
<span v-else>Saving …</span>
</button>`,
methods: {
handleClick() {
this.$emit('click');
}
}
})
var Form = Vue.component('v-form', {
name: "Form",
props: [ 'form' ],
data() {
return {
saveLoading: false
}
},
template: `<div>
<h2>{{ form.form_name }}</h2>
<v-btn
:loading="saveLoading"
@click="submit(form)"
>
submit
</v-btn>
</div>`,
methods: {
submit() {
console.log('save')
this.setLoading(true);
setTimeout(this.setLoading.bind(this, false), 1000)
},
setLoading(isLoading) {
this.saveLoading = isLoading
}
}
});
new Vue({
el: '#app',
components: { Form },
data() {
return {
forms: window.forms
}
},
template: `<div>
<v-form
v-for="(item, index) in forms" :key="index" :form="item"
>
</v-form>
</div>`
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
CodePudding user response:
<v-btn
:loading="saveLoading == index"
@click="submit(item, index)"
>
data: () => ({
valid: true,
saveLoading: -1,
})
submit (formItem, index) {
this.saveLoading = index
console.log(formItem)
// POST the formItem and make the saveLoading false in async then(), catch()
},
It is not a very logical method, but this way you can solve the problem.
CodePudding user response:
If you are generating the forms from the api response, mean that in some way you are attaching the response to the Vue Data property. If so, you could easily enrich the objects of the array (the forms object) to have a isLoading property. So the result will be something like:
API RESPONSE
[
{
form_name: 'Form One',
name: 'Peter',
email: '[email protected]'
},
{
form_name: 'Form Two',
name: 'John',
email: '[email protected]'
}
]
and store is as:
Stored object
[
{
form_name: 'Form One',
name: 'Peter',
email: '[email protected]',
isLoading: false
},
{
form_name: 'Form Two',
name: 'John',
email: '[email protected]',
isLoading: false
}
]
Set the loading status in the submit(item) method:
submit(item){
item.isLoading = true;
}
then you can use it by checking the value of isLoading on the form object, something on the lines of:
<v-form
v-for="(item, index) in forms" :key="index"
>
<v-btn
:loading="item.isLoading"
@click="submit(item)"
>
submit
</v-btn>
</v-form>