This commit is contained in:
399
frontend/src/lib/components/pagebuilder/form/Formular.svelte
Normal file
399
frontend/src/lib/components/pagebuilder/form/Formular.svelte
Normal file
@@ -0,0 +1,399 @@
|
||||
<script lang="ts">
|
||||
import Form from "./form.svelte"
|
||||
import MobileForm from "./mobileForm.svelte"
|
||||
import { writable } from "svelte/store"
|
||||
import { validateFields } from "../../../functions/validateFields"
|
||||
import { sendForm } from "../../../functions/sendForm"
|
||||
import { navigate } from "svelte-routing"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
export let col: Column
|
||||
export let siteId: string
|
||||
export let rowNr: number
|
||||
export let row: Row
|
||||
export let rows: Row[]
|
||||
|
||||
let formSend = false
|
||||
let formValues = writable<FormValues>({})
|
||||
|
||||
function submitForm() {
|
||||
const values: Array<ValueEntry> = Object.entries($formValues).map((entry: ObjectEntry) => {
|
||||
const key: string = entry[0]
|
||||
const value: CustomHTMLElement = entry[1]
|
||||
if (!key.includes("numberLabel")) {
|
||||
return [key, [value.checked || value.value, value.required]] as ValueEntry
|
||||
} else {
|
||||
return [key, [value.value, value, value.getAttribute("name"), value.required]] as ValueEntry
|
||||
}
|
||||
})
|
||||
|
||||
const fields: Array<ValueEntry> = values.filter((entry: ValueEntry) => !entry[0].includes("label"))
|
||||
const validation = validateFields(fields)
|
||||
if (validation.length) {
|
||||
validation.forEach((error) => {
|
||||
// @ts-ignore
|
||||
if (error[0].includes("block")) {
|
||||
// @ts-ignore
|
||||
error[1]()
|
||||
} else {
|
||||
// @ts-ignore
|
||||
$formValues[error[1]].classList.add("invalid")
|
||||
const label = $formValues[`${error[1]}_label`]
|
||||
const errorElement = document.createElement("div")
|
||||
errorElement.className = "error-message"
|
||||
errorElement.textContent = error[0] as string
|
||||
label?.appendChild(errorElement)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// @ts-ignore
|
||||
const formObj: FormObj = {}
|
||||
fields.forEach((entry) => {
|
||||
if (Array.isArray(entry[1]) && entry[1].length == 4) {
|
||||
// @ts-ignore
|
||||
if (entry[1][0]) formObj[entry[0]] = entry[1]
|
||||
} else {
|
||||
if (!entry[1][0] && !entry[1][1]) return
|
||||
// @ts-ignore
|
||||
formObj[entry[0]] = entry[1][0]
|
||||
}
|
||||
})
|
||||
let form: any
|
||||
row.column.forEach((col) => {
|
||||
if (col.contentType == "form") form = col
|
||||
})
|
||||
if (!form) return
|
||||
formObj["formRows"] = form.formRows.map((r: FormRow) => r.rowName)
|
||||
formObj["formTitle"] = form.formEmailTitle
|
||||
formSend = true
|
||||
const hny = document.getElementById("hny") as HTMLInputElement
|
||||
if (hny) formObj["honey"] = hny.checked
|
||||
sendForm(formObj)
|
||||
}
|
||||
}
|
||||
let innerWidth = window.innerWidth
|
||||
|
||||
onMount(() => {
|
||||
const handleResize = () => {
|
||||
innerWidth = window.innerWidth
|
||||
}
|
||||
|
||||
window.addEventListener("resize", handleResize)
|
||||
|
||||
// Cleanup function
|
||||
return () => {
|
||||
window.removeEventListener("resize", handleResize)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if formSend}
|
||||
<div class="success-message">
|
||||
<h1>Formular erfolgreich gesendet!</h1>
|
||||
<p>Vielen Dank für Ihre Anfrage. Wir werden uns in Kürze bei Ihnen melden.</p>
|
||||
</div>
|
||||
{:else}
|
||||
<form
|
||||
class="form-rows"
|
||||
on:submit="{(e) => {
|
||||
e.preventDefault()
|
||||
submitForm()
|
||||
}}"
|
||||
>
|
||||
{#each col.formRows ?? [] as formRow, i}
|
||||
{#if innerWidth < 768}
|
||||
<MobileForm formRow="{formRow}" formValues="{formValues}" index="{i}" />
|
||||
{:else}
|
||||
<Form formRow="{formRow}" formValues="{formValues}" index="{i}" />
|
||||
{/if}
|
||||
{/each}
|
||||
<div class="row additional">
|
||||
<div class="data-protection">
|
||||
<label bind:this="{$formValues[`agreement_label`]}">
|
||||
<input
|
||||
required="{true}"
|
||||
class="checkit"
|
||||
type="checkbox"
|
||||
on:change="{(e) => {
|
||||
let element = e.currentTarget
|
||||
element.classList.remove('invalid')
|
||||
}}"
|
||||
bind:this="{$formValues['agreement']}"
|
||||
/>
|
||||
<span class="checkit-span"></span>
|
||||
</label>
|
||||
|
||||
<div class="datasec">
|
||||
<button on:click|preventDefault="{() => navigate('/datenschutz')}" class="link">
|
||||
Datenschutz
|
||||
</button>
|
||||
akzeptieren
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="checkbox"
|
||||
name="contact_me_by_fax_only"
|
||||
id="hny"
|
||||
value="1"
|
||||
style="display:none !important"
|
||||
tabindex="-1"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<button class="submit-request" type="submit">Anfrage absenden</button>
|
||||
</div>
|
||||
</form>
|
||||
{/if}
|
||||
|
||||
<style lang="less" global>
|
||||
@import "../../../assets/css/variables.less";
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
.data-protection {
|
||||
margin: 5px 0px;
|
||||
box-shadow: 0 0 25px 10px var(--opposite-bg-color-5);
|
||||
}
|
||||
|
||||
.success-message {
|
||||
h1 {
|
||||
color: var(--heading-font-color);
|
||||
font-size: 36px;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
.invalidBlocks {
|
||||
border: 2px solid rgb(255, 0, 0) !important;
|
||||
position: relative;
|
||||
&::after {
|
||||
font-size: 0.9rem !important;
|
||||
color: red !important;
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
content: "Bitte wähle entweder eine Kartenanzahl oder einen Wunschbetrag aus.";
|
||||
}
|
||||
}
|
||||
|
||||
.border-red {
|
||||
border-color: red !important;
|
||||
}
|
||||
|
||||
.no-margin {
|
||||
margin-top: 15px !important;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
border: 2px solid red !important;
|
||||
}
|
||||
.error-message {
|
||||
font-size: 0.9rem !important;
|
||||
color: red !important;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
|
||||
.checkit {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.checkit-span {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
border: 1px solid grey;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[type="checkbox"]:checked + span:before {
|
||||
content: "\2714";
|
||||
position: absolute;
|
||||
transform-origin: bottom;
|
||||
}
|
||||
|
||||
.form-rows {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
width: 100%;
|
||||
h3 {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 1.5rem;
|
||||
|
||||
.date {
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
label {
|
||||
width: 100% !important;
|
||||
font-size: inherit;
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
width: 100%;
|
||||
font-size: inherit;
|
||||
}
|
||||
}
|
||||
.form-cols {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.form-column {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
width: 100%;
|
||||
gap: 1rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--hover-color);
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
.data-protection {
|
||||
padding: 10px 20px;
|
||||
border: 0px solid var(--opposite-bg-color);
|
||||
border-bottom: 3px solid var(--heading-font-color);
|
||||
outline: 0px solid var(--opposite-bg-color);
|
||||
color: var(--opposite-bg-color);
|
||||
background-color: var(--background-color);
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.data-protection {
|
||||
display: flex;
|
||||
|
||||
flex-wrap: nowrap;
|
||||
gap: 5px !important;
|
||||
justify-content: start;
|
||||
flex-direction: row !important;
|
||||
}
|
||||
|
||||
input[type="date"] {
|
||||
font-family: inherit;
|
||||
width: 100% !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
select {
|
||||
padding: 10px 20px;
|
||||
border: 0;
|
||||
border-bottom: 3px solid var(--heading-font-color);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
select:focus {
|
||||
border-bottom-color: var(--heading-font-color);
|
||||
}
|
||||
|
||||
#time-select {
|
||||
appearance: none;
|
||||
background-image: url("../../../../../media/clock.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 20px center;
|
||||
background-size: 18px;
|
||||
|
||||
option {
|
||||
padding: 10px 20px;
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
}
|
||||
@media @mobile {
|
||||
.date {
|
||||
width: 100vw !important;
|
||||
}
|
||||
}
|
||||
@media @tablet {
|
||||
.date {
|
||||
width: 100% !important;
|
||||
}
|
||||
.form-cols {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
}
|
||||
i .max-width {
|
||||
max-width: @body-maxwidth !important;
|
||||
}
|
||||
|
||||
.datasec {
|
||||
display: flex;
|
||||
align-items: center !important;
|
||||
.link {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: flex-end !important;
|
||||
text-decoration: underline;
|
||||
margin-right: 3px;
|
||||
color: rgb(14, 91, 146);
|
||||
}
|
||||
}
|
||||
|
||||
.additional {
|
||||
display: flex;
|
||||
@media @mobile {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
@media @tablet {
|
||||
flex-direction: row !important;
|
||||
}
|
||||
gap: 2.5rem;
|
||||
div {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
}
|
||||
.submit-request {
|
||||
flex: 1;
|
||||
box-shadow: 0 0 25px 10px var(--opposite-bg-color-5);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
background-color: var(--heading-font-color);
|
||||
color: var(--background-color);
|
||||
padding: 10px 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
18
frontend/src/lib/components/pagebuilder/form/checkbox.svelte
Normal file
18
frontend/src/lib/components/pagebuilder/form/checkbox.svelte
Normal file
@@ -0,0 +1,18 @@
|
||||
<script lang="ts">
|
||||
import type { Writable } from "svelte/store"
|
||||
|
||||
export let label = "" // Der Text, der neben der Checkbox angezeigt wird
|
||||
export let bindValue: any // Der Wert der Checkbox
|
||||
export let formValues: Writable<FormValues> // Das formValues-Objekt aus dem übergeordneten Komponenten
|
||||
export let id = "" // Eindeutige ID für die Checkbox, um den Label korrekt zuzuweisen
|
||||
export let name = "" // Name des Formularelements
|
||||
</script>
|
||||
|
||||
<label class="checkbox-container" for="{id}">
|
||||
<input type="checkbox" bind:checked="{bindValue}" id="{id}" name="{name}" bind:this="{formValues[name]}" />
|
||||
<span>{label}</span>
|
||||
</label>
|
||||
|
||||
<style>
|
||||
/* Sie können hier den Stil für Ihre Checkbox anpassen */
|
||||
</style>
|
||||
@@ -0,0 +1,48 @@
|
||||
<script lang="ts">
|
||||
import type { Writable } from "svelte/store"
|
||||
export let groupTitle: string
|
||||
export let checkboxes: { name: string; emailName: string }[]
|
||||
export let formValues: Writable<FormValues>
|
||||
export let rowNr: number
|
||||
</script>
|
||||
|
||||
<div class="checkbox-group">
|
||||
<h3>{groupTitle}</h3>
|
||||
<div class="containerr">
|
||||
{#each checkboxes as checkbox, i}
|
||||
<label class="checkbox-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox-input checkit"
|
||||
bind:this="{$formValues[`checkbox_${groupTitle}_${rowNr}_${checkbox.emailName}`]}"
|
||||
/>
|
||||
<span class="checkit-span"></span>
|
||||
{checkbox.name}
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="less">
|
||||
.checkbox-group {
|
||||
.checkbox-input {
|
||||
vertical-align: middle;
|
||||
margin-right: 8px;
|
||||
width: fit-content !important;
|
||||
}
|
||||
|
||||
.checkbox-label {
|
||||
width: 100%;
|
||||
vertical-align: middle;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
& > .containerr {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
131
frontend/src/lib/components/pagebuilder/form/datepicker.svelte
Normal file
131
frontend/src/lib/components/pagebuilder/form/datepicker.svelte
Normal file
@@ -0,0 +1,131 @@
|
||||
<script lang="ts">
|
||||
import { CalendarView } from "fluent-svelte"
|
||||
|
||||
export let groupTitle: string
|
||||
export let datePickerProps: DatePickerProps
|
||||
export let formValues: any
|
||||
export let rowNr: number
|
||||
export let formCol: FormColumn
|
||||
|
||||
const today = new Date()
|
||||
const oneYearFromNow = new Date(today)
|
||||
oneYearFromNow.setFullYear(today.getFullYear() + 1)
|
||||
const indexToDay: Record<number, string> = {
|
||||
0: "sunday",
|
||||
1: "monday",
|
||||
2: "tuesday",
|
||||
3: "wednesday",
|
||||
4: "thursday",
|
||||
5: "friday",
|
||||
6: "saturday",
|
||||
}
|
||||
|
||||
function generateBlackoutDates(props: DatePickerProps): Date[] {
|
||||
let blackoutDates = []
|
||||
|
||||
// Funktion, um einen ISO-String in ein vereinfachtes Date-Objekt umzuwandeln
|
||||
const dateFromISOString = (isoString: string) => {
|
||||
const date = new Date(isoString)
|
||||
return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()))
|
||||
}
|
||||
|
||||
const dayToIndex: Record<string, number> = {
|
||||
sunday: 0,
|
||||
monday: 1,
|
||||
tuesday: 2,
|
||||
wednesday: 3,
|
||||
thursday: 4,
|
||||
friday: 5,
|
||||
saturday: 6,
|
||||
}
|
||||
|
||||
// Initialisiere ein aktuelles Datum auf heute
|
||||
let currentDate = new Date(Date.UTC(today.getFullYear(), today.getMonth(), today.getDate()))
|
||||
|
||||
// Schleife durch die nächsten 365 Tage
|
||||
for (let i = 0; i <= 365; i++) {
|
||||
// Überprüfen, ob dieses Datum erlaubt ist
|
||||
const isAllowed = props.allowedDateRanges.some((range) => {
|
||||
const fromDate = dateFromISOString(range.from)
|
||||
const toDate = dateFromISOString(range.to)
|
||||
|
||||
return currentDate >= fromDate && currentDate <= toDate
|
||||
})
|
||||
|
||||
// Überprüfen, ob der Wochentag ausgeschlossen ist
|
||||
const currentDayIndex = currentDate.getUTCDay()
|
||||
const currentDayString = indexToDay[currentDayIndex]
|
||||
const isExcluded = props.excludeDays?.includes(currentDayString)
|
||||
|
||||
// Wenn nicht erlaubt oder ausgeschlossen, zu den Blackout-Daten hinzufügen
|
||||
if (!isAllowed || isExcluded) {
|
||||
blackoutDates.push(new Date(currentDate))
|
||||
}
|
||||
|
||||
// Zum nächsten Tag wechseln
|
||||
currentDate.setUTCDate(currentDate.getUTCDate() + 1)
|
||||
}
|
||||
|
||||
return blackoutDates
|
||||
}
|
||||
|
||||
let value = new Date()
|
||||
const blackoutDates = generateBlackoutDates(datePickerProps)
|
||||
|
||||
function setFormValues() {
|
||||
$formValues[`datepicker_${groupTitle}_${rowNr}_${formCol.datePickerEmailTitle}`] = {
|
||||
value: value.toLocaleDateString("de-DE"),
|
||||
required: !formCol.datePickerNotRequired,
|
||||
}
|
||||
}
|
||||
//needs email conntection
|
||||
$: {
|
||||
if (value) {
|
||||
setFormValues()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div class="container">
|
||||
<div
|
||||
class="datepicker"
|
||||
on:click|preventDefault|stopPropagation
|
||||
on:keydown|stopPropagation
|
||||
on:submit|stopPropagation|preventDefault
|
||||
>
|
||||
<CalendarView
|
||||
weekStart="{1}"
|
||||
bind:vaue="{value}"
|
||||
on:change="{(e) => {
|
||||
value = e.detail
|
||||
}}"
|
||||
min="{today}"
|
||||
max="{oneYearFromNow}"
|
||||
blackout="{blackoutDates}"
|
||||
locale="de-DE"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="less">
|
||||
@import url("https://unpkg.com/fluent-svelte/theme.css");
|
||||
.container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
--fds-solid-background-quarternary: var(--background-color);
|
||||
--fds-text-primary: var(--normal-font-color);
|
||||
--fds-text-secondary: var(--normal-font-color-80);
|
||||
--fds-text-tertiary: var(--normal-font-color-50);
|
||||
--fds-text-disabled: var(--normal-font-color-30);
|
||||
--fds-accent-disabled: var(--opposite-bg-color-5);
|
||||
--fds-control-strong-stroke-default: var(--opposite-bg-color-80);
|
||||
.datepicker {
|
||||
width: fit-content;
|
||||
margin: 5px 0px;
|
||||
box-shadow: 0 0 25px 10px var(--opposite-bg-color-5);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import CheckboxGroup from "./checkboxGroup.svelte"
|
||||
import Datepicker from "./datepicker.svelte"
|
||||
import FormLabelNumberBlock from "./formLabelNumberBlock.svelte"
|
||||
import type { Writable } from "svelte/store"
|
||||
|
||||
@@ -24,6 +26,9 @@
|
||||
</script>
|
||||
|
||||
<div class="form-row">
|
||||
<h3 style="margin-bottom: -0.5rem;">
|
||||
{#if formRow.showRowName}{formRow.rowName || ""}{/if}
|
||||
</h3>
|
||||
<div class="form-cols">
|
||||
{#each formRow.columns as column, columnIndex}
|
||||
<div class="form-column">
|
||||
@@ -48,7 +53,7 @@
|
||||
on:change="{removeInvalid}"
|
||||
>
|
||||
<option value="" disabled selected>Bitte Uhrzeit wählen</option>
|
||||
{#each column?.times || [] as time}
|
||||
{#each column?.times ?? [] as time}
|
||||
<option value="{time?.timeFrom}-{time?.timeTo}">
|
||||
{time?.timeFrom} - {time?.timeTo}
|
||||
</option>
|
||||
@@ -114,49 +119,70 @@
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
{#each column.text || [] as textField, textFieldIndex}
|
||||
{#if textField?.textArea}
|
||||
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
|
||||
<textarea
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
on:change="{removeInvalid}"
|
||||
{#if column.showCheckboxGroup}
|
||||
<CheckboxGroup
|
||||
checkboxes="{column.checkboxes}"
|
||||
groupTitle="{column.groupTitle}"
|
||||
formValues="{formValues}"
|
||||
rowNr="{index}"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if column.showDatePicker}
|
||||
<Datepicker
|
||||
datePickerProps="{column.datePickerProps}"
|
||||
groupTitle="{column.groupTitle}"
|
||||
formValues="{formValues}"
|
||||
rowNr="{index}"
|
||||
formCol="{column}"
|
||||
|
||||
/>
|
||||
{/if}
|
||||
{#each column.text ?? [] as textField, textFieldIndex}
|
||||
<div>
|
||||
<h3 class="textTitle">{textField.textTitle || ""}</h3>
|
||||
{#if textField?.textArea}
|
||||
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
|
||||
<textarea
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
on:change="{removeInvalid}"
|
||||
bind:this="{$formValues[
|
||||
`textarea_Nachricht_${textField.textfieldOrder}_${index}_${
|
||||
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
|
||||
}`
|
||||
]}"></textarea>
|
||||
</label>
|
||||
{:else}
|
||||
<label
|
||||
bind:this="{$formValues[
|
||||
`textarea_Nachricht_${textField.textfieldOrder}_${index}_${
|
||||
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
|
||||
}`
|
||||
]}"></textarea>
|
||||
</label>
|
||||
{:else}
|
||||
<label
|
||||
bind:this="{$formValues[
|
||||
`input_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_label`
|
||||
]}"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
on:change="{removeInvalid}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
bind:this="{$formValues[
|
||||
`${
|
||||
textField?.telValidation
|
||||
? 'Telefon'
|
||||
: textField?.emailValidation
|
||||
? 'Email'
|
||||
: 'input'
|
||||
}_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_${
|
||||
textField.textfieldOrder
|
||||
}_${index}_${textField.emailName || columnIndex + 'invalidtext' + textFieldIndex}`
|
||||
`input_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_label`
|
||||
]}"
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
on:change="{removeInvalid}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
bind:this="{$formValues[
|
||||
`${
|
||||
textField?.telValidation
|
||||
? 'Telefon'
|
||||
: textField?.emailValidation
|
||||
? 'Email'
|
||||
: 'input'
|
||||
}_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_${
|
||||
textField.textfieldOrder
|
||||
}_${index}_${
|
||||
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
|
||||
}`
|
||||
]}"
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="less">
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import FormLabelNumberBlock from "./formLabelNumberBlock.svelte"
|
||||
import type { Writable } from "svelte/store"
|
||||
|
||||
import CheckboxGroup from "./checkboxGroup.svelte"
|
||||
import Datepicker from "./datepicker.svelte"
|
||||
export let formRow: FormRow
|
||||
export let formValues: Writable<FormValues>
|
||||
export let index: number
|
||||
@@ -126,46 +127,69 @@
|
||||
</label>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if column.showCheckboxGroup}
|
||||
<CheckboxGroup
|
||||
checkboxes="{column.checkboxes}"
|
||||
groupTitle="{column.groupTitle}"
|
||||
formValues="{formValues}"
|
||||
rowNr="{index}"
|
||||
/>
|
||||
{/if}
|
||||
{#if column.showDatePicker}
|
||||
<Datepicker
|
||||
datePickerProps="{column.datePickerProps}"
|
||||
groupTitle="{column.groupTitle}"
|
||||
formValues="{formValues}"
|
||||
rowNr="{index}"
|
||||
formCol="{column}"
|
||||
/>
|
||||
{/if}
|
||||
{#each column.text ?? [] as textField, textFieldIndex}
|
||||
<div class="column-{columnIndex} position-{getPosition(column, 5 + textFieldIndex, textFieldIndex)}">
|
||||
{#if textField?.textArea}
|
||||
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
|
||||
<textarea
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
on:change="{removeInvalid}"
|
||||
<h3 class="textTitle">{textField.textTitle || ""}</h3>
|
||||
<div
|
||||
class="column-{columnIndex} position-{getPosition(column, 5 + textFieldIndex, textFieldIndex)}"
|
||||
>
|
||||
{#if textField?.textArea}
|
||||
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
|
||||
<textarea
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
on:change="{removeInvalid}"
|
||||
bind:this="{$formValues[
|
||||
`textarea_Nachricht_${textField.textfieldOrder}_${index}_${
|
||||
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
|
||||
}`
|
||||
]}"></textarea>
|
||||
</label>
|
||||
{:else}
|
||||
<label
|
||||
bind:this="{$formValues[
|
||||
`textarea_Nachricht_${textField.textfieldOrder}_${index}_${
|
||||
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
|
||||
}`
|
||||
]}"></textarea>
|
||||
</label>
|
||||
{:else}
|
||||
<label
|
||||
bind:this="{$formValues[
|
||||
`input_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_label`
|
||||
]}"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
on:change="{removeInvalid}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
bind:this="{$formValues[
|
||||
`${
|
||||
textField?.telValidation
|
||||
? 'Telefon'
|
||||
: textField?.emailValidation
|
||||
? 'Email'
|
||||
: 'input'
|
||||
}_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_${
|
||||
textField.textfieldOrder
|
||||
}_${index}_${textField.emailName || columnIndex + 'invalidtext' + textFieldIndex}`
|
||||
`input_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_label`
|
||||
]}"
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
on:change="{removeInvalid}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
bind:this="{$formValues[
|
||||
`${
|
||||
textField?.telValidation
|
||||
? 'Telefon'
|
||||
: textField?.emailValidation
|
||||
? 'Email'
|
||||
: 'input'
|
||||
}_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_${
|
||||
textField.textfieldOrder
|
||||
}_${index}_${
|
||||
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
|
||||
}`
|
||||
]}"
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
{/each}
|
||||
|
||||
Reference in New Issue
Block a user