JSFiddle - React, Tailwind, and code Playground
by jo0nax232
HTML
<div class="contenedor">
<h3>Formulario dinámico</h3>
<form action="" id="formulario">
<div class="row-form">
<input type="text" name="textNombre" id="textNombre" data-label="Nombre" data-guardar="true" data-tipo="text">
</div>
<div class="row-form">
<input type="text" name="textApellido" id="textApellido" data-label="Apellidos" data-guardar="true" data-tipo="text">
</div>
<div class="row-form">
<select name="cboCiudad" id="cboCiudad" data-label="Ciudad" data-guardar="true" data-tipo="select">
<option value="0">Selecione una opción</option>
<option value="1">Xalapa</option>
<option value="2">Veracruz</option>
<option value="3">Orizaba</option>
</select>
</div>
<div class="row-form">
<div class="input-radio">
<div>
<span class="label">Sexo</span>
</div>
<div class="radios">
<div>
<input type="radio" name="sexo" id="radioMasculino" data-label="Sexo" data-guardar="true" value="Masculino" data-tipo="radio">
</div>
<div>
<input type="radio" name="sexo" id="radioFemenino" data-label="Sexo" data-guardar="true" value="Femenino" data-tipo="radio">
</div>
</div>
</div>
</div>
<div class="row-form">
<button id="btnEnviar" type="submit">Enviar</button>
</div>
</form>
</div>
CSS
:root{
--border-radius: 5px;
}
*,
*::after,
*::before{
margin: 0;
padding: 0;
box-sizing: border-box;
outline: none;
}
body{
font-size: 14px;
font-family: Arial, Helvetica, sans-serif;
color: #5c5c5c;
}
h3{
font-weight: normal;
font-size: 2em;
margin-bottom: 0.5em;
}
label{
font-weight: normal;
}
.contenedor{
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
height: 100%;
padding-top: 2em;
font-size: 1.3em;
width: 70%;
max-width: 600px;
margin: 0 auto;
}
.contenedor form{
width: 100%;
display: flex;
flex-direction: column;
}
input[type="text"],
select{
padding: 1em;
background-color: transparent;
border: 1px solid #c9c9c9;
width: 100%;
border-radius: var(--border-radius);
}
.row-form{
padding: 1em;
}
.label,
label{
display: block;
margin-bottom: 0.5em;
}
.radios{
display: flex;
gap: 1em;
text-align: center;
}
button{
display: block;
padding: 1em;
width: 100%;
background-color: #337ab7;
border: 1px solid #2e6da4;
color: #fff;
border-radius: var(--border-radius);
font-size: 0.90em;
transition: all ease 0.2s;
text-transform: uppercase;
letter-spacing: 5px;
}
button:hover{
background-color: #2c6698;
cursor: pointer;
}
JavaScript
const d = document;
const elementos = d.querySelectorAll('[data-guardar]');
const formulario = d.querySelector('#formulario');
formulario.onsubmit = () =>{
return validarFormulario();
}
crearLabel();
function crearLabel() {
elementos.forEach(elemento => {
let data = elemento.dataset;
let label = d.createElement('label');
let padre = elemento.parentElement;
label.htmlFor = elemento.id;
label.innerHTML = elemento.type == 'radio' ? elemento.value : data.label;
padre.prepend(label);
});
}
function validarFormulario() {
let valido = true;
elementos.forEach(elemento => {
if (valido) {
let data = elemento.dataset;
if (data.guardar) {
let valor = elemento.value;
switch (data.tipo) {
case 'select':
if (valor == '0') {
valido = false;
elemento.focus();
}
break;
case 'radio':
let inputRadio = d.querySelectorAll('[type="radio"]');
let checked = false;
inputRadio.forEach(radio => {
if (radio.checked) {
checked = true;
}
});
if (!checked) {
valido = false;
}
break;
default:
if (!valor) {
valido = false;
}
break;
}
if (!valido) {
alert(`El campo ${data.label} no puede ir vacío`);
elemento.focus();
}
}
}
});
return valido;
}