Как правильно обрабатывать события отправки в Vue + Rails?

Я изучаю Rails, Vue и JS, и у меня возник вопрос о правильной обработке кнопок отправки на Rails с использованием компонента Vue для его проверки. Я использую mdbootstrap для стилей.

Я создал мастер форм, который использует vee-validate для проверки полей, и в некоторых формах я хочу также выполнять некоторые операции на стороне сервера (например, проверять точный адрес с помощью геокодирования). В настоящее время я сталкиваюсь с тремя проблемами.

  1. Хотя я добавил директиву v-clock, я все еще вижу небольшое мерцание при каждой загрузке компонента мастера форм (например, обновление страницы).
  2. Мне пришлось обойти Rails с автоматическим отключением обработки данных, чтобы заставить его работать, и это выглядит неоптимально для меня, и я хотел бы знать, есть ли лучший способ справиться с этим (мне пришлось отключить событие submit распространение и предотвращение по умолчанию, а также отключение / включение вручную, иначе обработчик из Rails UJS получит его позже и отключит кнопку навсегда).
  3. Хотя кнопка снова включается, она становится ярче каждый раз, когда я нажимаю на нее, если проверка не удалась (возможно, какой-то обработчик из mdbootstrap?). Это происходит только после того, как я нажимаю кнопку обновления в браузере, и я заметил, что после каждого щелчка создается следующий элемент div, за которым следует ошибка во время проверки формы, в результате чего кнопка становится "ярче", как в накопленном "отключенном эффекте":

У кого-нибудь есть идеи о том, как эти проблемы можно решить? Спасибо!

new.html.erb:

<div id="stepper">
    <div v-cloak>
        <transition-group name="fade">
            <div class="d-none d-lg-block"  key="progress_bar">
                <%= render 'forms/progress_bar' %>
            </div>
            <div id="step1" v-if="step === 1" key="step1">
                <%= render 'forms/description' %>
            </div>
            <div id="step2" v-if="step === 2" key="step2">
                <%= render 'forms/address' %>
            </div>
        </transition-group>
    </div>
</div>

_description.html.erb:

<template>
  <form 
    id="description-form" 
    data-vv-scope="description-form" 
    novalidate="true"
    @submit.prevent="next('description-form', $event)">

    <div class="row mb-5">
      <div class="col-lg-12 col-md-12">
        <div class="container">
          <div class="row" id="step-1">
            <div class="col-lg-6">
              <div class="max-height-80">
                <div class="mb-4">
                  <h4><%= t(:'step1.title') %></h4>
                </div>

                <div class="form-group">
                  <label 
                    for="name" 
                    class="control-label">
                    <%= t(:'step1.label.name') %>
                  </label>
                  <input 
                    id="name" 
                    name="name" 
                    type="text" 
                    class="form-control" 
                    placeholder="<%= t(:'step1.input.name') %>" 
                    v-validate="'required'" 
                    v-model="name" 
                    :class="{ 'is-invalid': errors.has('name','description-form') }" 
                    required/>
                  <div 
                    v-if="errors.has('name','description-form')" 
                    class="invalid-feedback">
                    <%= t(:'name.required') %>
                  </div>
                </div>

                <div class="form-group">
                  <label 
                    for="description" 
                    class="control-label">
                    <%= t(:'step1.label.description') %>
                  </label>
                  <textarea 
                    id="description" 
                    name="description" 
                    class="form-control" 
                    placeholder="<%= t(:'step1.input.description') %>" 
                    rows="11" 
                    v-validate="'required'" 
                    v-model="description" 
                    :class="{ 'is-invalid': errors.has('description','description-form') }" 
                    required>
                  </textarea>
                  <div 
                    v-if="errors.has('description','description-form')" 
                    class="invalid-feedback">
                    <%= t(:'description.required') %>
                  </div>
                </div>
              </div>
              <footer class="page-footer white fixed-bottom d-block d-sm-none z-depth-1" id="footer">
                <div class="d-flex justify-content-end">
                  <button class="btn btn-default pull-right" type="submit" data-remote="true" data-disable-with="<%= wait_spinner %>"><%= t(:'btn.next') %></button>
                </div>
              </footer>
              <div class="d-none d-sm-block">
                <div class="d-flex justify-content-end mt-2">
                  <button class="btn btn-default pull-right" type="submit" data-remote="true" data-disable-with="<%= wait_spinner %>"><%= t(:'btn.next') %></button>
                </div>
              </div>
            </div>
            <div class="col-lg-2"></div>
            <div class="col-lg-4 d-none d-lg-block mt-lg-5">
            </div>
          </div>
        </div>
      </div>
    </div>
  </form>
</template>

stepper.js

var element = document.getElementById("stepper");
if (element != null) {
    Vue.use(VeeValidate);
    Vue.use(VueResource);

    Vue.http.headers.common['X-CSRF-Token'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content');

    const stepper = new Vue({
        el: element,
        data() {
            return {
            /**
            * The step number (starting from 1).
            * @type {Integer}
            */
            step:1,
            name:null,
            description:null
            }
        }
    },

    methods: {
        /**
        * Goes back to previous stepp
        */
        prev() {
            this.step--;
        },
        /**
        * Triggers validation of current step and goes to the 
        * next step if validation succeeds
        * @param {String} scope The step scope used for validation.
        * @param {Object} Event that triggered the next step (form submit)
        */
        next(scope, event) {
            if (event != undefined) {
                event.stopImmediatePropagation();
                event.preventDefault();
                event.stopPropagation();
            }

            const form = event.currentTarget;
            $("button[type=submit]",form).each(function() {
                Rails.disableElement(this);
            });

            this.validateFields(scope, event);
        },
        validateFields(scope, event) {
            this.$validator.validateAll(scope).then(function (valid) {
                this.postFieldsValidation(valid, event);
            }.bind(this));
        },
        postFieldsValidation(valid, event) {

            if (valid) {
                stepper.step++;
            }

            const form = event.currentTarget;
            $("button[type=submit]",form).each(function() {
                Rails.enableElement(this);
            });

        },
        handleError(error) {
            alert(error)
        },
        submit() {

        }
    }
});
}

* edit * for # 3, я использую обходной путь для удаления div с классом waves-ripple внутри моей кнопки при повторном включении элементов в форме.

$ ("div"). remove ("button.waves-ripple");

однако было бы неплохо узнать причину этого.

0 ответов

Другие вопросы по тегам