【问题标题】:Clear the errors once input field is valid输入字段有效后清除错误
【发布时间】:2017-07-25 03:44:28
【问题描述】:

我将 AngularJS 与 node.js 一起使用。我已经实现了如下错误处理程序:

节点路由器 effect.js:

router.post('/', function(req, res, next){

    req.checkBody('name', 'Effect name is required.').notEmpty();
    var errors = req.validationErrors();

    console.log(errors);

    if(errors) {
        res.status(500).json(errors);
        return;
    }

    var effect = new Effect({
        name: req.body.name
    });

    Effect.createEffect(effect, function(err, result) {
        if(err) { next(err) }
        res.status(201).end();
    });

});

效果控制器.js:

$scope.submit = function(effect) {

    effectService.save(effect, function(err, result, status) {

        $scope.errors = err;

        if(err == null) {
            $scope.effect = null;
            if(!(effect == null || effect == undefined)) {
                if(!(effect._id == undefined || effect._id == '')) { 
                    $location.path('/effect');
                }
            }
            reload();
        }

    });

}

effectService.js

function save(effect, callback) {
    if(effect == undefined || effect._id == undefined || effect._id == '') {
        $http.post('/api/effect', effect)
             .success(function(data, status) {
                callback(null, data);
             })
             .error(function(data, status) {
                var errors = {};
                for (var i = 0; i < data.length; i++) {
                    var err = data[i];
                    var param, msg;
                    for(var key in err){
                        if(key == 'param') param = err[key];
                        if(key == 'msg') msg = err[key];
                    }
                    errors[param] = msg;
                }
                callback(errors, null);
             });
    } else {
        $http.put('/api/effect/' + effect._id, effect);
    }
}

HTML:

<form novalidate>
    <div class="form-group">
        <label for="name" class="form-label">Name</label>
        <div class="col-xs-12" ng-class="{ 'has-error': errors.fname }">
            <input type="text" id="name" name="name" class="form-control form-input" ng-model="effect.name"
                   ng-disabled="isReadOnly" required />
            <p class="help-block" ng-model="errors.name" ng-show="(errors == null || errors == undefined) ? false : errors.name">Effect name is required</p>
        </div>
    </div>
    <div class="row">
        <div class="col-md-4 col-md-offset-8">
            <div class="form-group form-controls">
                <button id="submit" class="btn btn-success btn-input submit" ng-click="submit(effect)" ng-hide="isReadOnly">Save</button>
                <button id="clear" class="btn btn-input clear" ng-class="isReadOnly ? 'btn-primary' : 'btn-danger'" ng-click="clear()">{{clearButtonText}}</button>
            </div>
        </div>
    </div>
</form>

-> 这按预期工作。

问题:

当服务器出现错误时,错误会显示在页面上。但是一旦输入有效,错误就不会消失。简而言之,我希望一旦输入字段有效,错误就会消失。我不希望用户点击提交按钮来清除错误。

更新:

我已经对服务器中的重复项进行了另一种验证,如下所示:

index.js 文件:

app.use(expressValidator({
    customValidators: {
        duplicateRecord: function(input, propertyName, collection) {
            var duplicateRecordFound = false;
            collection.forEach(function(element) {
                if (element.propertyName == input) {
                    duplicateRecordFound = true;
                    return;
                }
            }, this);
            return duplicateRecordFound;
        }
    }
}));

路由器效果.js 文件:

router.post('/', function(req, res, next){

    Effect.find(function(err, effects) {

        if(err){
            next(err);
        }

        req.checkBody('name', 'Effect name is required.').notEmpty();
        req.checkBody('name', 'Duplicate effect name.').duplicateRecord('name', effects);
        var errors = req.validationErrors();

        console.log(errors);

        if(errors) {
            res.status(500).json(errors);
            return;
        }

        var effect = new Effect({
            name: req.body.name
        });

        Effect.createEffect(effect, function(err, result) {
            if(err) { next(err) }
            res.status(201).end();
        });

    });

});

我还按照@lean 的建议更改了角度控制器:

