javascript - tipos - ¿Hay un complemento de entrada enmascarado para knockout.js que usa extensores?
ejemplos de complementos del verbo (5)
He visto este post - muestra una posible solución. Pero me gustaría tener una forma más elegante de hacer entradas enmascaradas.
También debería jugar bien con el complemento de validación de nocaut (o tal vez extenderlo).
Alguien sabe cómo hay un proyecto similar por ahí?
Bien hecho, riceboyler. Tomé su código y lo extendí un poco para usar la propiedad "placeholder" del complemento de entrada enmascarado:
ko.bindingHandlers.masked = {
init: function (element, valueAccessor, allBindingsAccessor) {
var mask = allBindingsAccessor().mask || {};
var placeholder = allBindingsAccessor().placeholder;
if (placeholder) {
$(element).mask(mask, { placeholder: placeholder });
} else {
$(element).mask(mask);
}
ko.utils.registerEventHandler(element, "blur", function () {
var observable = valueAccessor();
observable($(element).val());
});
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).val(value);
}
};
HTML con marcador de posición:
<input id="DOB" type="text" size="12" maxlength="8" data-bind="masked: BirthDate, mask: ''99/99/9999'', placeholder: ''mm/dd/yyyy'', valueUpdate: ''input''"/>
HTML sin marcador de posición:
<input id="DOB" type="text" size="12" maxlength="8" data-bind="masked: BirthDate, mask: ''99/99/9999'', valueUpdate: ''input''"/>
El enlace KO funciona de cualquier manera.
Intenté usar la primera respuesta, pero no funcionó con el complemento ko.validation. No se mostraban mis errores de validación.
Quería tener un poco más intuitiva la carpeta ko. Aquí está mi solución. Estoy usando el complemento jquery.inputmask. También borro la propiedad en mi modelo de vista si no se ingresa el valor.
ko.bindingHandlers.mask = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var mask = valueAccessor() || {};
$(element).inputmask({ "mask": mask, ''autoUnmask'': false });
ko.utils.registerEventHandler(element, ''focusout'', function () {
var value = $(element).inputmask(''unmaskedvalue'');
if (!value) {
viewModel[$(element).attr("id")]("");
}
});
}
};
Aquí está el uso:
<input type="text" data-bind="value: FEIN, mask: ''99-9999999''" id="FEIN" >
Puedes usar esta solución casera, funciona perfectamente para mí:
Mi llamada eliminatoria vinculante enmascarada inspirada en la red, agregué un poco de lenguaje administrado y actualizaciones de diferentes eventos. También uso esta biblioteca js para usar básicamente: https://plugins.jquery.com/maskedinput/
Puede ver en mi enlace el término "allBindingsAccessor (). Mask" esto es de la biblioteca maskedinput
ko.bindingHandlers.masked = {
init: function (element, valueAccessor, allBindingsAccessor) {
var mask = allBindingsAccessor().mask || {},
getCaretPosition,
setCaretPosition;
// Permet d''obtenir la position du curseur
getCaretPosition = function getCaretPosition(element) {
// Initialise la position
var caretPos = 0, sel;
// IE
if (document.selection) {
// Donne le focus à l''élément
element.focus();
// Afin d''obtenir la position du curseur
sel = document.selection.createRange();
// On place le curseur à 0
sel.moveStart(''character'', -element.value.length);
caretPos = sel.text.length;
}
// Firefox
else if (element.selectionStart || element.selectionStart === ''0'') {
caretPos = element.selectionStart;
}
return (caretPos);
};
// Permet de définir la position du curseur en fonction d''une position donnée
setCaretPosition = function setCaretPosition(element, pos) {
var range;
if (element.setSelectionRange) {
element.focus();
element.setSelectionRange(pos, pos);
}
else if (element.createTextRange) {
range = element.createTextRange();
range.collapse(true);
range.moveEnd(''character'', pos);
range.moveStart(''character'', pos);
range.select();
}
};
// Définition du masque inséré dans le champ
if (configSvc.culture === "fr-FR") {
// Cas francais
$(element).mask("99/99/9999", { placeholder: "JJ/MM/AAAA" });
}
else {
// Cas anglophone
$(element).mask("99/99/9999", { placeholder: "MM/DD/YYYY" });
}
// On capte l''événement d''appuie sur une touche
ko.utils.registerEventHandler(element, ''keypress'', function () {
var observable = valueAccessor(),
position;
// Afin de résoudre le pb de déplacement du curseur a la fin du mask lors de la mise à jour de l''observable knockout
if ($(element).val().length === 10) {
// On récupère la dernière position
position = getCaretPosition(this);
// On met à jour la valeur de l''obersable (en cas de sauvegarde)
observable($(element).val());
// On force la position du curseur apres mise à jour de l''observable à la derniere position récupéré
setCaretPosition(this, position);
}
});
// On capte l''événement de perte de focus pour mettre l''obersable à jour
ko.utils.registerEventHandler(element, ''blur'', function () {
var observable = valueAccessor();
observable($(element).val());
});
// On capte l''événement change pour mettre l''obersable à jour
ko.utils.registerEventHandler(element, ''change'', function () {
var observable = valueAccessor();
observable($(element).val());
});
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).val(value);
}
};
en mi página html, uso este observable "enmascarado":
<input type="text" id="head-birthDate" class="form-control" data-bind="masked: birthDate" />
Finalmente en mi js:
fecha de nacimiento es sólo un observable
this.birthDate = ko.observable();
Si desea utilizar el excelente complemento de entrada enmascarado en Knockout, es bastante fácil escribir un enlace personalizado básico en lugar de un extensor.
ko.bindingHandlers.masked = {
init: function(element, valueAccessor, allBindingsAccessor) {
var mask = allBindingsAccessor().mask || {};
$(element).mask(mask);
ko.utils.registerEventHandler(element, ''focusout'', function() {
var observable = valueAccessor();
observable($(element).val());
});
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).val(value);
}
};
Y luego en tu HTML:
<input type="text" data-bind="masked: dateValue, mask: ''99/99/9999''" />
<input type="text" data-bind="masked: ssnValue, mask: ''999-99-9999''" />
Y así sucesivamente con varias máscaras. De esta manera, solo puede colocar la máscara en su enlace de datos, y le permite una tonelada de flexibilidad.
Simplemente tome el código de la respuesta en ese enlace y póngalo en un extensor (Escrito en manos libres, puede tener errores)
ko.extenders.masked = function(observable, options) {
return ko.computed({
read: function() {
return ''$'' + this.observable().toFixed(2);
},
write: function(value) {
// Strip out unwanted characters, parse as float, then write the raw data back to the underlying observable
value = parseFloat(value.replace( /[^/./d]/g , ""));
observable(isNaN(value) ? 0 : value); // Write to underlying storage
}
});
};
edición: probablemente desee proporcionar la máscara como una opción en lugar de tenerla codificada en USD, etc.
actualización: si desea utilizar el complemento de máscara de la respuesta de riceboyler pero con extensores puede hacerlo
ko.extenders.mask = function(observable, mask) {
observable.mask = mask;
return observable;
}
var orgValueInit = ko.bindingHandlers.value.init;
ko.bindingHandlers.value.init = function(element, valueAccessor) {
var mask = valueAccessor().mask;
if(mask) {
$(element).mask(mask);
}
orgValueInit.apply(this, arguments);
}