web-dev-qa-db-ja.com

ng-maxlengthでモデルをねじ止めする

検証とともに「非常に多くの文字が残っている」シンプルなテキストエリアを作成しようとしています。 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>
35
Riz

テキストエリアが15文字を超えると、resultundefinedになります。これが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


Update: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

56
Mark Rajcok

または、標準のhtml maxlength属性を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を使用すると、制限に達したときにカスタムメッセージを表示できます。

クリックしてプランカーの例

52
Thalis K.

名前属性を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 を更新しました

17
jlooooo

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>
14
Lutz

これは、角度に関するバグとして記録されるべきだと思います。モデルをクリアすることは想定されていません。ドロップダウン選択をテキストボックスにリンクするディレクティブがあり、最大長を超えるWordを挿入するとすぐにモデルとテキストボックスがクリアされます。モデルが無効であると判断したときにモデルをクリアしないバリデーターである。

3
user3232182

私が使用している代替手段は、ng-maxlengthバリデータと同じ動作を保持することですが、追加の属性「actual-length」を介して長さをフィードバックすることです。

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>
3
PenFold

私は思うより良い解決策があります:ng-maxlengthが存在する場合にmaxlengthを設定する。

この方法では、両方の機能を同時に取得できます:angular validations + text cut off

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