ng-maxlength搞砸了我的模型

时间:2013-06-12 21:50:35

标签: angularjs ng-maxlength

我正在尝试做一个简单的textarea,其中包含“剩余的那么多字符”以及验证。 当我使用ng-maxlength来验证我的表单时,只要长度达到最大长度,它就会重置我的charcount。这是plunkr任何解决方法吗?

  <body ng-controller="MainCtrl">
    <div ng-form="noteForm">
      <textarea ng-maxlength="15" ng-model="result"></textarea>
      <p>{{15 - result.length}} chars remaining</p>
      <button ng-disabled="!noteForm.$valid">Submit</button>
    </div>
  </body>

7 个答案:

答案 0 :(得分:56)

当您的textarea超过15个字符时,result变为undefined - 这就是ng-min/maxlength指令的工作方式。我想你必须编写自己的指令。这是一个将在15个字符后阻止输入的指令:

<textarea my-maxlength="15" ng-model="result"></textarea>
app.directive('myMaxlength', function() {
  return {
    require: 'ngModel',
    link: function (scope, element, attrs, ngModelCtrl) {
      var maxlength = Number(attrs.myMaxlength);
      function fromUser(text) {
          if (text.length > maxlength) {
            var transformedInput = text.substring(0, maxlength);
            ngModelCtrl.$setViewValue(transformedInput);
            ngModelCtrl.$render();
            return transformedInput;
          } 
          return text;
      }
      ngModelCtrl.$parsers.push(fromUser);
    }
  }; 
});

fiddle


更新:允许超过15个字符,但在计数超过15时禁用提交按钮:

link: function (scope, element, attrs, ngModelCtrl) {
  var maxlength = Number(attrs.myMaxlength);
  function fromUser(text) {
      ngModelCtrl.$setValidity('unique', text.length <= maxlength);
      return text;
  }
  ngModelCtrl.$parsers.push(fromUser);
}

fiddle

答案 1 :(得分:52)

或者,您只需在maxlength旁边添加标准html ng-maxlength属性。

<form name="myForm">
    <textarea name="myTextarea" ng-maxlength="15" maxlength="15" ng-model="result"></textarea>
    <span class="error" ng-show="myForm.myTextarea.$error.maxlength">
         Reached limit!
     </span>
</form>

这将截止“15”个字符,maxlength总是这样做,此外ng-maxlength可让您在达到限制时显示自定义消息。

Click for Plunker Example

答案 2 :(得分:17)

如果向textarea添加name属性,则会在表单范围内创建一个具有该值的新属性,您可以使用该属性获取字符计数器的长度。

<body ng-controller="MainCtrl">
  <div ng-form="noteForm">
    <textarea ng-maxlength="15" name="noteItem" ng-model="result"></textarea>
    <p>{{15 - noteForm.noteItem.$viewValue.length}} chars remaining</p>
    <button ng-disabled="!noteForm.$valid">Submit</button>
  </div>
</body>

更新了您的plnkr

答案 3 :(得分:14)

正如doc所说,$ validate函数在有效性变为无效时将模型设置为未定义。

但是,我们仍然可以通过将allowInvalid: true添加到ng-model-options来阻止此行为。

因此,只需修改您的代码,如:

<body ng-controller="MainCtrl">
    <div ng-form="noteForm">
        <textarea ng-maxlength="15" ng-model="result" 
            ng-model-options="{ allowInvalid: true }"></textarea>
        <p>{{15 - result.length}} chars remaining</p>
        <button ng-disabled="!noteForm.$valid">Submit</button>
    </div>
</body>

答案 4 :(得分:3)

我认为这应该记录为角度上的错误。它不应该清除你的模型。我有一个指令将下拉选择链接到一个文本框,一旦你插入一个单词使它超过最大长度然后它清除我的模型和文本框。它应该是当认为模型无效时,作为验证者不清楚你的模型。

答案 5 :(得分:3)

我使用的替代方法是保留与ng-maxlength验证器相同的行为,但通过额外的属性&#39;实际长度&#39;来提供长度。

app.directive('newMaxlength', function () {
        return {
            require: 'ngModel',
            scope: {
                maxlength: '=newMaxlength',
                actualLength: '='
            },
            link: function (scope, elem, attr, ngModelCtrl) {

                function validate(ctrl, validatorName, validity, value) {
                    ctrl.$setValidity(validatorName, validity);
                    return validity ? value : undefined;
                }

                var maxlength = parseInt(scope.maxlength, 10);
                var maxLengthValidator = function (value) {
                    scope.actualLength = value ? value.length : 0;
                    return validate(ngModelCtrl, 'maxlength', ngModelCtrl.$isEmpty(value) || value.length <= maxlength, value);
                };

                ngModelCtrl.$parsers.push(maxLengthValidator);
                ngModelCtrl.$formatters.push(maxLengthValidator);
            }
        };
    });

这是具有额外属性的元素:

<textarea name="myTextarea" new-maxlength="100" actual-length="actualLength" ng-model="text"></textarea>

答案 6 :(得分:0)

我认为我有一个更好的解决方案:如果存在ng-maxlength,则设置maxlength。

这样您可以同时获得两种功能:角度验证+文本切断

.directive("textarea", function () {
    return {
        restrict: "E",
        link: function (scope, elem, attrs) {
            if (angular.isDefined(attrs["ngMaxlength"])) {
                attrs.$set("maxlength", attrs["ngMaxlength"]);
            }
        }
    };
})