在模型更改时触发自定义AngularJS表单验证

时间:2022-03-13 08:04:11

I have a custom validation directive that I use to ensure two dates are within a valid range. The directive works fine when a user changes the values, however it does not trigger when I load in a new lineItem model via AJAX.

我有一个自定义验证指令,用于确保两个日期在有效范围内。当用户更改值时,该指令工作正常,但是当我通过AJAX加载新的lineItem模型时,它不会触发。

The problem is that a user could enter invalid dates on the form and trigger the error, then load another lineItem. At this point, there is an error message on the form even though the data in the form is valid.

问题是用户可能在表单上输入无效日期并触发错误,然后加载另一个lineItem。此时,即使表单中的数据有效,表单上也会显示一条错误消息。

If I try the same thing with Angular's built in validation (like required), the validation triggers and disappears appropriately. So, what do I need to do to make my validation trigger the same way as Angular's?

如果我使用Angular的内置验证(如需要)尝试相同的操作,验证会触发并适当地消失。那么,我需要做什么才能使我的验证触发器与Angular相同?

(note: I'm using novalidate on the form attribute, and Angular v1.1.5)

(注意:我在表单属性和Angular v1.1.5上使用了novalidate)

DIRECTIVE

指示

ngApp.directive("validateBefore", function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ctrl) {
            ctrl.$parsers.unshift(function(value) {
                var before = scope.$eval(attrs.validateBefore);
                if(value <= before || !before) {
                    ctrl.$setValidity("validateBefore", true);
                    return value;
                } else {
                    ctrl.$setValidity("validateBefore", false);
                    return undefined;
                }
            });
        }
    }
});

TEMPLATE

模板

<div class="date-group">
    <span class="date">
        <input type="text" class="input-medium" name="starts-at" ng-model="lineItem.startsAt" placeholder="From..." validate-before="lineItem.endsAt">  
    </span>

    <span class="date">
        <input type="text" class="input-medium" name="ends-at" ng-model="lineItem.endsAt" placeholder="To..." validate-after="lineItem.startsAt"> 
    </span>    
</div>

CONTROLLER

CONTROLLER

var lineItem = LineItem.get( { id: lineItemId }, function () {
    $scope.lineItem = lineItem;

    if($scope.lineItemForm) {
        $scope.lineItemForm.$setPristine();
    }
}

1 个解决方案

#1


10  

Ah-hah, I was only accounting for half of the equation. The $parsers fire when input is sent from the DOM to the model. I needed to add $formatters, which sends data from the model to the DOM.

啊哈,我只占了等式的一半。当输入从DOM发送到模型时,$解析器触发。我需要添加$ formatters,它将数据从模型发送到DOM。

After the $parsers, I added the following:

在$解析器之后,我添加了以下内容:

ctrl.$formatters.unshift(function(value) {
    var before = scope.$eval(attrs.validateBefore);
    ctrl.$setValidity("validateBefore", before ? value <= before : true);
    return value;
});

This causes validation to fire the moment the model is changed. It's discussed more here: http://docs.angularjs.org/guide/forms, and here http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController#$formatters

这会导致验证在模型更改时触发。这里讨论的更多:http://docs.angularjs.org/guide/forms,这里http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController#$formatters

#1


10  

Ah-hah, I was only accounting for half of the equation. The $parsers fire when input is sent from the DOM to the model. I needed to add $formatters, which sends data from the model to the DOM.

啊哈,我只占了等式的一半。当输入从DOM发送到模型时,$解析器触发。我需要添加$ formatters,它将数据从模型发送到DOM。

After the $parsers, I added the following:

在$解析器之后,我添加了以下内容:

ctrl.$formatters.unshift(function(value) {
    var before = scope.$eval(attrs.validateBefore);
    ctrl.$setValidity("validateBefore", before ? value <= before : true);
    return value;
});

This causes validation to fire the moment the model is changed. It's discussed more here: http://docs.angularjs.org/guide/forms, and here http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController#$formatters

这会导致验证在模型更改时触发。这里讨论的更多:http://docs.angularjs.org/guide/forms,这里http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController#$formatters