検証とともに「非常に多くの文字が残っている」シンプルなテキストエリアを作成しようとしています。 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>
テキストエリアが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);
}
};
});
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);
}
または、標準の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
を使用すると、制限に達したときにカスタムメッセージを表示できます。
名前属性を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 を更新しました
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>
これは、角度に関するバグとして記録されるべきだと思います。モデルをクリアすることは想定されていません。ドロップダウン選択をテキストボックスにリンクするディレクティブがあり、最大長を超えるWordを挿入するとすぐにモデルとテキストボックスがクリアされます。モデルが無効であると判断したときにモデルをクリアしないバリデーターである。
私が使用している代替手段は、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>
私は思うより良い解決策があります: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"]);
}
}
};
})