FormGenerator
by der_robert
HTML
<script id="form-config" type="application/json">
{
"action": "/submit-form",
"method": "POST",
"fields": [
{
"id": "personal-info",
"type": "input-group",
"fields": [
{
"id": "full_name",
"type": "text",
"label": "Name",
"placeholder": "Max Mustermann",
"required": true,
"validation": "string",
"layout": "horizontal"
},
{
"id": "user_email",
"type": "email",
"label": "E-Mail",
"placeholder": "[email protected]",
"required": true,
"validation": "email",
"layout": "horizontal"
}
]
},
{
"id": "address_group_1",
"type": "input-group",
"fields": [
{
"id": "street",
"type": "text",
"label": "Straße",
"placeholder": "Musterstraße",
"required": true,
"layout": "vertical"
},
{
"id": "houseNumber",
"type": "text",
"label": "Nr.",
"placeholder": "12a",
"required": true,
"layout": "vertical"
}
]
},
{
"id": "address_group_2",
"type": "input-group",
"fields": [
{
"id": "zip",
"type": "text",
"label": "PLZ",
"placeholder": "12345",
"required": true,
"layout": "vertical"
},
{
"id": "city_name",
"type": "text",
"label": "Stadt",
"placeholder": "Berlin",
"required": true,
"layout": "vertical"
}
]
},
{
"id": "user_age",
"type": "number",
"label": "Alter",
"required": true,
"validation": "int",
"min": 18,
"max": 99,
"layout": "horizontal"
},
{
"id": "salary",
"type": "text",
"label": "Monatsgehalt (€)",
"placeholder": "z.B....
CSS
/* Grundlegende Formulargestaltung */
form {
max-width: 600px;
margin: 20px auto;
padding: 20px;
border-radius: 8px;
background: #f9f9f9;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
}
/* Gemeinsame Struktur für Form-Felder */
.form-group {
display: flex;
align-items: center;
gap: 15px;
margin-bottom: 15px;
}
/* Labels mit fester Breite für Einheitlichkeit */
.form-group label {
font-weight: bold;
text-align: right;
flex-basis: 30%; /* Setzt eine Basisbreite für alle Labels */
min-width: 120px; /* Mindestens 120px, falls kürzere Labels */
white-space: nowrap; /* Verhindert Umbrüche */
}
/* Eingabefelder */
.form-group input,
.form-group select,
.form-group textarea {
flex-grow: 1;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
}
.form-group textarea {
height: 100px;
resize: vertical;
}
/* Fehlerhafte Eingabefelder */
input.error, select.error, textarea.error {
border-color: red;
background-color: #ffecec;
}
/* Platzhalter-Bereich für AJAX */
.placeholder {
border: 1px dashed #999;
padding: 10px;
min-height: 50px;
background: #f5f5f5;
text-align: center;
font-size: 14px;
color: #666;
}
/* Buttons */
button, .button-link {
background-color: #007bff;
color: white;
padding: 10px 15px;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
transition: background 0.3s;
text-decoration: none;
display: inline-block;
}
button:hover, .button-link:hover {
background-color: #0056b3;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
/* 🔥 Vertikale Layout-Variante */
.vertical {
flex-direction: column;
align-items: flex-start;
}
.vertical label {
text-align: left;
flex-basis: auto;
min-width: 100%;
margin-bottom: 5px;
}
/* Input Group (mehrere Felder in einer Gruppe) */
.input-group {
display: flex;
flex-direction: column;
gap: 10px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 6px;
...
JavaScript
document.addEventListener("DOMContentLoaded", () => {
const formElement = document.querySelector("dynamic-form");
const jsonConfig = document.getElementById("form-config").textContent;
formElement.setAttribute("data-json", jsonConfig);
class DynamicForm extends HTMLElement {
constructor() {
super();
this.formData = [];
}
connectedCallback() {
try {
const jsonString = this.getAttribute("data-json");
if (jsonString) {
this.formData = JSON.parse(jsonString);
if (!this.formData.fields || !Array.isArray(this.formData.fields)) {
throw new Error("Das JSON enthält kein gültiges 'fields'-Array.");
}
this.renderForm();
} else {
console.warn("Kein JSON gefunden! Stelle sicher, dass 'data-json' gesetzt ist.");
}
} catch (error) {
console.error("Fehler beim Parsen des JSON:", error);
}
}
renderForm() {
try {
this.innerHTML = "";
const form = document.createElement("form");
form.id = "dynamic-form";
form.action = this.formData.action || "#";
form.method = this.formData.method || "POST";
console.log("Starte Rendering des Formulars...");
this.formData.fields.forEach((field, index) => {
try {
if (!field.id || !field.type) {
throw new Error(`Fehlende 'id' oder 'type' in Feld ${index + 1}: ${JSON.stringify(field)}`);
}
console.log(`Rendere Feld ${index + 1}:`, field.id);
// Jedes Element direkt an der entsprechenden Position einfügen
const fieldElement = this.renderField(field);
if (fieldElement) {
form.appendChild(fieldElement);
} else {
console.warn(`Feld '${field.id}' konnte nicht gerendert werden.`);
}
} catch (fieldError) {
console.error("Fehler beim Rendern eines Formularfeldes:", fieldError);
}
});
// Falls ein Submit-Button in der config existiert, hinzufügen
const submitButtonConfig =...