【问题标题】:Angular: how to fire ngChange when input type="number" but not entered a numberAngular:输入类型=“数字”但未输入数字时如何触发ngChange
【发布时间】:2017-02-22 11:47:42
【问题描述】:

我正在构建一个角度指令,其中我有两个数字输入,它们一起代表一个年龄范围。

我想要实现的是能够通过以下方式使用该指令:

<input-age-range
    name="ageRange"
    ng-model="filterUpdateVM.ageRange">
</input-age-range>
<span ng-if="myCtrlVM.form.ageRange.$error.ageRange">
    Please, enter a valid age range.
</span>

并且能够在输入的年龄范围不正确时显示自定义错误。

我的指令 html 模板看起来是这样的:

<div class="col-md-3">
    <input type="number"
           class="form-control"
           placeholder="Minimum age"
           name="ageMin"
           min="18"
           max="80"
           ng-change="checkAndValidateAgeRange()"
           ng-model="ageRange.ageMin"
           ng-model-options="{allowInvalid: true}">
</div>
<div class="col-md-3">
    <input type="number"
           class="form-control"
           placeholder="Maximum age"
           name="ageMax"
           min="18"
           max="80"
           ng-change="checkAndValidateAgeRange()"
           ng-model="ageRange.ageMax"
           ng-model-options="{allowInvalid: true}">
</div>

每次用户在输入中输入任何内容时,我都希望检查输入的范围是否正确:

  • 两个年龄都应该是数字
  • 两个年龄都应该在 18 到 80 岁之间
  • ageMin

到目前为止,ng-model-options="{allowInvalid: true}" 将触发我指令中的 ngChange 函数,以防输入的任何年龄不在所需的年龄范围 (18-80) 之间 - 这样我可以进行一些检查并设置输入如果有错误并显示它。

我的问题是,如果最初输入的年龄不是数字,则不会调用 ngChange:它将无法进行错误检查,因此不会显示任何错误。在这种情况下,如何在不更改输入 type="number" 的情况下调用我的 ngChange 函数?

编辑:已添加 Jsfiddle: http://jsfiddle.net/afkf96qh/

【问题讨论】:

  • 如果type="number" 那么有人如何输入不是数字
  • @Kumkar 即:'eeeee')
  • 输入任意字符。
  • @PetrAveryanov 然后在ng-change 上我们可以检查值是否包含eeeee
  • @Kumkar 如果输入的 minAge 不是数字,则会收到 form.ageMin.$error.number 错误,但不会触发 ngChange。我想在我的指令中检查这个错误以设置 ngModel 的有效性,并能够在使用我的指令时捕获错误。

标签: javascript angularjs input frontend


【解决方案1】:

终于在尝试了一天之后,我实现了我正在寻找的行为。

首先,ng-model-options="{allowInvalid: true}" 与解决我的问题无关,因此我将其从输入中删除。我的指令 html 模板现在看起来是这样的:

<div class="col-md-3">
    <input type="number"
           class="form-control"
           placeholder="Minimum age"
           name="ageMin"
           min="18"
           max="80"
           ng-model="ageRange.ageMin"
           ng-change="checkAndValidateAgeRange()">
</div>
<div class="col-md-3">
    <input type="number"
           class="form-control"
           placeholder="Maximum age"
           name="ageMax"
           min="18"
           max="80"
           ng-model="ageRange.ageMax"
           ng-change="checkAndValidateAgeRange()">
</div>

导致未触发 ng-change="checkAndValidateAgeRange()" 的问题是我在 ngModel $render 函数中初始化 ageRange 变量的方式:

angular
    .module('myModule')
    .directive('myDirective', myDirective);

function myDirective() {

    var directive = {
        templateUrl: 'myTemplate.html',
        restrict: 'E',
        require:  ['^form', 'ngModel'],
        link: linkFunc
    };

    return directive;

    /////////

    function linkFunc(scope, element, attrs, ctrls) {
        scope.form = ctrls[0];
        scope.ageRange = {};
        scope.checkAndValidateAgeRange = checkAndValidateAgeRange;

        var ngModel = ctrls[1];
        ngModel.$render = getAgeRange;

        function checkAndValidateAgeRange() {
            // fired when the model changes
        };

        // $render function
        function getAgeRange() {
            scope.ageRange.ageMin = ngModel.$viewValue.ageMin;
            scope.ageRange.ageMax = ngModel.$viewValue.ageMax;
        };
    };

};