$scope.validate = function () {
    if($scope.errors != undefined)
    {
        if (angular.isDefined($scope.effect.name) && $scope.effect.name.length > 0) {
            $scope.errors.showName = false;
        } else {
            $scope.errors.showName = true;
        }
    }
}

$scope.submit = function(effect) {

    effectService.save(effect, function(err, result, status) {

        $scope.errors = err;

        if(err == null) {
            $scope.effect = null;
            if(!(effect == null || effect == undefined)) {
                if(!(effect._id == undefined || effect._id == '')) { 
                    $location.path('/effect');
                }
            }
            reload();
        } else {
            $scope.errors.showName = true;
        }

    });

我也将html文件中的段落元素更改如下:

<input type="text" id="name" name="name" class="form-control form-input" ng-model="effect.name"
       ng-change="validate()" ng-disabled="isReadOnly" required />
<p class="help-block" ng-model="errors.name" ng-show="(errors == null || errors == undefined) ? false : (errors.showName)">{{errors.name}}</p>

问题:

当我在输入中输入效果的名称然后单击提交按钮时,如果效果的名称已经存在于数据库中,那么我会收到一条消息说Duplicate Effect name。然后,如果我在输入框中更改一个字符,那么错误消息就会消失。到目前为止,它工作正常。但是如果我删除输入框中的所有文本,那么显示的错误消息又是Duplicate Effect name.而不是Effect name is required.

【问题讨论】:

    标签: javascript html angularjs node.js


    【解决方案1】:

    您可以在输入中使用ng-change 来调用验证器函数,如本例中的validate()

    查看

    <form novalidate>
        <div class="form-group">
            <label for="name" class="form-label">Name</label>
            <div class="col-xs-12" ng-class="{ 'has-error': errors.name }">
                <input type="text"
                       id="name"
                       name="name"
                       class="form-control form-input"
                       ng-model="effect.name"
                       ng-change="validate()"
                       ng-disabled="isReadOnly" 
                       required />
                <p class="help-block" ng-model="errors.name" ng-show="(errors == null || errors == undefined) ? false : errors.name">Effect name is required</p>
            </div>
        </div>
        <div class="row">
            <div class="col-md-4 col-md-offset-8">
                <div class="form-group form-controls">
                    <button id="submit" class="btn btn-success btn-input submit" ng-click="submit(effect)" ng-hide="isReadOnly">Save</button>
                    <button id="clear" class="btn btn-input clear" ng-class="isReadOnly ? 'btn-primary' : 'btn-danger'" ng-click="clear()">{{clearButtonText}}</button>
                </div>
            </div>
        </div>
    </form>
    

    验证$scope函数

    //init scopes
    $scope.errors = {};
    $scope.effect = {
      name: ''
    }
    
    /**
     * Manually validate fields
     */
    $scope.validate = function () {
        if (angular.isDefined($scope.effect.name) && $scope.effect.name.length > 0) {
            $scope.errors.name = false;
        } else {
            $scope.errors.name = true;
        }
    }
    

    【讨论】:

    • 很抱歉回复晚了,因为我不得不出城去做其他工作。我已尝试实施您的答案,并且对于所需的此类简单验证非常有效。但我需要更多。我的意思是,如果我从服务器验证一个名为 name 的属性,那么效果的名称不应该是重复的。在这种情况下,我无法仅从客户端完成此任务。我需要从服务器端检查。所以,当我点击保存按钮时,如果数据库中已经存在效果名称,那么我应该得到一个错误。然后当我更改名称时,错误应该会消失。
    • @Vishal 你应该实现客户端和服务端验证。从指定错误的服务器创建回调(例如 empty|noUnique){ error: true, fields: [{ name: 'name', errors: [{ empty: true, unique: true }]}]} 。抱歉,为这种处理创建一个答案将是太多了。无法在 stackoverflow 上使用服务器端验证创建有效答案。
    • 我已根据您建议的更改更新了问题。但我仍然有一些问题。有关更多信息,请查看相关更新部分。
    猜你喜欢
    • 2020-05-05
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多