jquery - example - laravel mask input
Conflicto entre jQuery Validate y Masked Input (6)
¿Importa el orden en que hagas la encuadernación? Por ejemplo, ¿hay una diferencia entre
$(function() {
var $form = $("#myForm"), $zip = $("#zip");
$zip.mask("99999?-9999");
$form.validate();
});
y
$(function() {
var $form = $("#myForm"), $zip = $("#zip");
$form.validate();
$zip.mask("99999?-9999");
});
Creo que las fijaciones deben dispararse en orden.
Tengo un formulario que usa jQuery Validate y Masked Input para los campos de número de teléfono y código postal de EE. UU.
Por ejemplo, para un código postal de EE. UU., La entrada enmascarada permite que solo se ingresen números y fuerza el formato "99999" o "99999-9999" (donde 9 puede ser cualquier número). La regla Validar requiere lo mismo. Pero en algunos casos, Validar marca un campo como no válido cuando realmente debería ser válido.
Códigos específicos
La expresión regular que está utilizando jQuery Validate en el campo del código postal es ^/d{5}$|^/d{5}/-/d{4}$
.
La máscara que estoy aplicando con la entrada enmascarada es .mask(''99999?-9999'')
pasos para reproducir
Un conflicto entre ellos se produce cuando hago lo siguiente:
- Rellene un código postal no válido (por ejemplo, tres dígitos)
- Pestaña lejos del campo. La entrada enmascarada borra la entrada (comportamiento esperado) y jQuery Validate lo marca como no válido porque está en blanco (también se espera).
- Vuelva al campo zip y complete un zip válido de 5 dígitos .
- Pestaña lejos del campo. Todavía está marcado como no válido. Esto es inesperado .
Este problema no ocurre si completo un código postal de 9 dígitos.
Hipótesis
Creo que este error se debe a que, en el caso del zip de 5 dígitos, Masked Input ha insertado temporalmente "-____" para mostrar al usuario que puede ingresar opcionalmente un guión y cuatro dígitos más. Esto se elimina en el desenfoque, pero antes de eliminarlo, el campo se valida y falla, ya que no se permiten guiones bajos.
Esta hipótesis se apoya en el hecho de que, si el formulario se vuelve a validar posteriormente, el campo zip pasará. He hecho esto de dos maneras:
- Al enviar el formulario; todos los campos se vuelven a validar cuando se hace clic en el botón de envío, se pasa el campo zip y se envía el formulario.
Al configurar un evento de
blur
que vuelve a validar ese campo específico. Por ejemplo:$ ("# zipcode"). blur (function () {$ (this) .closest (''form''). validate (). element ($ (this));});
Esto puede servir como una solución pirata , pero no es muy satisfactorio, porque 1) la configuración predeterminada ya se vuelve a validar en el desenfoque, por lo que es repetitivo, y 2) requiere un código adicional además de las reglas normales de Validación.
¿Alguien más se ha topado con este problema? ¿Tiene una solución más elegante que configurar un detector de eventos de desenfoque adicional?
Actualización: aplicando la solución hacky.
Incluso la aplicación de la solución hacky anterior no funciona tan bien como me gustaría. Por ejemplo, esto no funciona:
$appDiv.delegate(''input,select,textarea'',''blur'',function(){
$(this).closest(''form'').validate().element($(this));
});
... ni tampoco esto:
$(''input,select,textarea'').live(''blur'',function(){
$(this).closest(''form'').validate().element($(this));
});
... pero esto hace:
$(''input,select,textarea'').each(function(){
$(this).blur(function(){
$(this).closest(''form'').validate().element($(this));
});
});
Como AJAX carga estos elementos, la versión .each
debe ejecutarse cada vez que se carga una sección de formulario.
En realidad estaba buscando una respuesta a esta pregunta exacta. Acabé descubriendo una solución más confiable.
Dado que estoy definiendo mi propio método de validación para el código postal, lo modifiqué para que elimine el guión si la longitud del código postal fuera 6 después de haber eliminado el marcador de posición del valor.
Se veía así:
$.validator.addMethod("zipcode", function(postalcode, element) {
//removes placeholder from string
postalcode = postalcode.split("_").join("");
//Checks the length of the zipcode now that placeholder characters are removed.
if (postalcode.length === 6) {
//Removes hyphen
postalcode = postalcode.replace("-", "");
}
//validates postalcode.
return this.optional(element) || postalcode.match(/^/d{5}$|^/d{5}/-/d{4}$/);
}, "Please specify a valid zip code");
Por lo tanto, el código postal que estoy validando tendrá los marcadores de posición agregados por el complemento de entrada y el guión eliminado si el código postal que se ingresa solo tiene 5 dígitos numéricos (6 incluyendo el guión). Así lo validará correctamente.
Probé algunas de las soluciones, pero ninguna me funcionó, estoy usando ''bootstrapValidator'' ( http://bootstrapvalidator.com/ ) y ''jquery.maskedinput'' ( http://digitalbush.com/projects/masked-input- plugin / ) así que si alguien todavía tiene este problema, mi solución fue:
Mi entrada fue marcada así:
<input type="text" class="form-control" id="telefone" placeholder="(__) ____-_____" name="telefone" required>
Y el guión completo como este:
$(document).ready(function() {
var telefone = $(''#telefone''), //THAT''S MY INPUT WITH MASK
form = telefone.parents("form"), //THAT''S MY FORM WITH THE VALIDATE
alteredField = false; //THAT''S A FLAG TO SSE IF THE INPUT WAS ALTERED
// APPLY MY MASK
telefone.mask(''(99) 9999-9999?9'');
// FOCUS ON ANY INPUT
form.find(''input[type=text]'').focus(function(){
// REMOVE THE VALIDATION STATUS
$(form).data(''bootstrapValidator'').updateStatus($(this).attr(''name''), ''NOT_VALIDATED'');
// ENABLE THE SUBMIT BUTTON
$(form).data(''bootstrapValidator'').disableSubmitButtons(false);
});
// FOCUS ON THE MASKED INPUT
telefone.focus(function(){
// DISABLE THE VALIDATE
$(form).data(''bootstrapValidator'').enableFieldValidators(''telefone'', false);
// ENABLE THE SUBMIT BUTTON
$(form).data(''bootstrapValidator'').disableSubmitButtons(false);
}).blur(function(){ // BLUR ON THE MASKED INPUT
// GET THE INPUT VALUE
var value = telefone.val();
// ENABLE THE VALIDATE
$(form).data(''bootstrapValidator'').enableFieldValidators(''telefone'', true);
// CHECK IF THE VALUE IS EMPTY
if(value != ""){
// CHANGE THE STATUS OF THE INPUT TO VALID
$(form).data(''bootstrapValidator'').updateStatus(''telefone'', ''VALID'')
// ACTIVE THE FLAG
alteredField = true;
}else if (alteredField) { // IF THE INPUT WAS ALTERED BEFORE AND DON''T HAVE VALUE
// CHANGE THE STATUS OF THE INPUT TO INVALID
$(form).data(''bootstrapValidator'').updateStatus(''telefone'', ''INVALID'')
};
});
});
Este código modifica el comportamiento estándar del ''bootstrapValidator'', pero fue la única forma en que tengo que resolver el error.
No sé acerca de los problemas de rendimiento, así que modifique y mejore el código ^^ Espero que esta ayuda ^ _ ^
Simplemente enganche a la función de máscara () y agregue un poco de lógica adicional para disparar su propia lógica de desenfoque después de la lógica de desenfoque de la máscara predeterminada:
//Store the original mask function
var origMaskFn = $.fn.mask;
$.fn.mask = function (mask, settings) {
//Call the original function applying the default settings
origMaskFn.apply(this, [mask, settings]);
//Manually validate our element on blur to prevent unobtrusive messages
//from showing before the mask is properly scrubbed
$(this).bind(''blur'', function () {
var $form = $(this).parents(''form'');
if (!$form.exists())
return;
var validator = $form.validate().element($(this));
});
}
Además, puede notar la función ''existe ()''. Esto es algo que uso mucho con mis selectores jQuery:
//Function to detect if a jQuery elements exists. i.e.:
// var $element = $(selector);
// if($element.exists()) do something...
$.fn.exists = function () {
return this.length !== 0;
}
Traté de seguir la solución, y funciona como un encanto.
$("[data-input-type=phone]", "body")
.mask("(999) 999 99 99")
.bind("blur", function () {
// force revalidate on blur.
var frm = $(this).parents("form");
// if form has a validator
if ($.data( frm[0], ''validator'' )) {
var validator = $(this).parents("form").validate();
validator.settings.onfocusout.apply(validator, [this]);
}
});
Lo que desencadena el problema es el ordenamiento de eventos. Cuando un elemento está enmascarado, se valida mediante el complemento maskedinput on blur
, pero el mismo elemento se valida mediante el complemento validator en el evento focusout
(que es un envoltorio para blur en no navegadores), que se llama antes de bluredinput''s blur.
En esta situación, el elemento de entrada tiene el valor "(___) ___ __ __"
cuando el validador verifica el valor. Cuando el código alcanza el evento de desenfoque de maskedinput, el complemento prueba y borra el valor, ya que no es una entrada válida.
El resultado de la validación puede ser diferente para cada caso de validación. Por ejemplo, required
reglas required
pasarán con éxito ya que el elemento tiene un valor. los campos de number
no requeridos fallarán incluso si dejamos la entrada vacía ya que una máscara como "999"
puede probarse como 12_
el código anterior prueba si la forma de entrada enmascarada tiene una validación adjunta, y recuerda el controlador de eventos de enfoque. Dado que nuestro controlador se adjunta como el último, esperamos que finalmente se llame.
Una advertencia, el código simplemente copia el comportamiento del complemento de validación. Probablemente funcionará durante una década, pero puede fallar si el complemento de validación decide hacer cosas diferentes a las de ahora.
sinceramente
Tuve un problema similar y logré resolverlo cambiando el carácter de marcador de posición predeterminado a una cadena vacía.
Estaba usando una .mask(''9?99'');
y estaba validando con una simple regla de ''número'', y tenía el mismo tipo de conflicto.
Cambié la declaración de máscara a .mask(''9?99'',{placeholder:''''});
y ... no más conflicto. :)
Existe un posible problema en su caso, debido al código en el código postal, que siempre se inserta en el formulario mediante el complemento de máscara. Creo que puede cambiar la expresión regular a ^/d{5}/-$|^/d{5}/-/d{4}$
(coincidiendo con el guión en ambos casos) y debería validarse entonces.
De todos modos, publicaste hace un tiempo y probablemente ya no necesites esto, pero quizás ayude a alguien más. :)