在某些情况下,传递给指令的 ngModel 对象的两个属性 - ageMinageMax - 可能是 undefined

而且我们都知道当我们有一个带有限制的输入时会发生什么,例如type="[whatever]"min="18"max="80",并且在该输入中输入的数据不符合这些要求:它被设置为undefined in模型。

因此,如果上述属性最初被传递给设置为 undefined 的指令,并且您在 &lt;input type="number ...&gt; 中输入了一个值,例如,它不是数字......绑定模型的值仍然是 @987654336 @,因此模型中不会有任何更改使 ng-change 不触发。

我最终解决这个问题的方法是将ageRange.ageMinageRange.ageMax 初始化为null,如果它们作为undefined 传递,在我的$render 函数中:

ngModel.$render = getAgeRange;

// $render function
function getAgeRange() {
    scope.ageRange.ageMin = ngModel.$viewValue.ageMin || null;
    scope.ageRange.ageMax = ngModel.$viewValue.ageMax || null;
};

这样,当输入无效输入时,模型的属性值将从null 更改为undefined,从而触发ng-change

【讨论】:

    【解决方案2】:

    结帐this fiddle

    $scope.checkAndValidateAgeRange = function(name, model) {
        if (name === 'ageMin') {
            if (angular.isNumber(model)) {
                if (model < $scope.age.min) {
                    $scope.minAgeMessage = 'You are under age';
                } else if (model > $scope.age.max) {
                    $scope.minAgeMessage = 'You are too old';
                } else {
                    $scope.minAgeMessage = '';
                }
            } else {
                $scope.minAgeMessage = 'Enter Only Numbers';
                $scope.ageRange.ageMin = null;
            }
        }
    
        if (name === 'ageMax') {
            if (angular.isNumber(model)) {
                if (model <= $scope.ageRange.ageMin) {
                    $scope.maxAgeMessage = 'You are under age';
                } else if (model > $scope.age.max) {
                    $scope.maxAgeMessage = 'You are too old';
                } else {
                    $scope.maxAgeMessage = '';
                }
            } else {
                $scope.maxAgeMessage = 'Enter Only Numbers';
                $scope.ageRange.ageMax = null;
            }
        }
    }
    

    【讨论】:

    • 你好!感谢您的回答,但我并不想弄清楚逻辑是什么(我已经有了它!)。在您的情况下,您使用一些默认值初始化 ageMin 和 ageMax,这是我不感兴趣的事情。我只是希望能够触发我的 ngChange 函数,无论输入什么值。
    • 另外,在我的指令中,我会使用ngModel.$setValidity('ageRange', true); 来处理和显示指令之外的错误——那些我会使用它的地方——而不是在指令。
    • 我知道基本逻辑放在了控制器中,但我这样做的原因是为了证明我所拥有的工作正常,并且您对我所拥有的有所了解。
    • 还想利用 min-max 输入属性,在您的情况下,您正在以这种方式验证model &lt;= $scope.ageRange.ageMin 它在scope.form.ageMin.$error. 也可见,您明白我的意思吗? :-)
    • 这就是我要求代码 sn-p 的原因,你可以在给定的小提琴中添加你的指令,它可能有助于我理解你面临的问题。
    【解决方案3】:

    您不能在给定 here 的 type='number' 上使用 allowInvalid。如果使用 type='number' 的意图显示验证消息,则可以设置 type='text' 然后在 ng-change 处理程序中处理验证。

    要在控制器中设置表单的有效性,请参考this link

    【讨论】:

    • 我终于解决了我的问题,我自己已经回答了这个问题。有兴趣的可以去看看!无需将类型从number 更改为text
    猜你喜欢
    • 1970-01-01
    • 2012-08-05
    • 2021-12-09
    • 2020-10-05
    • 2018-11-13
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多