Como ejecutar un evento al terminar de escribir en un campo en Genexus
Algunas veces al desarrollar una aplicación, nos encontramos con la necesidad de realizar un cálculo cuando se modifica algún campo. Para esto en Genexus existen dos tipos de eventos que nos ayudan a ejecutar un codigo despues de que se modificó un campo, ControlValueChanged y ControlValueChanging.
Pero este artículo no es sobre como utilizar estos eventos, si no más bien de como crear un nuevo evento que nos ayude a realizar una función que los otros dos eventos no pueden realizar.
Para que se comprenda lo que se quiere lograr, vamos a explicar como funcionan a grandes rasgos los otros dos eventos:
ControlValueChanged. Este evento se ejecuta cuando se detecta un cambio sobre un campo. Para los campos de texto, es necesario salir del campo para que este evento se ejecute.
ControlValueChanging. Este evento se ejecuta cuando se detecta un cambio sobre un campo. Para los campos de texto, se ejecuta cada vez que se presiona una tecla sobre el campo, por ejemplo al escribir "Hola" el evento se ejecutaría 4 veces.
Bien, ahora veamos un ejemplo práctico. Vamos a crear un aplicación en la que se ingrese la estatura y el peso, y nos muestre el IMC. Esta calculadora no tendrá un botón para calcular, así que utilizaremos el evento ControlValueChanging, para que al modificar el peso nos realice el calculo:
Como ven es algo muy sencillo, quizás se pregunten por que muestro de nuevo la estatura y el peso que se ingreso si ya se puede ver en los campos de arriba, bueno esto es algo que nos ayudara a notar el problema que tiene el evento ControlValueChanging.
Vamos a hacer una prueba, ingreso unos datos y nos muestra un resultado correcto:
Funciona bien, pero qué pasa si tenemos la necesidad de que en el evento se recupere información de la base de datos para realizar los cálculos?, pues cada vez que escribamos sobre el campo se va a realizar un llamado a la base de datos. Para simular esto voy a poner un sleep, que simule el tiempo que le tomaría al evento terminar de ejecutarse:
Al ingresar los mismos datos de prueba, vemos que el resultado es diferente:
Si nos fijamos en el dato de Peso que esta arriba de IMC, podemos ver que esta tomando el valor de 10, pero nosotros ingresamos 100, por que el evento no tomo la cantidad correcta?, Esto es por que cada cifra que se escribe ejecuta el evento y debido que el evento le esta tomando mas tiempo ejecutarse no esta respondiendo a los últimos números ingresados.
Como podemos solucionar esto? podríamos utilizar el evento ControlValueChanged, que solo se ejecuta una vez, pero el problema que solo se ejecutara hasta que salgas del campo, lo cual podría ser confuso para el usuario.
Nuevo Evento
Así que veamos que necesitamos, un campo que ejecute un evento pero solo una vez, cuando terminemos de escribir y sin que sea necesario salir del campo. Bien, eso es lo que va a hacer nuestro nuevo evento.
Para hacerlo vamos a utilizar un poco de código Javascript. Primero crearemos un external object llamado Calcular, y en su propiedad "Javascript External Name" pondremos Calcular
Agregamos un evento llamado IMC en la sección Events, y en su propiedad "Javascript External Name" podremos Calcular.IMC
Esto es lo único que tenemos que hacer en el external object, ahora volvemos a nuestro webpanel y primero vamos a agregar un TextBlock en nuestro form, y modificamos su propiedad Format a HTML. Cambiaremos el nombre del textblock a Script.
En el código vamos a agregar el evento Start, y vamos a crear una variable Script (LongVarchar), en la que escribiremos el siguiente código:
Básicamente lo que hace ese código es asignarle un evento al campo Peso, que se ejecuta cada vez que se presiona una tecla sobre el campo, el evento crea un temporizador de 1 segundo y al terminar ejecuta el evento de genexus llamado Calcular.IMC, Si se sigue escribiendo antes de que el temporizador termine resetea el temporizador y vuelve a iniciar, de esta manera nos aseguramos de que el evento solo se ejecute 1 segundo después de que se terminó de escribir.
Ahora lo que haremos es copiar el código que teníamos en el evento &Peso.ControlValueChanging, y lo pasaremos al evento Calcular.IMC. Algo importante es no borrar y mantener el evento &Peso.ControlValueChanging. El codigo quedaria asi:
Volvemos a ingresar los datos para hacer una prueba, y como se puede observar el resultado es correcto, ahora el evento solo se ejecuta al terminar de escribir y solo una vez.