feat(curriculum): add form validation lab to FSD cert (#57211)

Co-authored-by: Zaira <33151350+zairahira@users.noreply.github.com>
This commit is contained in:
Dario-DC
2024-12-13 17:03:49 +01:00
committed by GitHub
parent db7f36c1db
commit 6462abdf0b
5 changed files with 884 additions and 1 deletions

View File

@@ -3042,7 +3042,12 @@
"You'll also practice basic regular expressions, template literals, the <code>addEventListener()</code> method, and more."
]
},
"egkv": { "title": "213", "intro": [] },
"lab-customer-complaint-form": {
"title": "Build a Customer Complaint Form",
"intro": [
"For this lab, you will use JavaScript to validate a customer complaint form."
]
},
"review-form-validation-with-javascript": {
"title": "Form Validation with JavaScript Review",
"intro": [

View File

@@ -0,0 +1,9 @@
---
title: Introduction to the Build a Customer Complaint Form
block: lab-customer-complaint-form
superBlock: full-stack-developer
---
## Introduction to the Build a Customer Complaint Form
For this lab, you will use JavaScript to validate a customer complaint form.

View File

@@ -0,0 +1,11 @@
{
"name": "Build a Customer Complaint Form",
"isUpcomingChange": true,
"usesMultifileEditor": true,
"blockType": "lab",
"blockLayout": "link",
"dashedName": "lab-customer-complaint-form",
"superBlock": "full-stack-developer",
"challengeOrder": [{ "id": "67279fe50237291f80eed8b8", "title": "Build a Customer Complaint Form" }],
"helpCategory": "JavaScript"
}

View File

@@ -0,0 +1,857 @@
---
id: 67279fe50237291f80eed8b8
title: Build a Customer Complaint Form
challengeType: 25
dashedName: build-a-customer-complaint-form
demoType: onClick
---
# --description--
For this lab, you have been provided with all the HTML and CSS. You will use JavaScript to validate the complaint form.
**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
**User Stories:**
1. When the form is submitted, you should ensure that:
- `#full-name` is not empty.
- `#email` is a valid email address format.
- `#order-no` is a sequence of ten numbers starting with `2024`.
- `#product-code` follows the pattern `XX##-X###-XX#`, where `X` represents either a lowercase letter or an uppercase letter and `#` represents a number.
- `#quantity` is a positive integer.
- at least one checkbox from `#complaints-group` is checked.
- `#complaint-description` contains at least twenty characters if the `Other` checkbox is checked.
- a radio button from `#solutions-group` is selected.
- `#solution-description` contains at least twenty characters if the `Other` radio button is selected.
1. You should have a function named `validateForm` that returns an object containing the following keys: `full-name`, `email`, `order-no`, `product-code`, `quantity`, `complaints-group`, `complaint-description`, `solutions-group`, and `solution-description`. The value of each key should be `true` if the corresponding form field is correctly filled and `false` otherwise.
1. You should have a function named `isValid` that takes the object returned by `validateForm` as argument and returns `true` if every form field is correctly filled and `false` otherwise.
1. If a change event is triggered on a form field and it has a valid value, you should set its border color to `green`. In case of checkbox and radio button groups, you should set the border color of the parent `fieldset`.
1. If a change event is triggered on a form field and it has an invalid value, you should set its border color to `red`. In case of checkbox and radio button groups, you should set the border color of the parent `fieldset`.
1. When you try to submit the form you should call `isValid` to validate the form.
1. When you try to submit the form, if the form has any invalid field, each invalid field should be highlighted by setting the border color of each invalid input, textarea or fieldset (in case of checkbox and radio button groups) to `red`.
# --hints--
You should have a function named `validateForm`.
```js
assert.isFunction(validateForm);
```
`validateForm` should return an object.
```js
assert.isObject(validateForm());
```
`validateForm()["full-name"]` should be `false` when `#full-name` is empty, and `true` otherwise.
```js
const field = document.getElementById("full-name");
field.value = "";
assert.isFalse(validateForm()["full-name"]);
field.value = "testing";
assert.isTrue(validateForm()["full-name"]);
```
When a `change` event is triggered on `#full-name`, you should set its border color to `green` if it contains a valid value, and `red` otherwise.
```js
const field = document.getElementById("full-name");
field.value = "testing"
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "green");
field.value = ""
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "red");
```
`validateForm()["email"]` should be `true` when `#email` contains a valid email address, and `false` otherwise.
```js
const field = document.getElementById("email");
field.value = "example@domain.com"
assert.isTrue(validateForm()["email"]);
field.value = "testing"
assert.isFalse(validateForm()["email"]);
```
When a `change` event is triggered on `#email`, you should set its border color to `green` if it contains a valid email address, and `red` otherwise.
```js
const field = document.getElementById("email");
field.value = "example@domain.com"
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "green");
field.value = ""
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "red");
```
`validateForm()["order-no"]` should be `true` when `#order-no` contains a valid value, and `false` otherwise.
```js
const field = document.getElementById("order-no");
field.value = "2024001122"
assert.isTrue(validateForm()["order-no"]);
field.value = "testing"
assert.isFalse(validateForm()["order-no"]);
```
When a `change` event is triggered on `#order-no`, you should set its border color to `green` if it contains a valid value, and `red` otherwise.
```js
const field = document.getElementById("order-no");
field.value = "2024001122"
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "green");
field.value = "20240011"
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "red");
```
`validateForm()["product-code"]` should be `true` when `#product-code` contains a valid value, and `false` otherwise.
```js
const field = document.getElementById("product-code");
field.value = "Xa22-X123-Xb4";
assert.isTrue(validateForm()["product-code"]);
field.value = "testing"
assert.isFalse(validateForm()["product-code"]);
```
When a `change` event is triggered on `#product-code`, you should set its border color to `green` if it contains a valid value, and `red` otherwise.
```js
const field = document.getElementById("product-code");
field.value = "Xa22-X123-Xb4"
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "green");
field.value = "Xa22-123-Xb4"
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "red");
```
`validateForm()["quantity"]` should be `true` when `#quantity` contains a valid value, and `false` otherwise.
```js
const field = document.getElementById("quantity");
field.value = "5";
assert.isTrue(validateForm()["quantity"]);
field.value = "0";
assert.isFalse(validateForm()["quantity"]);
```
When a `change` event is triggered on `#quantity`, you should set its border color to `green` if it contains a valid value, and `red` otherwise.
```js
const field = document.getElementById("quantity");
field.value = "2"
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "green");
field.value = "0"
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "red");
```
When at least one checkbox from `#complaints-group` is checked, `validateForm()["complaints-group"]` should be `true`.
```js
document.getElementById("damaged-product").checked = true
assert.isTrue(validateForm()["complaints-group"]);
```
When none of the checkboxes from `#complaints-group` is checked, `validateForm()["complaints-group"]` should be `false`.
```js
document.getElementById("damaged-product").checked = false;
document.getElementById("nonconforming-product").checked = false;
document.getElementById("delayed-dispatch").checked = false;
document.getElementById("other-complaint").checked = false;
assert.isFalse(validateForm()["complaints-group"]);
```
Once one checkbox from `#complaints-group` is checked, you should set `#complaints-group`'s border color to `green`.
```js
document.getElementById("damaged-product").checked = true;
document.getElementById("nonconforming-product").checked = false;
document.getElementById("delayed-dispatch").checked = false;
document.getElementById("other-complaint").checked = false;
const fieldset = document.getElementById("complaints-group");
fieldset.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(fieldset.style.borderColor, "green");
```
When all of the checkboxes from `#complaints-group` are changed to the unchecked state, you should set `#complaints-group`'s border color to `red`.
```js
document.getElementById("damaged-product").checked = false;
document.getElementById("nonconforming-product").checked = false;
document.getElementById("delayed-dispatch").checked = false;
document.getElementById("other-complaint").checked = false;
const fieldset = document.getElementById("complaints-group");
fieldset.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(fieldset.style.borderColor, "red");
```
When `#other-complaint` is checked and `#complaint-description` contains at least twenty characters, `validateForm()["complaint-description"]` should be `true`.
```js
document.getElementById("other-complaint").checked = true
document.getElementById("complaint-description").value = "A sentence with at least twenty characters";
assert.isTrue(validateForm()["complaint-description"]);
```
When `#other-complaint` is checked and `#complaint-description` contains less than twenty characters, `validateForm()["complaint-description"]` should be `false`.
```js
document.getElementById("other-complaint").checked = true
document.getElementById("complaint-description").value = "Less than 20 chars";
assert.isFalse(validateForm()["complaint-description"]);
```
Once the value of `#complaint-description` is changed to a valid value, you should set its border color to `green`.
```js
const field = document.getElementById("complaint-description");
field.value = "A sentence with at least twenty characters"
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "green");
```
Once the value of `#complaint-description` is changed to an invalid value, you should set its border color to `red`.
```js
const field = document.getElementById("complaint-description");
field.value = "Not enough chars"
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "red");
```
When a radio button from `#solutions-group` is checked, `validateForm()["solutions-group"]` should be `true`.
```js
document.getElementById("refund").checked = true
assert.isTrue(validateForm()["solutions-group"]);
```
When none of the radio buttons from `#solutions-group` is checked, `validateForm()["solutions-group"]` should be `false`.
```js
document.getElementById("refund").checked = false;
document.getElementById("exchange").checked = false;
document.getElementById("other-solution").checked = false;
assert.isFalse(validateForm()["solutions-group"]);
```
Once a radio button from `#solutions-group` is checked, you should set `#solutions-group`'s border color to `green`.
```js
document.getElementById("refund").checked = true;
document.getElementById("exchange").checked = false;
document.getElementById("other-solution").checked = false;
const fieldset = document.getElementById("solutions-group");
fieldset.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(fieldset.style.borderColor, "green");
```
When all of the checkboxes from `#complaints-group` are changed to the unchecked state, you should set `#complaints-group`'s border color to `red`.
```js
document.getElementById("refund").checked = false;
document.getElementById("exchange").checked = false;
document.getElementById("other-solution").checked = false;
const fieldset = document.getElementById("solutions-group");
fieldset.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(fieldset.style.borderColor, "red");
```
When `#other-solution` is checked and `#solution-description` contains at least twenty characters, `validateForm()["solution-description"]` should be `true`.
```js
document.getElementById("other-solution").checked = true
document.getElementById("solution-description").value = "A sentence with at least twenty characters";
assert.isTrue(validateForm()["solution-description"]);
```
When `#other-solution` is checked and `#solution-description` contains less than twenty characters, `validateForm()["solution-description"]` should be `false`.
```js
document.getElementById("other-solution").checked = true
document.getElementById("solution-description").value = "Less than 20 chars";
assert.isFalse(validateForm()["solution-description"]);
```
Once the value of `#solution-description` is changed to a valid value, you should set its border color to `green`.
```js
const field = document.getElementById("solution-description");
field.value = "A sentence with at least twenty characters"
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "green");
```
Once the value of `#solution-description` is changed to an invalid value, you should set its border color to `red`.
```js
const field = document.getElementById("solution-description");
field.value = "Not enough chars"
field.dispatchEvent(new Event("change", { bubbles: true }));
assert.equal(field.style.borderColor, "red");
```
You should have a function named `isValid`.
```js
assert.isFunction(isValid);
```
Your `isValid` function should take the `validateForm()` as its argument and return `true` when all the form fields have been filled correctly.
```js
document.getElementById("full-name").value = "testing"
document.getElementById("email").value = "example@domain.com"
document.getElementById("order-no").value = "2024001122"
document.getElementById("product-code").value = "Xa22-X123-Xb4"
document.getElementById("quantity").value = "5"
document.getElementById("damaged-product").checked = true
document.getElementById("other-complaint").checked = false
document.getElementById("refund").checked = true
document.getElementById("other-solution").checked = false
assert.isTrue(isValid(validateForm()));
document.getElementById("other-complaint").checked = true
document.getElementById("complaint-description").value = "A sentence with at least twenty characters";
document.getElementById("other-solution").checked = true
document.getElementById("solution-description").value = "A sentence with at least twenty characters";
assert.isTrue(isValid(validateForm()));
```
Your `isValid` function should take the `validateForm()` as its argument and return `false` when not all the form fields have been filled correctly.
```js
const name = document.getElementById("full-name");
const email = document.getElementById("email");
const orderNo = document.getElementById("order-no");
const prCode = document.getElementById("product-code");
const quantity = document.getElementById("quantity");
const damaged = document.getElementById("damaged-product");
const nonConforming = document.getElementById("nonconforming-product");
const delayed = document.getElementById("delayed-dispatch");
const otherC = document.getElementById("other-complaint");
const complaintDescr = document.getElementById("complaint-description");
const refund = document.getElementById("refund");
const exchange = document.getElementById("exchange");
const otherS = document.getElementById("other-solution");
const solutionDescr = document.getElementById("solution-description");
// invalid full-name
name.value = "";
email.value = "example@domain.com";
orderNo.value = "2024001122";
prCode.value = "Xa22-X123-Xb4";
quantity.value = "5";
damaged.checked = true;
refund.checked = true;
assert.isFalse(isValid(validateForm()));
// invalid email
name.value = "testing";
email.value = "";
assert.isFalse(isValid(validateForm()));
// invalid order-no
email.value = "example@domain.com";
orderNo.value = "202400";
assert.isFalse(isValid(validateForm()));
// invalid product-code
orderNo.value = "2024001122";
prCode.value = "1a22-Xa23-Xb4";
assert.isFalse(isValid(validateForm()));
// invalid quantity
prCode.value = "Xa22-X123-Xb4";
quantity.value = 0;
assert.isFalse(isValid(validateForm()));
// invalid complaints-group
quantity.value = 5;
damaged.checked = false;
nonConforming.checked = false;
delayed.checked = false;
otherC.checked = false;
assert.isFalse(isValid(validateForm()));
// invalid complaint-description
otherC.checked = true;
complaintDescr.value = "not enough chars";
assert.isFalse(isValid(validateForm()));
// invalid solutions-group
complaintDescr.value = "A sentence with at least twenty characters";
refund.checked = false;
exchange.checked = false;
otherS.checked = false;
assert.isFalse(isValid(validateForm()));
// invalid solutions-description
otherS.checked = true;
solutionDescr.value = "not enough chars";
assert.isFalse(isValid(validateForm()));
```
You should call `isValid` when you try to submit the form.
```js
let flag = false;
const temp = isValid;
try {
isValid = (obj) => {flag = true};
document.getElementById("form").dispatchEvent(new Event("submit"));
assert.isTrue(flag);
} finally {
isValid = temp;
}
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Customer Complaint Form</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Complaint Form</h1>
<form id="form">
<fieldset id="personal-info">
<div>
<label for="full-name">Full Name:</label>
<input type="text" id="full-name" name="full-name" placeholder="John Doe">
</div>
<div>
<label for="email">Email Address:</label>
<input type="email" id="email" name="email" placeholder="example@domain.com">
</div>
</fieldset>
<hr>
<fieldset id="product-info">
<div>
<label for="order-no">Order No:</label>
<input type="text" id="order-no" name="order-no" placeholder="2024######">
</div>
<div>
<label for="product-code">Product Code:</label>
<input type="text" id="product-code" name="product-code" placeholder="XX##-X###-XX#">
</div>
<div>
<label for="quantity">Quantity:</label>
<input type="number" id="quantity" name="quantity" min="1">
</div>
</fieldset>
<fieldset id="complaints-group">
<legend>Complaint Reason:</legend>
<div>
<input type="checkbox" id="damaged-product" name="complaint" value="damaged-product">
<label for="damaged-product">Damaged Product</label>
</div>
<div>
<input type="checkbox" id="nonconforming-product" name="complaint" value="nonconforming-product">
<label for="nonconforming-product">Nonconforming Product</label>
</div>
<div>
<input type="checkbox" id="delayed-dispatch" name="complaint" value="delayed-dispatch">
<label for="delayed-dispatch">Delayed Dispatch</label>
</div>
<div>
<input type="checkbox" id="other-complaint" name="complaint" value="other">
<label for="other-complaint">Other</label>
</div>
</fieldset>
<div id="complaint-description-container">
<legend>Description of Complaint Reason</legend>
<textarea placeholder="Describe the reason of your complaint in at least 20 characters"
name="complaint-textarea" id="complaint-description"></textarea>
</div>
<fieldset id="solutions-group">
<legend>Desired Solution</legend>
<input type="radio" name="solutions" id="refund" value="refund">
<label for="refund">Refund</label>
<input type="radio" name="solutions" id="exchange" value="exchange">
<label for="exchange">Exchange</label>
<input type="radio" name="solutions" id="other-solution" value="other">
<label for="other-solution">Other</label>
</fieldset>
<div id="solution-description-container">
<legend>Description of Desired Solution</legend>
<textarea placeholder="Describe the desired solution to your issue in at least 20 characters"
name="solution-textarea" id="solution-description"></textarea>
</div>
<div id="btn-container">
<button type="submit" id="submit-btn">Submit</button>
<span id="message-box"></span>
</div>
</form>
<script src="script.js"></script>
</body>
</html>
```
```css
* {
box-sizing: border-box;
}
h1 {
text-align: center;
}
#form {
max-width: 70%;
margin: auto;
border-radius: 10px;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
padding: 10px;
}
input {
border-color: rgb(118, 118, 118);
}
#personal-info input, #product-info input {
width: 100%;
margin-bottom: 10px;
}
fieldset {
margin-bottom: 10px;
border-radius: 5px;
border-color: rgb(118, 118, 118);
}
textarea {
width: 100%;
border-color: rgb(118, 118, 118);
}
#btn-container {
display: flex;
justify-content: space-between;
align-items: center;
}
#submit-btn, #clear-btn {
margin: 10px 15px 0;
}
```
```js
```
## --solutions--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Customer Complaint Form</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Complaint Form</h1>
<form id="form">
<fieldset id="personal-info">
<div>
<label for="full-name">Full Name:</label>
<input type="text" id="full-name" name="full-name" placeholder="John Doe">
</div>
<div>
<label for="email">Email Address:</label>
<input type="email" id="email" name="email" placeholder="example@domain.com">
</div>
</fieldset>
<hr>
<fieldset id="product-info">
<div>
<label for="order-no">Order No:</label>
<input type="text" id="order-no" name="order-no" placeholder="2024######">
</div>
<div>
<label for="product-code">Product Code:</label>
<input type="text" id="product-code" name="product-code" placeholder="XX##-X###-XX#">
</div>
<div>
<label for="quantity">Quantity:</label>
<input type="number" id="quantity" name="quantity" min="1">
</div>
</fieldset>
<fieldset id="complaints-group">
<legend>Complaint Reason:</legend>
<div>
<input type="checkbox" id="damaged-product" name="complaint" value="damaged-product">
<label for="damaged-product">Damaged Product</label>
</div>
<div>
<input type="checkbox" id="nonconforming-product" name="complaint" value="nonconforming-product">
<label for="nonconforming-product">Nonconforming Product</label>
</div>
<div>
<input type="checkbox" id="delayed-dispatch" name="complaint" value="delayed-dispatch">
<label for="delayed-dispatch">Delayed Dispatch</label>
</div>
<div>
<input type="checkbox" id="other-complaint" name="complaint" value="other">
<label for="other-complaint">Other</label>
</div>
</fieldset>
<div id="complaint-description-container">
<legend>Description of Complaint Reason</legend>
<textarea placeholder="Describe the reason of your complaint in at least 20 characters"
name="complaint-textarea" id="complaint-description"></textarea>
</div>
<fieldset id="solutions-group">
<legend>Desired Solution</legend>
<input type="radio" name="solutions" id="refund" value="refund">
<label for="refund">Refund</label>
<input type="radio" name="solutions" id="exchange" value="exchange">
<label for="exchange">Exchange</label>
<input type="radio" name="solutions" id="other-solution" value="other">
<label for="other-solution">Other</label>
</fieldset>
<div id="solution-description-container">
<legend>Description of Desired Solution</legend>
<textarea placeholder="Describe the desired solution to your issue in at least 20 characters"
name="solution-textarea" id="solution-description"></textarea>
</div>
<div id="btn-container">
<button type="submit" id="submit-btn">Submit</button>
<span id="message-box"></span>
<button type="button" id="clear-btn">Clear</button>
</div>
</form>
<script src="script.js"></script>
</body>
</html>
```
```css
* {
box-sizing: border-box;
}
h1 {
text-align: center;
}
#form {
max-width: 70%;
margin: auto;
border-radius: 10px;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
padding: 10px;
}
input {
border-color: rgb(118, 118, 118);
}
#personal-info input, #product-info input {
width: 100%;
margin-bottom: 10px;
}
fieldset {
margin-bottom: 10px;
border-radius: 5px;
border-color: rgb(118, 118, 118);
}
textarea {
width: 100%;
border-color: rgb(118, 118, 118);
}
#btn-container {
display: flex;
justify-content: space-between;
align-items: center;
}
#submit-btn, #clear-btn {
margin: 10px 15px 0;
}
```
```js
const form = document.getElementById("form");
const fullName = document.getElementById("full-name");
const emailAddress = document.getElementById("email");
const orderNo = document.getElementById("order-no");
const productCode = document.getElementById("product-code");
const quantity = document.getElementById("quantity");
const complaints = document.querySelectorAll('input[name="complaint"]');
const complaintDescription = document.getElementById("complaint-description");
const complaintTextAreaDiv = document.getElementById("complaint-description-container");
const solutions = document.querySelectorAll('input[name="solutions"]');
const solutionDescription = document.getElementById("solution-description");
const solutionTextAreaDiv = document.getElementById("solution-description-container");
const submitBtn = document.getElementById("submit-btn");
const messageBox = document.getElementById("message-box");
const clearBtn = document.getElementById("clear-btn");
const hideTextareas = () => {
complaintTextAreaDiv.style.display = "none";
solutionTextAreaDiv.style.display = "none";
}
hideTextareas();
const formFields = {
"full-name": fullName,
"email": emailAddress,
"order-no": orderNo,
"product-code": productCode,
"quantity": quantity,
"complaints-group": Array.from(complaints),
"complaint-description": complaintDescription,
"solutions-group": Array.from(solutions),
"solution-description": solutionDescription
}
const clearForm = () => {
Object.entries(formFields).forEach(entry => {
const [key, val] = entry;
if (Array.isArray(val)) {
val.forEach(i => i.checked = false);
} else {
val.value = "";
}
hideTextareas();
messageBox.innerText = "";
document.getElementById(key).style.borderColor = "rgb(118, 118, 118)";
})
}
const validateForm = () => {
const complaintsArr = Array.from(complaints).map(i => i.checked);
const solutionsArr = Array.from(solutions).map(i => i.checked);
const validationObject = {
"full-name": Boolean(fullName.value.trim()),
"email": /^\S+@\S+\.\S+$/.test(emailAddress.value.trim()),
"order-no": /^2024\d{6}$/.test(orderNo.value.trim()),
"product-code": /[A-Z]{2}\d{2}-[A-Z]\d{3}-[A-Z]{2}\d/i.test(productCode.value.trim()),
"quantity": Number(quantity.value.trim()) > 0,
"complaints-group": complaintsArr.some(i => i),
"complaint-description": null,
"solutions-group": solutionsArr.some(i => i),
"solution-description": null
}
if (complaintsArr[3]) {
complaintTextAreaDiv.style.display = "block";
const complaintsDescriptionVal = complaintDescription.value.trim();
if (complaintsDescriptionVal.length < 20) {
validationObject["complaint-description"] = false;
} else {
validationObject["complaint-description"] = true;
}
} else {
complaintTextAreaDiv.style.display = "none";
}
if (solutionsArr[2]) {
solutionTextAreaDiv.style.display = "block";
const solutionDescriptionVal = solutionDescription.value.trim();
if (solutionDescriptionVal.length < 20) {
validationObject["solution-description"] = false;
} else {
validationObject["solution-description"] = true;
}
} else {
solutionTextAreaDiv.style.display = "none";
}
if (validationObject["complaint-description"] === null) delete validationObject["complaint-description"];
if (validationObject["solution-description"] === null) delete validationObject["solution-description"];
return validationObject;
}
clearBtn.addEventListener("click", clearForm);
Object.keys(formFields).forEach(key => {
document.getElementById(key).addEventListener("change", (e) => {
const validationObject = validateForm();
if (Object.values(validationObject).every(val => val)) messageBox.innerText = "";
if (!validationObject[key]) {
document.getElementById(key).style.borderColor = "red";
} else {
document.getElementById(key).style.borderColor = "green";
}
});
});
const isValid = (validationObj) => Object.values(validationObj).every(i => i);
form.addEventListener("submit", (e) => {
e.preventDefault();
const validationObject = validateForm();
if (!isValid(validationObject)) {
messageBox.innerText = "Please, fill out the required fields correctly before submitting.";
Object.keys(validationObject).forEach(key => {
if (!validationObject[key]) {
document.getElementById(key).style.borderColor = "red";
} else {
document.getElementById(key).style.borderColor = "green";
}
});
} else {
messageBox.innerText = "";
alert("Form successfully submitted.");
clearForm();
}
});
```

View File

@@ -445,6 +445,7 @@
"blocks": [
{ "dashedName": "lecture-understanding-form-validation" },
{ "dashedName": "workshop-calorie-counter" },
{ "dashedName": "lab-customer-complaint-form" },
{ "dashedName": "review-form-validation-with-javascript" },
{ "dashedName": "quiz-form-validation-with-javascript" }
]