TransWikia.com

Как сделать так, чтобы при удачном запросе отображалась анимация на кнопке?

Stack Overflow на русском Asked on December 30, 2021

Я не понимаю, как сделать так, чтобы при удачной отправке формы значение loading становилось true и на 5 секунд появлялась анимация.
Вот кусочек HTML с кнопкой:

<div class = 'submit'>
  <button class="buttonload" name = 'submitting-botton' value = 'Отправить заказ' :disabled = "form.errors.any()">
  <p v-if="form.loading"><i class="fa fa-circle-o-notch fa-spin"></i><span>Идёт загрузка<span></p>
  <p v-else>Отправить заказ</p>
</button>
</div>

Я пыталась сделать подобное: в методе класса Form onSuccess, но первые 2 команды игнорировались:

onSuccess(response) {
    //Show Loader
    this.originalData.loading = true;

    //Waste 5 seconds
    setTimeout(() => {
      this.originalData.loading = false;
    }, 5000);
    alert(response.data.message);
    this.errors.clear();
    this.reset();
  }

Также приложу полную форму HTML:

<div id="app">
<form method="post" name="boocking" action="/clients" @submit.prevent="onSubmit" @keydown="form.errors.clear($event.target.name)">
<div class = 'name'>
  <label for = 'name'>Представьтесь:</label>
  <input type = 'text' id = "client" name="client" v-model = "form.client">
  <span class ="help is-danger" v-if="form.errors.has('client')" v-text="form.messages"></span>
</div>
<div class = 'phone'>
  <label for = 'phone'>Номер телефона:</label>
  <input type = 'text' id = "phone" name="phone" v-model = "form.phone">
  <span class ="help is-danger" v-if="form.errors.has('phone')" v-text="form.messages"></span>
</div>
<div class = 'extra'>
  <label for = 'extra'>Доп. номер:</label>
  <input type = 'text' id = 'extra' name="extra" v-model = "form.extra">
</div>
<div class = 'email'>
  <label for = 'email'>Email:</label>
  <input type = 'text' id = "email" name="email" v-model = "form.email">
<span class ="help is-danger" v-if="form.errors.has('email')" v-text="form.messages"></span>
</div>
<div class = 'volume'>
  <label for = 'volume'>Объём заказа:</label>
  <br>
  <select id = 'volume' name="volume" v-model ="form.volume" @change="form.errors.clear('volume')">
    <option disabled value="">Выберите один из вариантов</option>
    <option value = 'Менее 5 бареллей'>Менее 5 бареллей</option>
    <option value = 'От 5 до 10 баррелей в неделю'>От 5 до 10 баррелей в неделю</option>
  </select>
  <span class ="help is-danger" v-if="form.errors.has('volume')" v-text="form.messages"></span>
</div>
<div class = 'comments' name="comments">
  <label for = 'comments'>Доп. комментарий:</label>
  <textarea  v-model = "form.comments"></textarea>
</div>
<div class = 'message'>
  <input type = 'checkbox' id = 'messages' name="checkbox" v-model="form.checkbox" true-value="Согласен" false-value="Не согласен">
  <label for = 'messages'> Я согласен получать квасную рассылку</label>
</div>
<div class = 'submit'>
  <button class="buttonload" name = 'submitting-botton' value = 'Отправить заказ' :disabled = "form.errors.any()">
  <p v-if="form.loading"><i class="fa fa-circle-o-notch fa-spin"></i><span>Идёт загрузка<span></p>
  <p v-else>Отправить заказ</p>
</button>
</div>

И полный vue-app.js:

class Errors {
  constructor() {
    this.errors = {};
  }

  has(field) {
    return  this.errors.hasOwnProperty(field);
  }

  any() {
    return Object.keys(this.errors).length > 0;
  }

  get(field) {
    if(this.errors[field]) {
      return this.errors[field][0];
    }
  }


  record(errors) {
    this.errors = errors;
  }

  clear(field) {
    if (field) {
      delete this.errors[field];
      return;
    }
    this.errors = {};
  }
}

class Form {
  constructor(data) {
    this.originalData = data;

    for (let field in data) {
      this[field] = data[field];
    }

    this.errors = new Errors();
  }

  data() {
    let data = Object.assign({}, this);
    delete data.originalData;
    delete data.errors;
    return data;
  }

  reset() {
    for(let field in this.originalData) {
      this[field] = '';
    }
  }

  submit(requestType, url) {
    axios[requestType](url, this.data())
    .then(this.onSuccess.bind(this))
    .catch(this.onFail.bind(this))
  }

  onSuccess(response) {
    //Show Loader
    this.originalData.loading = true;

    //Waste 5 seconds
    setTimeout(() => {
      this.originalData.loading = false;
    }, 5000);
    alert(response.data.message);
    this.errors.clear();
    this.reset();
  }

  onFail(error) {
    this.errors.record(error.response.data.errors);
  }
}

new Vue({
  el: '#app',
  data: {
    form: new Form({
      client: '',
      phone: '',
      extra: '',
      email: '',
      volume: '',
      comments: '',
      checkbox: 'Не согласен',
      messages: 'Данное поле обязательно для заполнения',
      loading: false
    })
  },


  methods: {
    onSubmit() {
      this.form.submit('post', '/clients');

    }


  }
});

Подскажите, пожалуйста, в чём ошибка? Заранее спасибо.

One Answer

Думаю проблема в том что вы сбрасываете значения originalData в reset() который сработает раньше setTimeout(). может для начала попробуйте другую переменную для наглядности ваших изменений.

reset() срабатывает раньше потому что он выполняется синхронно. setTimeout устанавливает функцию в event loop и когда поток освободится только в этом случае он начнет выполнять функцию переданную в setTimeout.

Answered by Aziz Umarov on December 30, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP