Bootstrap form validation disable my radio buttons - forms

I use boostrap form validation on my form for 2 input text only (I do not want to validate radio button).
My problem is that when displaying errors on the input text (a value is required), it disables the radio button and even change the color of the radio button text. How to avoid that ?
Here is the code
<div class="form-group">
<label for="txtDatenaissance">Date de naissance</label>
<input type="text" class="form-control" id="txtDateNaissance"
name="txtDateNaissance" data-provide="datepicker"
placeholder="JJ/MM/YYYY" data-date-format="dd/mm/yyyy" required="required"/>
<div class="invalid-feedback">
La date de naissance est obligatoire
</div>
</div>
<div class="form-group">
<div class="custom-control custom-control-inline custom-radio">
<input type="radio" class="custom-control-input" id="rdoOui" name="rdoRetraite" value="1" />
<label class="custom-control-label" for="rdoOui">Oui</label>
</div>
<div class="custom-control custom-control-inline custom-radio">
<input type="radio" class="custom-control-input" id="rdoNon" name="rdoRetraite" value="0" checked="checked" />
<label class="custom-control-label" for="rdoNon">Non</label>
</div>
</div>
<div id="divMetier" class="form-group d-none">
<label for="txtMetier">Métier exercé</label>
<input type="text" class="form-control" id="txtMetier" name="txtMetier" valueId="0" required="required" />
<div class="invalid-feedback">
Le métier est obligatoire
</div>
</div>
in JS :
$( document ).ready(function() {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
After investigating, the problem seems to with the all the custom classes because it works good if I use form-check classes (so normal button : it is ugly but it works).

Here I placed the radio and submit button outside the form with the help of form attribute
$(document).ready(function() {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
<form class="needs-validation" id="formid" novalidate>
<div class="form-group">
<label for="txtDatenaissance">Date de naissance</label>
<input type="text" class="form-control" id="txtDateNaissance" name="txtDateNaissance" data-provide="datepicker" placeholder="JJ/MM/YYYY" data-date-format="dd/mm/yyyy" required="required" />
<div class="invalid-feedback">
La date de naissance est obligatoire
</div>
</div>
<div id="divMetier" class="form-group d-none">
<label for="txtMetier">Métier exercé</label>
<input type="text" class="form-control" id="txtMetier" name="txtMetier" valueId="0" required="required" />
<div class="invalid-feedback">
Le métier est obligatoire
</div>
</div>
</form>
<div class="form-group">
<div class="custom-control custom-control-inline custom-radio">
<input type="radio" class="custom-control-input" id="rdoOui" name="rdoRetraite" value="1" />
<label class="custom-control-label" for="rdoOui">Oui</label>
</div>
<div class="custom-control custom-control-inline custom-radio">
<input type="radio" class="custom-control-input" id="rdoNon" name="rdoRetraite" value="0" checked="checked" />
<label class="custom-control-label" for="rdoNon">Non</label>
</div>
</div>
<button class="btn btn-primary" form="formid" type="submit">Submit form</button>
Using custom class custom-radio-primary
$(document).ready(function() {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
/* custom-radio-primary escapes validation with primary color */
.custom-radio-primary label {
color: #212529!important;
}
.custom-radio-primary .custom-control-input:checked~.custom-control-label::before {
border-color: #007bff!important;
background-color: #007bff!important;
}
.custom-radio-primary .custom-control-input~.custom-control-label::before {
border: #adb5bd solid 1px!important;
}
.custom-radio-primary .custom-control-input:focus~.custom-control-label::before {
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, .25)!important;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
<form class="needs-validation" id="formid" novalidate>
<div class="form-group">
<label for="txtDatenaissance">Date de naissance</label>
<input type="text" class="form-control" id="txtDateNaissance" name="txtDateNaissance" data-provide="datepicker" placeholder="JJ/MM/YYYY" data-date-format="dd/mm/yyyy" required="required" />
<div class="invalid-feedback">
La date de naissance est obligatoire
</div>
</div>
<div class="form-group">
<div class="custom-control custom-control-inline custom-radio custom-radio-primary">
<input type="radio" class="custom-control-input" id="rdoOui" name="rdoRetraite" value="1" />
<label class="custom-control-label" for="rdoOui">Oui</label>
</div>
<div class="custom-control custom-control-inline custom-radio custom-radio-primary">
<input type="radio" class="custom-control-input" id="rdoNon" name="rdoRetraite" value="0" checked="checked" />
<label class="custom-control-label" for="rdoNon">Non</label>
</div>
</div>
<div id="divMetier" class="form-group d-none">
<label for="txtMetier">Métier exercé</label>
<input type="text" class="form-control" id="txtMetier" name="txtMetier" valueId="0" required="required" />
<div class="invalid-feedback">
Le métier est obligatoire
</div>
</div>
<button class="btn btn-primary" form="formid" type="submit">Submit form</button>
</form>

Related

Bootstrap 5 form validation - required & disabled

I currently have a disabled input box. I use the box to display the sum of two range sliders, where I update the value of the box via JavaScript.
I currently require that the value of the box equals 100 before allowing the form to be submitted. Is there a work-around where I can still disable the box, where it will still adopt the same Bootstrap style formatting (change color from red to green, etc) as a non-disabled box with the 'require' option?
Following a suggestion here, I've updated the code snippet below to almost be what I want. The only thing that I'd like to change, is to make 'rSum', the box that displays the sum, disabled (while still keeping all the validation formatting features). Ideally, I want this sum to adopt the validation feedback rather than the sliders, or other mutable input objects.
function checkSum() {
let currSum = parseInt(document.getElementById('rSum').value);
if (currSum != 100) {
document.getElementById('rSum').setCustomValidity('Must sum to 100%');
return false
} else {
document.getElementById('rSum').setCustomValidity('');
return true
}
}
function updateBoxes() {
const s1 = document.getElementById('range1');
const s2 = document.getElementById('range2');
let currSum = parseInt(s1.value) + parseInt(s2.value);
document.getElementById('rangeValue1').value = (s1.value)+"%";
document.getElementById('rangeValue2').value = (s2.value)+"%";
document.getElementById('rSum').value = (currSum)+"%";
}
// This last function is the original bootstrap validation example, modified to call 'checkSum()' instead
(function () {
'use strict'
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.querySelectorAll('.custom-validation')
// Loop over them and prevent submission
Array.prototype.slice.call(forms)
.forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!checkSum()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
<form class="custom-validation" novalidate>
<div class="mb-3 row">
<div class="form-group col-md-1">
<input class="form-control" type="text" id="rangeValue1" disabled>
</div>
<div class="form-group col-md-4 col-form-label">
<input type="range" class="form-range" min="0" max="100" step="5" id="range1" value="0" onchange="updateBoxes()" >
</div>
</div>
<div class="mb-3 row">
<div class="form-group col-md-1">
<input class="form-control" type="text" id="rangeValue2" disabled>
</div>
<div class="form-group col-md-4 col-form-label">
<input type="range" class="form-range" min="0" max="100" step="5" id="range2" value="0" onchange="updateBoxes()" >
</div>
</div>
<div class="mb-3 row">
<div class="form-group">
<input type="text" class="form-control text-center" id="rSum" placeholder="100%" required>
<div class="valid-feedback">
Looks good!
</div>
<div class="invalid-feedback">
Probabilities must add up to 100%
</div>
</div>
</div>
<div class="mb-3 row">
<div class="col-sm-6 offset-md-1">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
A couple of ways to do this. Here I use an example form with some inputs that can be used in the slider validation (one is a range slider but could be a simple number input also).
I set an event handler for those elements, associate them using data attributes and then; very verbosely and a bit ugly for clarity, use them in a function.
function checkSum(event) {
const fearRequird = this.fearNeed;
const myFear = event.target;
const associated = document.querySelector(myFear.dataset.related);
const result = this.sumEl;
const thisValue = parseInt(myFear.value);
const associatedValue = parseInt(associated.value);
let currSum = thisValue + associatedValue;
result.value = currSum;
let isValidSlider = currSum >= fearRequird;
result.classList.toggle("is-valid", isValidSlider);
result.classList.toggle("is-invalid", !isValidSlider);
let t = isValidSlider ? '' : `You Fear ${thisValue} and ${associatedValue} total ${currSum}. You need total ${fearRequird} fear`;
result.setCustomValidity(t);
result.closest('.form-group').querySelector('.invalid-feedback').textContent = t;
return isValidSlider;
}
(function() {
'use strict'
// Fetch all the forms we want to apply custom Bootstrap validation styles to
let forms = document.querySelectorAll('.needs-validation');
// Loop over them and prevent submission
Array.prototype.slice.call(forms)
.forEach(function(form) {
form.addEventListener('submit', function(event) {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false)
});
const fearNeed = 100;
const myFears = document.querySelectorAll('.fear-factor');
const needs = {
fearNeed: fearNeed,
sumEl: document.querySelector('#rSum')
};
myFears.forEach((fearElement) => {
fearElement.addEventListener('change', checkSum.bind(needs), false);
});
})();
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
<form class="row g-3 needs-validation mx-1 my-2" novalidate>
<div class="form-group">
<input type="text" class="form-control text-center" id="rSum" placeholder="100%" required>
<div class="valid-feedback">
Looks good!
</div>
<div class="invalid-feedback">
Fears must add up to 100%
</div>
</div>
<div class="col-md-4">
<label for="validationCustomUsername" class="form-label">Fish Name</label>
<div class="input-group has-validation">
<span class="input-group-text" id="inputGroupPrepend">Fish</span>
<input type="text" class="form-control" id="validationCustomFishname" aria-describedby="inputGroupPrepend" required>
<div class="invalid-feedback">
Must catch a fish.
</div>
<div class="valid-feedback">
Looks like an good catch!
</div>
</div>
</div>
<div class="col-md-3">
<label for="validationCustomFearMet" class="form-label">Scary cats fear</label>
<div class="input-group has-validation">
<input type="number" class="form-control fear-factor" min="0" max="100" step="1" value="13" id="validationCustomFearMet" data-related="#customRange3" required />
<span class="input-group-text" id="inputGroupPrepend">%</span>
<div class="invalid-feedback">
Please provide scary cats fear as a percent 0-100.
</div>
<div class="invalid-feedback">
Please provide scary cats fear as a percent 0-100.
</div>
</div>
</div>
<div class="mx-1">
<label for="customRange3" class="form-label">Fear range</label>
<input type="range" class="form-range fear-factor" min="0" max="100" step="1" value="0" data-related="#validationCustomFearMet" id="customRange3">
</div>
<div class="col-12">
<button class="btn btn-primary" type="submit">Submit form</button>
</div>
</form>

Google Sheets HTML data input, can't get it to populate

Spreadsheet:
The html data entry:
I have been working on this for 8 hours, I cannot figure it out.
I have a website that I am uploading items to be sold. I have a Google sheet that I am keeping track of this information. We will have probably over 3,000 items to sell, so this html would be a lifesaver!
I however cannot get it to populate into my Google sheets. It runs, I don't get error messages, it just won't populate in my sheet.
This is my sheet, it is open
I am teaching myself how to do the website myself, I only have about 3 or 4 months under my belt. Any help would be WONDERFUL!
Code GS
function doGet(request) {
return HtmlService.createTemplateFromFile("Index").evaluate();
}
/* #Include JavaScript and CSS Files */
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
/* #Process Form */
function processForm(formObject) {
var url =
"https://docs.google.com/spreadsheets/d/1uF5YBKyfVxvrA4QrUuRqHrxe7C1qEySIxAL_r-PkBIQ/edit#gid=1180254005";
function processForm(formObject) {
var ss = SpreadsheetApp.getActive();
var ws = ss.getSheetByName("Data");
ws.appendRow([
formObject.location,
formObject.itemNumber,
formObject.name,
formObject.description,
formObject.price,
formObject.markedDown,
formObject.pricePaid,
formObject.category,
formObject.sold,
formObject.postedOnline,
]);
}
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<?!= include('JavaScript'); ?>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-6">
<form id="myForm" onsubmit="handleFormSubmit(this)">
<p class="h4 mb-4 text-center font-weight-bold">Seattle Bound Data</p>
<!-- Row 1 -->
<div class="form-row">
<div class="form-group col-md-4 font-weight-bold">
<label for="first_name">Location</label>
<input type="text" class="form-control" id="location" name="location" placeholder="Location">
</div>
<div class="form-group col-md-4 font-weight-bold">
<label for="itemNumber">Item Number</label>
<input type="text" class="form-control" id="itemNumber" name="itemNumber" placeholder="Item Number">
</div>
<div class="form-group col-md-4 font-weight-bold">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Name">
</div>
</div>
<!-- Row 1 -->
<!-- Row 2 -->
<div class="form-row">
<div class="form-group col-lg-12 font-weight-bold">
<label for="description">Description</label>
<input type="text" class="form-control" id="description" name="description" placeholder="Description">
</div>
</div>
<!-- Row 2 -->
<!-- Row 3 -->
<div class="form-row">
<div class="form-group col-md-4 font-weight-bold">
<label for="price">Price</label>
<input type="number" class="form-control" id="price" name="price" placeholder="$00.00">
</div>
<div class="form-group col-md-4 font-weight-bold">
<label for="markedDown">Marked Down</label>
<input type="number" class="form-control" id="markedDown" name="markedDown" placeholder="$00.00">
</div>
<div class="form-group col-md-4 font-weight-bold">
<label for="pricePaid">Price Paid</label>
<input type="number" class="form-control" id="pricePaid" name="pricePaid" placeholder="$0.00">
</div>
</div>
<!-- Row 3 -->
<!-- Row 4 -->
<div class="form-row">
<div class="form-group col-sm-6 font-weight-bold">
<label for="categories">Categories</label>
<div class="form-check form-check-inline">
<select name="categories">
<option value="media">Media</option>
<option value="tools">Tools</option>
<option value="clothes">Clothes</option>
<option value="bears">Bears</option>
<option value="misc">Misc</option>
<option value="electronics">Electronics</option>
</select>
<div class="form-group col-sm-6 font-weight-bold">
<p>Sold</p>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="sold" id="true" value="true">
<label class="form-check-label" for="true">True</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="sold" id="false" value="false">
<label class="form-check-label" for="false">False</label>
</div>
</div>
<div class="form-group col-sm-6 font-weight-bold">
<p>Posted Online</p>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="postedOnline" id="true" value="true">
<label class="form-check-label" for="true">True</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="postedOnline" id="false" value="false">
<label class="form-check-label" for="false">False</label>
</div>
</div>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary btn-block">Submit</button>
</form>
<div id="output"></div>
</div>
</div>
</div>
</body>
</html>
JavaScript.html
<script>
// Prevent forms from submitting.
function preventFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener('load', preventFormSubmit);
function handleFormSubmit(formObject) {
google.script.run.processForm(formObject);
document.getElementById("myForm").reset();
}
</script>
I was able to run the code but with few corrections.
In app script, inside the pocessForm() function you are again declaring a new function with the same name, which is unnecessary and your code does not run because of this. So you should remove the outer function and just keep inner one.
When you deploy your app, the activeSheet function does not work. Instead, use
SpreadsheetApp.openById("")
and give the id of the spreadsheet which you can find in the link of the spreadsheet. These will be the alphanumeric character string. For your sheet it's this - "1uF5YBKyfVxvrA4QrUuRqHrxe7C1qEySIxAL_r-PkBIQ".
function doGet(request) {
return HtmlService.createTemplateFromFile('Index').evaluate();
}
/* #Include JavaScript and CSS Files */
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
/* #Process Form */
function processForm(formObject) {
Logger.log(JSON.stringify(formObject));
// var ss = SpreadsheetApp.getActive(); // incorrect
const ss = SpreadsheetApp.openById("");
const ws = ss.getSheetByName('Data');
ws.appendRow([formObject.location,
formObject.itemNumber,
formObject.name,
formObject.description,
formObject.price,
formObject.markedDown,
formObject.pricePaid,
formObject.category,
formObject.sold,
formObject.postedOnline]);
}
And this works.
Suggestion - You may want to handle the form validation. Currently, if a user submits the form with any empty field, app script throws error. Easy way to handle this is by making each input field required in html.

Not able to get invalid feedback message for input field Bootstrap 5 validation

I have created a simple form page for people to submit change requests and am struggling to get the invalid validation working for the input field where type="file".
I have written a function to run the object through custom validation (similar to how I handle Email validation), but I never receive the red outline and error message like I do for email. I am logging my "Not valid" message successfully when I try to upload more than 5 files, but still receive a green outline and the valid message on the input.
I think I've tried so much at this point I'm just confusing myself. I was able to get both valid and invalid messages at one point, but nothing beyond that.
I am trying to avoid validating every input individually if possible.
Thanks for any help in advance!
<!DOCTYPE html>
<html lang="en" class="vh-100">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="" />
<meta name="author" content="AWright" />
<link rel="icon" href="##URL_FAV_ICON##" />
<title>Change Request Form</title>
<!-- Bootstrap 5 CSS -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous"
/>
<!-- /Bootstrap 5 CSS-->
<!-- Axios Library -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- /Axios Library -->
<style></style>
<script src="https://cdn.jsdelivr.net/npm/vue#3.0.11"></script>
</head>
<body>
<div id="awApp" class="d-flex flex-column vh-100">
<!-- FIXED NAVBAR AND/OR HEADER -->
<header>
<nav
class="navbar navbar-expand-md navbar-light fixed-top bg-light"
></nav>
</header>
<!-- / HEADER/NAVBAR -->
<!-- MAIN CONTENT -->
<main role="main" class="flex-shrink-0">
<div class="container">
<div class="row mt-5 pt-5">
<div class="col-md-8 offset-md-2">
<h2 class="mt-5 text-center" style="font-size: 3rem">
Program Change Request Form
</h2>
<p class="text-center">
Please complete the below form to submit your program change
request:
</p>
</div>
</div>
<div class="row">
<div class="col-md-6 offset-md-3">
<div class="card shadow p-3 my-5">
<div class="card-body">
<form
novalidate
class="needs-validation"
name="mainForm"
#submit="submitForm"
method="post"
ref="requestForm"
>
<div class="row mb-2">
<div class="col-md-6 mb-3">
<label for="firstname" class="form-label mb-0"
>First Name*</label
>
<input
id="firstname"
type="text"
name="firstname"
class="form-control"
v-model="contact.firstName"
required
/>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please enter a first name.
</div>
</div>
<div class="col-md-6 mb-3">
<label for="lastname" class="form-label mb-0"
>Last Name*</label
>
<input
id="lastname"
type="text"
name="lastname"
class="form-control"
v-model="contact.lastName"
required
/>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please enter a last name.
</div>
</div>
</div>
<div class="row mb-3">
<div class="col">
<label for="email" class="form-label mb-0"
>Email Address*</label
>
<input
id="email"
type="text"
name="email"
class="form-control"
v-model="contact.email"
pattern="\b[a-zA-Z0-9._%-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,100}\b"
required
/>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please enter a valid email.
</div>
</div>
</div>
<div class="row mb-3">
<div class="col">
<label for="name" class="form-label mb-0"
>Name of Request*</label
>
<input
id="name"
type="text"
name="RequestName"
class="form-control"
v-model="contact.name"
required
/>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please enter a name for the change request being made.
</div>
</div>
</div>
<div class="row mb-3">
<div class="col">
<label for="description" class="form-label mb-0"
>Description of Request*</label
>
<textarea
id="description"
type="text"
name="RequestDetails"
class="form-control"
v-model="contact.description"
required
></textarea>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please enter a description for the request being made.
</div>
</div>
</div>
<div class="row mb-3">
<div class="col">
<label for="due_date" class="form-label mb-0"
>Estimated Due Date*</label
><br />
<em
><small
>Please note that this subject to change.</small
></em
>
<input
id="due_date"
type="text"
name="CompletionDate"
class="form-control"
v-model="contact.dueDate"
v-maska="dateMask"
required
/>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please enter a desired due date for the change request
in MM/dd/yyyy format.
</div>
</div>
</div>
<div class="row mb-3">
<div class="col">
<label for="files" class="form-label mb-0"
>Please attach any assets (images, font files, etc)
here to upload*:</label
><br />
<small
><em
>*Maximum of 5 files can be uploaded at a time</em
></small
>
<input
type="file"
class="form-control"
id="files"
name="files"
#change="handleFilesUpload( $event )"
multiple
/>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please do not upload more than 5 files at a time.
</div>
</div>
</div>
<button
type="submit"
class="btn btn-primary px-4 py-2"
value="Submit"
>
Submit
</button>
<div>
<small class="form-text text-muted">
<em>* Denotes a required field.</em>
</small>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</main>
<!-- /MAIN CONTENT -->
</div>
<!--Bootstrap 5 JS-->
<script
src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"
></script>
<!--/Bootstrap 5 JS-->
<!-- Maska JS -->
<script src="https://cdn.jsdelivr.net/npm/maska#latest/dist/maska.js"></script>
<!-- /Maska JS -->
<!-- VUE APP CODE -->
<script>
const app = Vue.createApp({
data() {
return {
currentYear: new Date().getFullYear(),
now: new Date().toISOString(),
contact: {
firstName: "##firstname##",
lastName: "##lastname##",
email: "##email##",
name: "",
description: "",
dueDate: "",
},
files: "",
};
},
methods: {
submitForm(e) {
const isValid =
this.contact.firstName &&
this.contact.lastName &&
this.contact.email &&
this.contact.name &&
this.contact.description &&
this.contact.dueDate &&
this.validEmail(this.contact.email) &&
this.files.length <= 5 &&
this.multipleFilesValidation(this.files);
e.target.classList.add("was-validated");
if (!isValid) {
e.preventDefault();
console.log("Not valid");
} else {
e.preventDefault();
this.postToZapier();
console.log("Success");
}
},
multipleFilesValidation: function (files) {
if (this.files.length > 5) {
console.log(this.files);
return false;
} else {
return true;
}
},
handleFilesUpload(event) {
this.files = event.target.files;
},
postToZapier() {
console.log(this.files);
var formData = new FormData();
for (var i = 0; i < this.files.length; i++) {
let file = this.files[i];
formData.append("files[" + i + "]", file);
}
console.log(formData);
var url = "https://hooks.zapier.com/hooks/catch/159749/b9h6kww/";
var requestForm = this.$refs.requestForm;
console.log(requestForm);
axios
.post(url, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then(function () {
console.log("Success!");
setTimeout(function () {
requestForm.submit();
}, 0);
})
.catch(function () {
console.log("Fail.");
});
},
validEmail: function (email) {
const re = /\b[a-zA-Z0-9._%-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,100}\b/;
return re.test(email);
},
},
computed: {
dateMask: function () {
return "##/##/####";
},
},
});
app.directive("maska", Maska.maska);
app.mount("#awApp");
</script>
<!-- /VUE APP CODE-->
</body>
</html>

how to deal with fields outside of form tag

Here is my code.
In this code, as you can see, there is no form tag wrapping around fields.
but somehow it can process fields. from my understanding, I always thought that fields are needed to be wrapped around form tag. How come this works?
Would anyone can explain this to me please? Thank you.
<form role="form" method="post">
<input type='hidden' name='bno' value="${boardVO.bno}">
</form>
<div class="box-body">
<div class="form-group">
<label for="exampleInputEmail1">Title</label> <input type="text"
name='title' class="form-control" value="${boardVO.title}"
readonly="readonly">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Content</label>
<textarea class="form-control" name="content" rows="3"
readonly="readonly">${boardVO.content}</textarea>
</div>
<div class="form-group">
<label for="exampleInputEmail1">Writer</label> <input type="text"
name="writer" class="form-control" value="${boardVO.writer}"
readonly="readonly">
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<button type="submit" class="btn btn-warning">Modify</button>
<button type="submit" class="btn btn-danger">REMOVE</button>
<button type="submit" class="btn btn-primary">LIST ALL</button>
</div>
<script>
$(document).ready(function(){
var formObj = $("form[role='form']");
console.log(formObj);
$(".btn-warning").on("click", function(){
formObj.attr("action", "/board/modify");
formObj.attr("method", "get");
formObj.submit();
});
$(".btn-danger").on("click", function(){
formObj.attr("action", "/board/remove");
formObj.submit();
});
$(".btn-primary").on("click", function(){
self.location = "/board/listAll";
});
});

Bootstrap 4 DatePicke issue

I am using bootstrap 4, jQuery 3.3.1 and datepicker (http://www.eyecon.ro/bootstrap-datepicker/)
I have three issues:
The Calendar icon is not the size of the input box
When submit without selecting the date, bootstrap validation message not working.
Auto close is not working.
$(document).ready(function()
{
$('#depositeDate').datepicker({
"setDate": new Date(),
"autoclose": true
});
})
<div class="form-group row">
<label for="depositeDate" class="col-sm-4 col-form-label col-form-label-lg">Deposit Date</label>
<div class="col-sm-2 input-group date">
<input type="text" class=" text-input form-control" id ="depositeDate" placeholder="MM/DD/YYYY">
<div class="input-group-addon">
<i class="fas fa-calendar-alt fa-3x" style="color:RED"></i> </div>
<div class="invalid-feedback">
Please enter a valid Order Number.
</div>
</div>
</div>
The Calendar icon is not the size of the input box
The markup for input group addon is changed in Bootstrap 4.0 stable
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Recipient's username" aria-label="Recipient's username" aria-describedby="basic-addon2">
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">#example.com</span>
</div>
</div>
Your code should be
<div class="input-group date" >
<input type="text" class="form-control" id ="depositeDate" placeholder="MM/DD/YYYY">
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2"><span class="fa fa-calendar"></span></span>
</div>
</div>
3.Auto close is not working.
I don't see setting like "autoclose": true , we should explicitly call to close the datepicker.
.on('changeDate', function(ev) {
checkout.hide();
})
<div class="form-group row justify-content-center align-items-center">
<label for="depositeDate" class="col-sm-3 col-form-label">Deposit Date</label>
<div class="col-sm-3 input-group date" >
<input type="text" class="text-input form-control" id ="depositeDate" placeholder="MM/DD/YYYY">
<div class="input-group-addon" style="cursor: pointer;" onclick="$('#depositeDate').focus();">
<i class="fas fa-calendar-alt fa-2x"></i>
</div>
</div>
</div>
this code will do:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.7.14/js/bootstrap-datetimepicker.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.7.14/css/bootstrap-datetimepicker.min.css">
<br>
<div class="container">
<div class="row">
<div class='col-sm-6'>
<div class="form-group">
<label for="Order number">Order number</label>
<input type="text" id="Order number" >
</div>
<div class="form-group">
<div class='input-group date' id='datetimepicker1'>
<label for="male">Deposit Date</label>
<input type='text' class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
</div>
</div>
<script>$(function() {
$('#datetimepicker1').datetimepicker();
});</script>
check out the fiddle:https://jsfiddle.net/rqy7L2do/