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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user