无法在 vue.js 1.0 和 Laravel 5.1 中进行错误处理

Can't get error handing in vue.js 1.0 and Laravel 5.1 to work

我正在构建一个应用程序,它使用 vue.js 和 Laravel 5 将数据保存到数据库中。至此,可以成功保存数据。

我的问题

当使用 Laravel 拥有的 'out of the box' 授权的用户验证失败时,我无法显示错误。我不断收到错误消息:

[Vue warn]: Error when evaluating expression "form.errors.length > 0"

(参考我下面代码中的errors.js

拼凑起来

那么这应该如何工作...用户将他们的详细信息输入到注册页面,Vue(使用 vue-resource)向 'out of the box' Laravel 发出 AJAX 请求AuthController@postRegister 方法。出现错误时,Laravel 会很好地输出我们都期望的 JSON 错误消息。现在理论上,我的 subscription.js 文件中的 sendRegistration 方法应该检测到 Laravel 吐出的错误(我已经用 console.log 测试过它并且它有效)并且将它们传递到 errors.js 组件以显示 <spark-errors> 标记内的错误。为了做到这一点,它在我的 <head> 标签中使用了一个 setErrorsOnForm: 函数。但是它没有按预期工作,我不知道为什么。

我的代码

我的代码包含一个注册页面:

<!DOCTYPE html>
<html lang="en">
<head>
<!-- Laravel Spark Globals -->
    <script>
        window.Spark = {
            // Laravel CSRF Token
            csrfToken: '{{ csrf_token() }}',

            // Flatten errors and set them on the given form
            setErrorsOnForm: function (form, errors) {
                if (typeof errors === 'object') {
                    form.errors = _.flatten(_.toArray(errors));
                } else {
                    form.errors.push('Something went wrong. Please try again.');
                }
            }
        }
    </script>
</head>
<body>
    <div id="spark-app">
<spark-subscription-register-screen inline-template>
<div class="panel panel-default">
    <div class="panel-heading">Your Information</div>
    <div class="panel-body">
        <spark-errors form="@'{'{ registerForm '}'}"></spark-errors>

        <form class="form-horizontal" role="form" id="subscription-basics-form">

            <div class="form-group">
                <label class="col-md-4 control-label">Your Name</label>
                <div class="col-md-6">
                    <input type="text" class="form-control spark-first-field" name="name" v-model="registerForm.name">
                </div>
            </div>

            <div class="form-group">
                <label class="col-md-4 control-label">E-Mail Address</label>
                <div class="col-md-6">
                    <input type="email" class="form-control" name="email" v-model="registerForm.email">
                </div>
            </div>

            <div class="form-group">
                <label class="col-md-4 control-label">Password</label>
                <div class="col-md-6">
                    <input type="password" class="form-control" name="password" v-model="registerForm.password">
                </div>
            </div>

            <div class="form-group">
                <label class="col-md-4 control-label">Confirm Password</label>
                <div class="col-md-6">
                    <input type="password" class="form-control" name="password_confirmation" v-model="registerForm.password_confirmation">
                </div>
            </div>

            <div v-if="freePlanIsSelected">
                <div class="form-group">
                    <div class="col-sm-6 col-sm-offset-4">
                        <div class="checkbox">
                            <label>
                                <input type="checkbox" v-model="registerForm.terms"> I Accept The <a href="/terms" target="_blank">Terms Of Service</a>
                            </label>
                        </div>
                    </div>
                </div>

                <div class="form-group">
                    <div class="col-sm-6 col-sm-offset-4">
                        <button type="submit" class="btn btn-primary" v-on:click="register" :disabled="registerForm.registering">
                            <span v-if="registerForm.registering">
                                <i class="fa fa-btn fa-spinner fa-spin"></i> Registering
                            </span>

                            <span v-if=" ! registerForm.registering">
                                <i class="fa fa-btn fa-check-circle"></i> Register
                            </span>
                        </button>
                    </div>
                </div>
            </div>
        </form>
    </div>
</div>
</spark-subscription-register-screen inline-template>
</div>
</body>
</html>

从 vue.js 的角度来看,有一个 subscription.js 文件:

Vue.component('spark-subscription-register-screen', {

    /*
     * Initial state of the component's data.
     */
    data: function () {
        return {
            registerForm: {
                nhs_org: '', team_name: '', name: '', email: '', password: '', password_confirmation: '',
                plan: '', terms: false, coupon: null, invitation: null,
                stripe_token: null, errors: [], registering: false
            },
        };
    },

    methods: {
        /*
         * Initialize the registration process.
         */
        register: function(e) {
            var self = this;

            e.preventDefault();

            this.registerForm.errors = [];
            this.registerForm.registering = true;

            return this.sendRegistration();
        },

        /*
         * After obtaining the Stripe token, send the registration to Spark.
         */
        sendRegistration: function() {
            this.$http.post('/register', this.registerForm)
                .success(function(response) {
                    window.location = '/';
                })
                .error(function(errors) {
                    this.registerForm.registering = false;
                    Spark.setErrorsOnForm(this.registerForm, errors);
                });
        },
    }

});

并且有一个 errors.js Vue 组件:

/*
 * Common Error Display Component.
 */
Vue.component('spark-errors', {
    props: ['form'],

    template: "<div><div class='alert alert-danger' v-if='form.errors.length > 0'>\
                <strong>Whoops!</strong> There were some problems with your input.<br><br>\
                <ul>\
                    <li v-for='error in form.errors'>\
                        {{ error }}\
                    </li>\
                </ul>\
            </div></div>"
});

现在将所有这些拼凑在一起的 Vue 文件(以正确的顺序):

app.js:

require('./core/dependencies');

if ($('#spark-app').length > 0) {
    new Vue(require('./core/spark.js'));
}

core/dependencies.js:

/*
 * Load Vue & Vue-Resource.
 *
 */
if (window.Vue === undefined) window.Vue = require('vue');

require('vue-resource');
Vue.http.headers.common['X-CSRF-TOKEN'] = Spark.csrfToken;

/*
 * Load Underscore.js, used for map / reduce on arrays.
 */
if (window._ === undefined) window._ = require('underscore');

/*
 * Load jQuery and Bootstrap jQuery, used for front-end interaction.
 */
if (window.$ === undefined || window.jQuery === undefined) window.$ = window.jQuery = require('jquery');
require('bootstrap-sass/assets/javascripts/bootstrap');

core/spark.js:

/*
 * Load the Spark components.
 */
require('./components');

/**
 * Export the Spark application.
 */
module.exports = {
    el: '#spark-app',

    /*
     * Bootstrap the application. Load the initial data.
     */
    ready: function () {
        $(function() {
            $('.spark-first-field').filter(':visible:first').focus();
        });
    }
}

和core/components.js:

require('./../auth/registration/subscription');
require('./../common/errors');

我遇到了同样的问题,我没有使用 spark 开箱即用的错误,而是定义了自己的组件:

<template>
    <div v-if="errors">
        <div class="alert alert-danger" v-if="formattedErrors.length > 0">
            <strong>Whoops!</strong> There were some problems with your input.<br><br>
            <ul>
                <li v-for="error in formattedErrors">
                    {{ error }}
                </li>
            </ul>
        </div>
    </div>
</template>

<script>
    export default {
        props: ['errors'],
        computed: {
            formattedErrors() {
                return this.format(this.errors);
            }
        },
        methods: {
            format(errors) {
                if (typeof errors === 'undefined') {
                    return [];
                }
                if (typeof errors === 'object') {
                    return _.flatten(_.toArray(errors));
                }
            }
        }
    }
</script>

然后你绑定在你的html:

<form-errors :errors="registerForm.errors"></form-errors>

这是有道理的,因为您的组件现在只需要有关错误的信息,而不需要有关 registerForm 的信息。

希望对您有所帮助。