feat(15): phone validation htmx inline

making phone input as a fragment that accepts value and error
initial value from overall state, initial error empty string

some contitional classes and hidden error message
wowy,
endpoint that takes POST request, extracts value and resends the
rendered fragment. cool
This commit is contained in:
efim
2023-07-16 15:07:46 +00:00
parent 8c0318c4e2
commit 77bcf87cd1
5 changed files with 162 additions and 64 deletions

View File

@@ -572,10 +572,6 @@ video {
grid-row: span 2 / span 2;
}
.row-span-full {
grid-row: 1 / -1;
}
.row-start-1 {
grid-row-start: 1;
}
@@ -655,6 +651,10 @@ video {
display: inline-grid;
}
.contents {
display: contents;
}
.hidden {
display: none;
}
@@ -777,14 +777,6 @@ video {
grid-template-columns: repeat(4, auto);
}
.grid-rows-5 {
grid-template-rows: repeat(5, minmax(0, 1fr));
}
.grid-rows-3 {
grid-template-rows: repeat(3, minmax(0, 1fr));
}
.flex-row {
flex-direction: row;
}
@@ -879,6 +871,11 @@ video {
border-color: rgb(255 255 255 / var(--tw-border-opacity));
}
.border-strawberry-red {
--tw-border-opacity: 1;
border-color: hsl(354 84% 57% / var(--tw-border-opacity));
}
.\!bg-light-blue {
--tw-bg-opacity: 1 !important;
background-color: hsl(206 94% 87% / var(--tw-bg-opacity)) !important;
@@ -1063,6 +1060,11 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.text-strawberry-red {
--tw-text-opacity: 1;
color: hsl(354 84% 57% / var(--tw-text-opacity));
}
.underline {
text-decoration-line: underline;
}

View File

@@ -33,13 +33,14 @@
</head>
<body>
<main class="grid place-content-center w-screen h-screen bg-magnolia">
<section
hx-get="/get-form"
hx-trigger="load"
hx-swap="outerHTML"
>
<section hx-get="/get-form" hx-trigger="load" hx-swap="outerHTML">
<!-- here be immediate hx-get for the form. to subscitute the body -->
<img class="w-14 text-green-500 fill-current" th:src="'public/images/tail-spin.svg'" src="../public/images/tail-spin.svg" alt="loading..." />
<img
class="w-14 text-green-500 fill-current"
th:src="'public/images/tail-spin.svg'"
src="../public/images/tail-spin.svg"
alt="loading..."
/>
</section>
<section class="absolute top-0 end-0" id="new-session-control">

View File

@@ -126,42 +126,81 @@
<p class="py-3 text-cool-gray">
Please provide your name, email address, and phone number.
</p>
<label for="name" class="pt-3 text-sm md:pt-5 md:pb-2 text-marine-blue"
>Name</label
<div class="contents">
<label
for="name"
class="pt-3 text-sm md:pt-5 md:pb-2 text-marine-blue"
>Name</label
>
<input
id="name"
th:value="${formData.userAnswers.step1.name}"
name="name"
type="text"
required
placeholder="e.g. Stephen King"
class="p-1 px-4 h-10 text-sm font-semibold rounded border md:p-6 md:px-4 md:text-base md:rounded-lg focus:outline-none placeholder:text-cool-gray invalid:border-strawberry-red focus:border-marine-blue"
/>
</div>
<div class="contents">
<label
for="email"
class="pt-3 text-sm md:pt-5 md:pb-2 text-marine-blue"
>Email Address</label
>
<input
id="email"
th:value="${formData.userAnswers.step1.email}"
name="email"
type="email"
required
placeholder="e.g. stephenking@lorem.com"
class="p-1 px-4 h-10 text-sm font-semibold rounded border md:p-6 md:px-4 md:text-base md:rounded-lg focus:outline-none placeholder:text-cool-gray invalid:border-strawberry-red focus:border-marine-blue"
/>
</div>
<!-- Following is email input field
it has outer div that sets separate 'value' variable
and innder div which denotes fragment, parametrized by this only variable
now i should be able to render only this input field as fragment -->
<div
th:with="value=${formData.userAnswers.step1.phone},error=''"
class="contents relative"
>
<input
id="name"
th:value="${formData.userAnswers.step1.name}"
name="name"
type="text"
required
placeholder="e.g. Stephen King"
class="p-1 px-4 h-10 text-sm font-semibold rounded border md:p-6 md:px-4 md:text-base md:rounded-lg focus:outline-none placeholder:text-cool-gray invalid:border-strawberry-red focus:border-marine-blue"
/>
<label for="email" class="pt-3 text-sm md:pt-5 md:pb-2 text-marine-blue"
>Email Address</label
>
<input
id="email"
th:value="${formData.userAnswers.step1.email}"
name="email"
type="email"
required
placeholder="e.g. stephenking@lorem.com"
class="p-1 px-4 h-10 text-sm font-semibold rounded border md:p-6 md:px-4 md:text-base md:rounded-lg focus:outline-none placeholder:text-cool-gray invalid:border-strawberry-red focus:border-marine-blue"
/>
<label for="phone" class="pt-3 text-sm md:pt-5 md:pb-2 text-marine-blue"
>Phone Number</label
>
<input
id="phone"
th:value="${formData.userAnswers.step1.phone}"
name="phone"
type="tel"
required
placeholder="e.g. +1 234 567 890"
class="p-1 px-4 h-10 text-sm font-semibold rounded border md:p-6 md:px-4 md:text-base md:rounded-lg focus:outline-none placeholder:text-cool-gray invalid:border-strawberry-red focus:border-marine-blue"
/>
<div
class="contents"
hx-target="this"
hx-swap="outerHTML"
th:fragment="email-input (value,error)"
>
<label
for="phone"
class="pt-3 text-sm md:pt-5 md:pb-2 text-marine-blue"
>Phone Number</label
>
<input
id="phone"
th:value="${value}"
name="phone"
type="tel"
required
placeholder="e.g. +1 234 567 890"
class="p-1 px-4 h-10 text-sm font-semibold rounded border md:p-6 md:px-4 md:text-base md:rounded-lg focus:outline-none placeholder:text-cool-gray invalid:border-strawberry-red focus:border-marine-blue"
th:classappend="${!error.isEmpty} ? 'border-strawberry-red' : ''"
hx-post="/step1/phonenumber"
hx-indicator="#ind"
/>
<div
th:if="${error} != null"
th:text="${error}"
class="text-sm text-strawberry-red">Please enter valid phone number</div>
<img
id="ind"
src="../public/images/tail-spin.svg"
th:src="'public/images/tail-spin.svg'"
class="absolute w-14 h-14 htmx-indicator"
/>
</div>
</div>
<!-- Step 1 end -->
</section>