36

我正在尝试使用“剩余这么多字符”以及验证来做一个简单的文本区域。当我使用 ng-maxlength 验证我的表单时,只要长度达到最大长度,它就会重置我的字符数。这是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>
4

7 回答 7

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

于 2013-06-12T22:15:39.217 回答
52

或者,您可以将标准 htmlmaxlength属性添加到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>

maxlength这将像往常一样在“15”个字符处截断,此外还ng-maxlength可以让您在达到限制时显示自定义消息。

点击查看 Plunker 示例

于 2013-08-29T17:59:09.997 回答
17

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

<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

于 2014-11-10T13:44:06.973 回答
16

正如文档所说,当有效性更改为无效时, $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>
于 2015-05-18T16:32:33.757 回答
3

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

于 2014-02-17T10:42:37.073 回答
3

我正在使用的另一种方法是保留与 ng-maxlength 验证器相同的行为,但通过额外的属性“实际长度”反馈长度。

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>
于 2014-03-26T09:48:49.037 回答
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"]);
            }
        }
    };
})
于 2014-06-24T14:35:23.063 回答