it-swarm.com.de

ng-maxlength vermasselt mein Modell

Ich versuche, ein einfaches Textfeld mit "so vielen verbleibenden Zeichen" zusammen mit der Validierung zu erstellen. Wenn ich mein Formular mit ng-maxlength validiere, wird mein Charcount zurückgesetzt, sobald die Länge die maximale Länge erreicht. Ist hier das plunkr Irgendwelche Problemumgehungen?

  <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

Wenn Ihr Textbereich 15 Zeichen überschreitet, wird result zu undefined - genau so wird das ng-min/maxlength Direktiven arbeiten. Ich denke, Sie müssen Ihre eigene Richtlinie schreiben. Hier ist eine Anweisung, die die Eingabe nach 15 Zeichen blockiert:

<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: um mehr als 15 Zeichen zuzulassen, aber deaktivieren Sie die Submit-Schaltfläche, wenn die Anzahl 15 überschreitet:

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

Alternativ können Sie neben ng-maxlength Auch das Standardattribut html maxlength einfügen.

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

Dies wird bei "15" Zeichen abgeschnitten, wie es maxlength immer getan hat, und zusätzlich können Sie mit ng-maxlength Benutzerdefinierte Meldungen anzeigen, wenn das Limit erreicht ist.

Klick für Plunker-Beispiel

52
Thalis K.

Wenn Sie dem Textbereich ein Namensattribut hinzufügen, wird im Gültigkeitsbereich des Formulars eine neue Eigenschaft mit dem Wert erstellt, mit der Sie die Länge für Ihren Zeichenzähler ermitteln können.

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

Aktualisiert Ihr plnkr

17
jlooooo

Wie in doc angegeben, setzt die Funktion $ validate das Modell auf undefiniert, wenn die Gültigkeit ungültig wird.

Aber wir können dieses Verhalten trotzdem verhindern, indem wir einfach allowInvalid: true Zu den ng-model-Optionen hinzufügen.

Ändern Sie einfach Ihren Code wie folgt:

<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

Ich denke, das sollte als Bug on Angular protokolliert werden. Es soll Ihr Modell nicht löschen. Ich habe eine Anweisung, die eine Dropdown-Auswahl mit einem Textfeld verknüpft. Sobald Sie ein Wort einfügen, das die maximale Länge überschreitet, werden mein Modell und mein Textfeld gelöscht Seien Sie ein Prüfer, der Ihr Modell nicht löscht, wenn er denkt, dass das Modell ungültig ist.

3
user3232182

Eine Alternative, die ich verwende, besteht darin, dasselbe Verhalten wie der ng-maxlength-Validator beizubehalten, die Länge jedoch über ein zusätzliches Attribut 'actual-length' zurückzuspeisen.

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);
            }
        };
    });

Hier ist das Element mit dem zusätzlichen Attribut:

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

Ich denke, ich habe eine bessere Lösung: die maximale Länge einstellen, wenn die ng-maximale Länge vorhanden ist.

Auf diese Weise erhalten Sie beide Funktionen gleichzeitig: angular Validierungen + abgeschnittener Text)

.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