ng-maxlength screws up my model

后端 未结 7 869
忘掉有多难
忘掉有多难 2020-12-08 02:17

I\'m trying to do a simple textarea with \"so many chars remaining\" along with validation. when I use ng-maxlength to validate my form, it resets my charcount as soon as th

相关标签:
7条回答
  • 2020-12-08 02:49

    If you add a name attribute to the textarea then a new property with the value is created in the scope of the form, which you can use to get the length for your character counter.

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

    Updated your plnkr

    0 讨论(0)
  • 2020-12-08 02:50

    I have a better solution I think: to set the maxlength if the ng-maxlength is present.

    This way you get both features at the same time: 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 讨论(0)
  • As the doc says, the $validate function set model to undefined when validity changes to invalid.

    But, we can still prevent this behavior simply by adding allowInvalid: true to the ng-model-options.

    So, just modify your code like:

    <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>
    
    0 讨论(0)
  • 2020-12-08 02:52

    An alternative that I'm using is to retain the same behaviour as the ng-maxlength validator but to feed the length back via an extra attribute '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);
                }
            };
        });
    

    Here is the element with the extra attribute:

    <textarea name="myTextarea" new-maxlength="100" actual-length="actualLength" ng-model="text"></textarea>
    
    0 讨论(0)
  • 2020-12-08 02:55

    I think this should be logged as a bug on angular. It is not supposed to clear your model.I have a directive that links a dropdown select to a textbox and as soon as you insert a word that makes it go over the max-length then it clears my model and textbox.It is supposed to be a validator not clear your model when it thinks the model is invalid .

    0 讨论(0)
  • 2020-12-08 03:00

    Alternatively you can just add the standard html maxlength attribute alongside the 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>
    

    This will cut-off at "15" characters, as maxlength has always done, and additionally the ng-maxlength lets you show custom message upon reaching the limit.

    Click for Plunker Example

    0 讨论(0)
提交回复
热议问题