🛡️ Validación de Entrada de Datos

Aprende a validar formularios en Jetpack Compose

🎥 Video Tutorial

Sigue este video para aprender paso a paso la validación de datos:

📚 Repaso del Capítulo Anterior

¿Qué aprendimos antes?
  • Crear vistas TextField para entrada de datos
  • Usar rememberSaveable para mantener el estado durante rotaciones
  • El delegado by permite acceder al valor sin usar .value

🎯 Objetivo de este Capítulo

Aprenderemos a validar la información ingresada por el usuario para evitar que envíe campos vacíos o datos incorrectos.

Usuario escribe
Validamos datos
Mostramos error
Usuario corrige

1️⃣ Paso 1: Crear Variable de Validación

Primero, crearemos una variable observable que guardará el estado de validación:

var isCorrect by rememberSaveable { mutableStateOf(false) }
💡 ¿Qué hace esta variable?

Esta variable almacena true si hay un error (campo vacío) o false si todo está correcto. Inicialmente es false porque el campo empieza limpio.

2️⃣ Paso 2: Validar en onValueChange

Dentro de onValueChange validaremos si el usuario ha escrito algo usando el método isNullOrEmpty():

isNullOrEmpty() devuelve:

  • true → Si el campo está vacío o es nulo (❌ ERROR)
  • false → Si el campo tiene contenido (✅ CORRECTO)
CreateTextField(
    value = value,
    onValueChange = {
        value = it
        // Validamos: ¿está vacío?
        isCorrect = value.isNullOrEmpty()
    },
    isError = isCorrect
)

3️⃣ Paso 3: Actualizar el TextField

Agregamos la propiedad isError al TextField para mostrar el error visualmente:

@Composable
fun CreateTextField(
    value: String,
    onValueChange: (String) -> Unit,
    isError: Boolean
) {
    TextField(
        value = value,
        onValueChange = onValueChange,
        label = { Text("Ingrese su nombre") },
        modifier = Modifier.fillMaxWidth(),
        // Si isError es true, se pinta el borde de rojo
        isError = isError,
        singleLine = true
    )
}
⚠️ Importante:

Cuando isError = true, el TextField muestra un borde rojo indicando que hay un problema con la entrada de datos.

4️⃣ Paso 4: Mostrar Mensaje de Error

Agregamos un texto condicional que se muestra solo cuando hay un error:

if (isCorrect) {
    Text(
        text = "⚠️ Debes ingresar un valor",
        color = Color.Red,
        fontSize = 14.sp,
        modifier = Modifier.padding(start = 16.dp, top = 4.dp)
    )
}
💡 ¿Cuándo se muestra este mensaje?

El mensaje aparece cuando el usuario comienza a escribir y luego borra todo el texto, porque la validación se ejecuta dentro de onValueChange.

5️⃣ Paso 5: Validar al Enviar

También debemos validar cuando el usuario presiona el botón:

CreateButton {
    // Validamos antes de mostrar el mensaje
    isCorrect = value.isNullOrEmpty()
    
    if (!isCorrect) {
        // Si NO hay error, mostramos el saludo
        Toast.makeText(
            context,
            "¡Hola $value! 👋",
            Toast.LENGTH_SHORT
        ).show()
    }
}
✅ Flujo completo:
  1. El usuario presiona el botón
  2. Validamos si el campo está vacío
  3. Si está vacío: mostramos el error (borde rojo + mensaje)
  4. Si tiene contenido: mostramos el saludo con Toast

📋 Código Completo

@Composable
fun Formulario(paddingValues: PaddingValues) {
    var value by rememberSaveable { mutableStateOf("") }
    var isCorrect by rememberSaveable { mutableStateOf(false) }
    val context = LocalContext.current

    Column(
        modifier = Modifier
            .padding(paddingValues)
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        // Campo de texto con validación
        CreateTextField(
            value = value,
            onValueChange = {
                value = it
                isCorrect = value.isNullOrEmpty()
            },
            isError = isCorrect
        )

        // Mensaje de error
        if (isCorrect) {
            Text(
                "⚠️ Debes ingresar un valor",
                color = Color.Red
            )
        }

        Spacer(modifier = Modifier.height(16.dp))

        // Botón con validación
        CreateButton {
            isCorrect = value.isNullOrEmpty()
            if (!isCorrect) {
                Toast.makeText(
                    context,
                    "¡Hola $value!",
                    Toast.LENGTH_SHORT
                ).show()
            }
        }
    }
}

💪 Ejercicios Prácticos

Pon en práctica lo aprendido con estos ejercicios:

Ejercicio 1

Convertir a Mayúsculas

Pide al usuario que ingrese una cadena de texto y conviértela a mayúsculas usando toUpperCase(). Muestra el resultado en un Toast.

Ejercicio 2

Contador de Caracteres

Pide al usuario que ingrese una cadena de texto y muestra cuántos caracteres tiene usando .length. Ejemplo: "Tu texto tiene 15 caracteres"

Ejercicio 3

Reemplazar Espacios

Pide al usuario que ingrese una cadena de texto y reemplaza todos los espacios por guiones usando replace(" ", "-"). Ejemplo: "Hola Mundo" → "Hola-Mundo"