angularjs - type - ng-maxlength arruina mi modelo
ng-maxlength angular 4 (7)
Intento hacer un área de texto simple con "tantos caracteres restantes" junto con la validación. cuando uso ng-maxlength para validar mi formulario, restablece mi charcount tan pronto como la longitud alcanza la longitud máxima. Aquí está el plunkr Alguna solución alternativa?
<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>
Alternativamente, puede agregar el atributo html maxlength
estándar junto con 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>
Esto cortará en "15" caracteres, como maxlength
siempre lo ha hecho, y además ng-maxlength
te permite mostrar un mensaje personalizado al llegar al límite.
Como dice el doc , la función $ validate establece el modelo como indefinido cuando la validez cambia a no válida.
Sin embargo, aún podemos evitar este comportamiento simplemente agregando allowInvalid: true
a ng-model-options.
Entonces, solo modifica tu código como:
<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>
Creo que esto debería registrarse como un error en angular. Se supone que no debe borrar su modelo. Tengo una directiva que vincula una selección desplegable a un cuadro de texto y tan pronto como inserta una palabra que lo hace ir más allá de la longitud máxima, entonces borra mi modelo y cuadro de texto. Se supone que debe Sea un validador, no borre su modelo cuando crea que el modelo no es válido.
Creo que tengo una mejor solución: establecer la longitud máxima si está presente ng-maxlength.
De esta forma obtienes ambas funciones al mismo tiempo: validaciones angulares + corte de texto
.directive("textarea", function () {
return {
restrict: "E",
link: function (scope, elem, attrs) {
if (angular.isDefined(attrs["ngMaxlength"])) {
attrs.$set("maxlength", attrs["ngMaxlength"]);
}
}
};
})
Cuando su área de texto excede los 15 caracteres, el result
undefined
ng-min/maxlength
, así es como funcionan las directivas ng-min/maxlength
. Creo que tendrás que escribir tu propia directiva. Aquí hay una directiva que bloqueará la entrada después de 15 caracteres:
<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);
}
};
});
Actualización: para permitir más de 15 caracteres, pero deshabilite el botón de enviar cuando el recuento excede de 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);
}
Si agrega un atributo de nombre al área de texto, se crea una nueva propiedad con el valor en el alcance del formulario, que puede usar para obtener la longitud del contador de caracteres.
<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>
Actualizado su plnkr
Una alternativa que estoy usando es mantener el mismo comportamiento que el validador ng-maxlength, pero retroalimentar la longitud mediante un atributo adicional ''real-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);
}
};
});
Aquí está el elemento con el atributo adicional:
<textarea name="myTextarea" new-maxlength="100" actual-length="actualLength" ng-model="text"></textarea>