javascript - w3schools - Evitar el ingreso de caracteres adicionales
textcontent javascript (3)
Estoy usando esta directiva angular para dar formato a los números de teléfono en una entrada al (999) 999-9999
. Esto funciona muy bien hasta que un usuario comete un error y modifica el número de teléfono ingresado.
Puede replicar este problema ejecutando el siguiente código y haciendo lo siguiente:
• Ingrese el número de teléfono (555) 123-4567
• Coloque su cursor después de los 4
caracteres y elimínelo.
• Escriba 0
dos veces.
Puede ver que el 0
se agrega dos veces y el carácter 7
se suelta.
Otro problema es si un usuario intenta eliminar y cambiar el carácter 1
. Su cursor es empujado hasta el final de la entrada.
Estoy seguro de que esto se debe a un problema con el filtro de número de teléfono, pero no estoy seguro de cómo abordar esto.
function MyCntl($scope) {
$scope.myModel = {};
$scope.myPrompt = "Input your phonenumber here!";
}
var phonenumberModule = angular.module(''phonenumberModule'', [])
.directive(''phonenumberDirective'', [''$filter'', function($filter) {
/*
Intended use:
<phonenumber-directive placeholder=''prompt'' model=''someModel.phonenumber''></phonenumber-directive>
Where:
someModel.phonenumber: {String} value which to bind only the numeric characters [0-9] entered
ie, if user enters 617-2223333, value of 6172223333 will be bound to model
prompt: {String} text to keep in placeholder when no numeric input entered
*/
function link(scope, element, attributes) {
// scope.inputValue is the value of input element used in template
scope.inputValue = scope.phonenumberModel;
scope.$watch(''inputValue'', function(value, oldValue) {
value = String(value);
var number = value.replace(/[^0-9]+/g, '''');
scope.phonenumberModel = number;
scope.inputValue = $filter(''phonenumber'')(number);
});
}
return {
link: link,
restrict: ''E'',
scope: {
phonenumberPlaceholder: ''=placeholder'',
phonenumberModel: ''=model'',
},
//templateUrl: ''/static/phonenumberModule/template.html'',
template: ''<input name="phonenumber" ng-model="inputValue" type="tel" class="phonenumber" placeholder="{{phonenumberPlaceholder}}" title="Phonenumber (Format: (999) 9999-9999)">'',
};
}])
.filter(''phonenumber'', function() {
/*
Format phonenumber as: c (xxx) xxx-xxxx
or as close as possible if phonenumber length is not 10
if c is not ''1'' (country code not USA), does not use country code
*/
return function (number) {
/*
@param {Number | String} number - Number that will be formatted as telephone number
Returns formatted number: (###) ###-####
if number.length < 4: ###
else if number.length < 7: (###) ###
Does not handle country codes that are not ''1'' (USA)
*/
if (!number) { return ''''; }
number = String(number);
// Will return formattedNumber.
// If phonenumber isn''t longer than an area code, just show number
var formattedNumber = number;
// if the first character is ''1'', strip it out and add it back
var c = (number[0] == ''1'') ? ''1 '' : '''';
number = number[0] == ''1'' ? number.slice(1) : number;
// # (###) ###-#### as c (area) front-end
var area = number.substring(0,3);
var front = number.substring(3, 6);
var end = number.substring(6, 10);
if (front) {
formattedNumber = (c + "(" + area + ") " + front);
}
if (end) {
formattedNumber += ("-" + end);
}
return formattedNumber;
};
});
.phonenumber {
min-width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="phonenumberModule" ng-controller="MyCntl">
<p>phonenumber value: {{ myModel.phonenumber }}</p>
<p>formatted phonenumber: {{ myModel.phonenumber | phonenumber }}</p>
<form name="phoneForm">
<phonenumber-directive placeholder="myPrompt" model=''myModel.phonenumber''></phonenumber-directive>
<div ng-show="phoneForm.phonenumber.$error.minlength">
<p>Enter a valid phone number</p>
</div>
</form>
</div>
¿Puedes revisar el plunker por favor ... espero que esto sea lo que quieres?
http://plnkr.co/edit/0IBJBRb2JtvZnq6PtBiV?p=preview
uso de enmascaramiento y expresiones regulares (es beta) Uso: # para ambos, a para caracteres, 9 es para números ... (el filtro de máscara no funciona como fue aceptado, lo comprobará ...
<maskinput ng-mask-model="value" ng-mask="9 (999) 99-9999" ng-mask-regex="[^0-9]+"></maskinput>
Creo que debería usar un campo editable (como la entrada de texto de tipo) para ingresar el número y un campo de solo lectura (como una etiqueta) para mostrarlo con formato, ya que el valor formateado es solo un problema de visualización, por lo que no debería editable
Así que modifiqué tu fragmento para hacer eso.
function MyCntl($scope) {
$scope.myModel = {};
$scope.myPrompt = "Input your phonenumber here!";
}
var phonenumberModule = angular.module(''phonenumberModule'', [])
.directive(''phonenumberDirective'', [''$filter'', function($filter) {
/*
Intended use:
<phonenumber-directive placeholder=''prompt'' model=''someModel.phonenumber''></phonenumber-directive>
Where:
someModel.phonenumber: {String} value which to bind only the numeric characters [0-9] entered
ie, if user enters 617-2223333, value of 6172223333 will be bound to model
prompt: {String} text to keep in placeholder when no numeric input entered
*/
function link(scope, element, attributes) {
// scope.inputValue is the value of input element used in template
scope.inputValue = scope.phonenumberModel;
scope.$watch(''inputValue'', function(value, oldValue) {
value = String(value);
oldValue = String(oldValue);
// get rid of input non digits chars
var number = value.replace(/[^0-9]+/g, '''');
var oldNumber = oldValue.replace(/[^0-9]+/g, '''');
var filteredNumber = $filter(''phonenumber'')(number);
// get rid of filter non digits chars
scope.phonenumberModel = filteredNumber.replace(/[^0-9]+/g, '''');
inputValue = scope.phonenumberModel;
var filteredOldNumber = $filter(''phonenumber'')(oldNumber);
if(filteredNumber.length === filteredOldNumber.length) {
scope.maxlength = filteredNumber.length;
}
else {
scope.maxlength = Math.max(number.length, 11);
}
});
}
return {
link: link,
restrict: ''E'',
scope: {
phonenumberPlaceholder: ''=placeholder'',
phonenumberModel: ''=model'',
},
//templateUrl: ''/static/phonenumberModule/template.html'',
template: ''<input name="phonenumber" ng-model="inputValue" type="tel" maxlength="{{maxlength || 11}}" class="phonenumber" placeholder="{{phonenumberPlaceholder}}" title="Phonenumber (Format: (999) 9999-9999)"> <label>Formatted:{{inputValue | phonenumber}}</label>'',
};
}])
.filter(''phonenumber'', function() {
/*
Format phonenumber as: c (xxx) xxx-xxxx
or as close as possible if phonenumber length is not 10
if c is not ''1'' (country code not USA), does not use country code
*/
return function (number) {
/*
@param {Number | String} number - Number that will be formatted as telephone number
Returns formatted number: (###) ###-####
if number.length < 4: ###
else if number.length < 7: (###) ###
Does not handle country codes that are not ''1'' (USA)
*/
if (!number) { return ''''; }
number = String(number);
// Will return formattedNumber.
// If phonenumber isn''t longer than an area code, just show number
var formattedNumber = number;
// if the first character is ''1'', strip it out and add it back
var c = (number[0] == ''1'') ? ''1 '' : '''';
number = number[0] == ''1'' ? number.slice(1) : number;
// # (###) ###-#### as c (area) front-end
var area = number.substring(0,3);
var front = number.substring(3, 6);
var end = number.substring(6, 10);
if (front) {
formattedNumber = (c + "(" + area + ") " + front);
}
if (end) {
formattedNumber += ("-" + end);
}
return formattedNumber;
};
});
.phonenumber {
min-width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="phonenumberModule" ng-controller="MyCntl">
<p>phonenumber value: {{ myModel.phonenumber }}</p>
<p>formatted phonenumber: {{ myModel.phonenumber | phonenumber }}</p>
<form name="phoneForm">
<phonenumber-directive placeholder="myPrompt" model=''myModel.phonenumber''></phonenumber-directive>
<div ng-show="phoneForm.phonenumber.$error.minlength">
<p>Enter a valid phone number</p>
</div>
</form>
</div>
Modificar la entrada de un usuario a medida que escribe puede distraer y siempre conduce a problemas como los que describe.
En general, es más fácil de implementar y menos frustrante para el usuario modificar la IU en su lugar. Una solución común para el caso de los números de teléfono es colocar tres campos de entrada uno al lado del otro, con los caracteres de formato mostrados en el medio.
Usando Angular, se puede crear una única directiva para envolver este mecanismo de entrada de varias partes y exponer un solo resultado concatenado al resto de la aplicación.