2013-06-12 10 views
35

Ich versuche, eine einfache Textarea mit "so viele Zeichen verbleibenden" zusammen mit Validierung zu tun. Wenn ich mit ng-maxlength mein Formular validiere, setzt es mein Charcount zurück, sobald die Länge die maximale Länge erreicht. Hier ist die plunkr Problemumgehungen?ng-maxlength verschraubt mein Modell

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

Lustige Sache, aber für mich (mit Schräg 1.4.7 + 1.8.7 Typoskript) Verwendung von HTML-Attribute „maxLength“ hatte denselben Effekt wie hier erwähnt "ng-maxLength": Nachdem ein großer Wert (größer als das definierte Limit) direkt in das Modell eingegeben wurde, wird der Wert im Modell undefiniert. Aus meiner Sicht ist dies ein Angular Bug (genau wie [user3232182] (http://stackoverflow.com/users/3232182/user3232182) oben erwähnt). Wahrscheinlich sogar nicht mit ng-maxLength directve verbunden, sondern mit dem ganzen Bindungsmechanismus. – bkg

Antwort

55

Wenn Ihr Textfeld 15 Zeichen überschreitet, wird resultundefined —, die gerade ist, wie die ng-min/maxlength Richtlinien arbeiten. Ich denke, du musst deine eigene Direktive schreiben. Hier ist eine Richtlinie, die Eingabe nach 15 Zeichen blockieren:

<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: zu ermöglichen, mehr als 15 Zeichen, aber deaktivieren die Absenden-Button, wenn die Zählung überschreitet 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

vielen Dank. Ich wollte, dass es darüber hinausgeht und negativ wie Twitter zeigt, aber das ist gut genug :) – Riz

+0

@Riz, siehe aktualisierte Antwort. –

+0

brilliant! Dies sollte standardmäßig das ng-maxlength-Verhalten sein. Vielleicht können Sie dies zu eckigen schieben;) – Riz

52

Alternativ können Sie nur das Standard-HTML-maxlength Attribut neben den ng-maxlength hinzufü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 cut-off, wie maxlength immer getan hat, und zusätzlich die ng-maxlength können Sie benutzerdefinierte Nachricht zeigen die Grenze bei Erreichen.

Click for Plunker Example

+0

Ich denke, das ist bei weitem der beste Ansatz. –

+0

Dies umfasst auch Einfügen in Text größer als die maximale, danke. –

+0

Ja, das ist, wie ich es funktionierte, obwohl es nicht so effizient ist, da ich den gleichen Wert in beiden Attributen wiederholen müsste ... –

3

Ich denke, dies als ein Fehler auf Winkel protokolliert werden soll. Es soll nicht Ihr Modell löschen. Ich habe eine Direktive, die eine Dropdown-Auswahl mit einem Textfeld verknüpft und sobald Sie ein Wort einfügen, das es über die maximale Länge geht dann löscht es mein Modell und Textbox.Es soll Seien Sie ein Validierer, wenn Sie das Modell nicht für ungültig halten.

3

Eine Alternative, die ich verwende, besteht darin, das gleiche Verhalten wie beim ng-maxlength-Validator beizubehalten, aber die Länge über ein zusätzliches Attribut 'tatsächliche Länge' zurückzugeben. Hier

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

ist das Element, mit dem zusätzlichen Attribute:

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

Ich habe eine bessere Lösung, die ich denke: die maxlength zu setzen, wenn die ng-maxlength vorhanden ist.

Auf diese Weise können beide Funktionen gleichzeitig erhalten: Winkel Validierungen + Text abgeschnitten

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

Dies funktioniert nicht in IE 9 wie ATTR maxlength funktioniert nur in HTML5 – alecellis1985

+0

in der Tat. aber Sie könnten Polyfills für diesen Fall verwenden, denke ich. Beispiel gefunden: http://stackoverflow.com/questions/1125482/how-to-impose-maxlength-on-textarea-in-html-using-javascript/1125521#1125521, obwohl ich nicht versucht habe, es innerhalb der arbeiten Richtlinie, aber ich denke, es ist nicht so schwer. DANKE FÜR DEN TIPP! –

16

Wenn Sie einen Namen Attribut auf das Textfeld fügen Sie dann eine neue Eigenschaft mit dem Wert im Rahmen geschaffen das Formular, mit dem Sie die Länge Ihres Charakterzählers 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 Ihre plnkr

+1

Dieser ist nett und benötigt keinen zusätzlichen Code. Vielen Dank! – yarl

+1

Warum hat diese Antwort nicht mehr Upvotes. So schnell und einfach auf den Punkt. : D Danke und ja bitte – BrettS

13

Wie die doc sagt, das $ validate Funktionssatz-Modell nicht definiert, wenn Änderungen Gültigkeit ungültig.

Aber wir können immer noch dieses Verhalten verhindern, indem wir einfach allowInvalid: true zu den ng-Modell-Optionen hinzufügen.

So ändern Sie einfach Ihren Code wie:

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

Das sollte die richtige Antwort sein –

+0

Danke mein Mann! – Wax

Verwandte Themen