如何在Vue + Rails中正确处理提交事件?

时间:2018-09-23 16:42:16

标签: ruby-on-rails vue.js mdbootstrap

我正在学习Rails,Vue和JS,我对使用Vue组件验证其在Rails上的提交按钮的正确处理存在疑问。我正在使用mdbootstrap作为样式。

我构建了一个表单向导,该表单向导使用vee-validate来验证字段,并且在某些表单中我也想执行一些服务器端操作(例如:使用地址解析验证确切的地址)。我目前基本上面临三个问题。

  1. 尽管我添加了v-clock指令,但仍然看到了一些 每次加载表单向导组件时都会闪烁(例如:页面 刷新)。
  2. 我不得不解决Rails自动禁用数据的问题,要使其正常工作,它对我来说似乎不是最佳选择,我想知道是否有更好的方法来处理它(我必须禁用提交事件传播并阻止默认事件,并手动进行禁用/启用,否则来自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() {

        }
    }
});
}

*编辑* 对于#3,我正在使用一种解决方法,当重新启用表单上的元素时,使用按钮内的wave-ripple类删除div。

$(“ div”)。remove(“ button .waves-ripple”);

但是,很高兴知道其根本原因。

0 个答案:

没有答案