Form data and file does not upload to Google spreadsheet? - forms

The below code had worked for the first 4 input fields and also upload files to the spreadsheet. For the first time, it uploaded data and file to the spreadsheet but when I added more input fields into the form I also customized the code.gs but it does not work. when I submit it stay in uploading state and do not sends data to the spreadsheet.
code.gs
var SHEET_NAME = "Sheet1";
var SCRIPT_PROP = PropertiesService.getScriptProperties(); // new property service
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('forms.html').setTitle("Registration With Document");
}
function uploadFileToGoogleDrive(data, file, code, issues, item, description, problem, defect,
solution, notes) {
try {
var dropbox = "Received Files";
var folder=DriveApp.getFolderById('1xqpdunLg-ygxOxwJvEHjScNhIT2qVgsF');
var contentType = data.substring(5,data.indexOf(';')),
bytes = Utilities.base64Decode(data.substr(data.indexOf('base64,')+7)),
blob = Utilities.newBlob(bytes, contentType, file),
file = folder.createFolder([name, email].join(" ")).createFile(blob),
filelink=file.getUrl() ;
var lock = LockService.getPublicLock();
lock.waitLock(30000);
var doc = SpreadsheetApp.openById("1Diy70efaCR8Po5drNNZ5_AcJ_nQEJP37_CMSLXlxLQs");
var sheet = doc.getSheetByName(SHEET_NAME);
var headRow = 1;
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var nextRow = sheet.getLastRow()+1; // get next row
var row = [];
for (i in headers){
if (headers[i] == "Timestamp"){ // special case if you include a 'Timestamp' column
row.push(new Date());
} else if (headers[i] == "code"){
row.push(code);
} else if (headers[i] == "issues"){
row.push(issues);
} else if (headers[i] == "item"){
row.push(item);
} else if (headers[i] == "description"){
row.push(description);
} else if (headers[i] == "problem"){
row.push(problem);
} else if (headers[i] == "defect"){
row.push(defect);
} else if (headers[i] == "solution"){
row.push(solution);
} else if (headers[i] == "notes"){
row.push(notes);
} else if (headers[i] == "filelink"){
row.push(filelink);
}
}
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
return "OK";
} catch (f) {
return f.toString();
} finally { //release lock
lock.releaseLock();
}
}
function setup() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
SCRIPT_PROP.setProperty("1Diy70efaCR8Po5drNNZ5_AcJ_nQEJP37_CMSLXlxLQs", doc.getId());
}
forms.html
<!DOCTYPE html>
<html>
<head>
<base target="_blank">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Registration</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
<style>
.disclaimer{width: 480px; color:#646464;margin:20px auto;padding:0 16px;text-align:center;font:400
12px Roboto,Helvetica,Arial,sans-serif}.disclaimer a{color:#009688}#credit{display:none}
</style>
</head>
<body>
<form class="main" id="form" novalidate="novalidate" style="max-width: 480px;margin: 40px auto;">
<div id="forminner">
<div class="row">
<div class="col s12
<h5 class="center-align teal-text">Repair/Issue Form</h5>
<p class="disclaimer">Fill up all fields.</p>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input id="code" type="text" name="Date Code" class="validate" required="" aria-required="true">
<label for="code">Date Code</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input id="issues" type="text" name="Reported Issues" class="validate" required="" aria-
required="true">
<label for="issues">Reported Issues</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input id="item" type="text" name="Item Number" class="validate" required="" aria-required="true">
<label for="item">Item Number</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input id="description" type="text" name="Description" class="validate" required="" aria-
required="true">
<label for="description">Description</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input id="problem" type="text" name="Problem" class="validate" required="" aria-required="true">
<label for="problem">Problem</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input id="defect" type="text" name="Frequency of Defect" class="validate" required="" aria-
required="true">
<label for="defect">Frequency of Defect</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input id="solution" type="text" name="Possible Issues" class="validate" required="" aria-
required="true">
<label for="solution">Possible Issues</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input id="notes" type="text" name="Notes" class="validate" required="" aria-required="true">
<label for="notes">Notes</label>
</div>
</div>
<div class="row">
<div class="file-field input-field col s12">
<div class="btn">
<span>File</span>
<input id="files" type="file">
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" placeholder="Select a file on your computer">
</div>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<button class="waves-effect waves-light btn submit-btn" type="submit" onclick="submitForm(); return
false;">Submit</button>
</div>
</div>
<div class="row">
<div class="input-field col s12" id = "progress">
</div>
</div>
</div>
<div id="success" style="display:none">
<h5 class="left-align teal-text">File Uploaded</h5>
<p>Your file has been successfully uploaded.</p>
<p class="center-align"><a class="btn btn-large" onclick="restartForm()" >Restart</a></p>
</div>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/js/materialize.min.js">
</script>
<script>
var file, reader = new FileReader();
reader.onloadend = function(e) {
if (e.target.error != null) {
howError("File " + file.name + " could not be read.");
return;
} else {
google.script.run
.withSuccessHandler(showSuccess)
.uploadFileToGoogleDrive(e.target.result, file.name, $('input#code').val(),
$('input#issues').val(), $('input#item').val(), $('input#description').val()),
$('input#problem').val(), $('input#defect').val(), $('input#solution').val(),
$('input#notes').val();
}
};
function showSuccess(e) {
if (e === "OK") {
$('#forminner').hide();
$('#success').show();
} else {
showError(e);
}
}
function restartForm() {
$('#form').trigger("reset");
$('#forminner').show();
$('#success').hide();
$('#progress').html("");
}
function submitForm() {
var files = $('#files')[0].files;
if (files.length === 0) {
showError("Please select a file to upload");
return;
}
file = files[0];
if (file.size > 1024 * 1024 * 5) {
showError("The file size should be < 5 MB. ");
return;
}
showMessage("Uploading file..");
reader.readAsDataURL(file);
}
function showError(e) {
$('#progress').addClass('red-text').html(e);
}
function showMessage(e) {
$('#progress').removeClass('red-text').html(e);
}
$(document).ready(function() {
$('select').material_select();
});
</script>
</body>
</html>

I have not looked at the rest of the code but there is a misplaced parenthesis
change for that :
{
google.script.run
.withSuccessHandler(showSuccess)
.uploadFileToGoogleDrive(e.target.result, file.name, $('input#code').val(),
$('input#issues').val(), $('input#item').val(), $('input#description').val(),
$('input#problem').val(), $('input#defect').val(), $('input#solution').val(),
$('input#notes').val());
}

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>

VueJS form item json post

I have a form and when the "new iban" button is clicked in this form, he can add as many "iban" inputs as he wants.
in the same way, when the "add item" button is clicked, as many entries can be added and "SPINNET" can be seen. But when I post them, the input values ​​return empty. I want it to be sent in "iban" and "authoritative" json format.
new Vue({
el: "#app",
data() {
return {
data: {
name: "",
iban: "",
yetkili: "",
},
sections: [{
ibans: [{
item: ""
}]
}],
yetkisection: [{
yetkililer: [{
yetkiliadi: "",
yetkilieposta: "",
yetkilitelefon: "",
yetkilinotu: "",
}]
}],
}
},
methods: {
addNewItem(id) {
this.sections[id].ibans.push({
item: ''
});
},
removeItem(sectionIndex, ibanIndex) {
this.sections[sectionIndex].ibans.splice(ibanIndex, 1);
},
addNewYetkili(id) {
this.yetkisection[id].yetkililer.push({
yetkiliadi: ''
});
},
removeYetkili(sectionIndex, ibanIndex) {
this.yetkisection[sectionIndex].yetkililer.splice(ibanIndex, 1);
},
async addTag() {
const res = await this.callApi('post', 'app/create_musteri', this.data)
if (res.status === 200) {
console.log(res)
} else {
console.log("error");
}
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<template>
<div class="container">
<div class="col-12">
<div class="mb-1 row">
<div class="col-sm-3">
<label class="col-form-label"><span><i data-feather='file-text'></i></span>NAME</label>
</div>
<div class="col-sm-6">
<input type="text" class="form-control" placeholder="Item" v-model="data.name">
</div>
</div>
</div>
<div class="col-12 sections" v-for="(section, sectionIndex) in sections">
<div class="mb-1 row" v-for="(iban, ibanIndex) in section.ibans">
<div class="col-sm-3">
<label class="col-form-label" for="iban"><span><i data-feather='file-text'></i></span>IBAN NUMBER</label>
</div>
<div class="col-sm-6">
<input type="text" class="form-control" placeholder="Item" v-model="iban.item">
<span v-if="section.ibans.length>1"
class="float-right" style="cursor:pointer" #click="removeItem(sectionIndex, ibanIndex)">X</span>
</div>
</div>
<button class="btn btn-success mt-5 mb-5" #click="addNewItem(sectionIndex)">New Iban</button>
</div>
<div>
<div>
<table class="fatura-table">
<colgroup>
<col style="width: 25%;;">
<col style="width: 25%;;">
<col style="width: 25%;;">
<col style="width: ;">
<col style="width: 70px;">
</colgroup>
<thead>
<tr>
<th>YETKİLİ KİŞİNİN ADI</th>
<th>E-POSTA</th>
<th>TELEFON</th>
<th>NOTLAR</th>
<th></th>
</tr>
</thead>
</table>
</div>
<section v-for="(section, sectionIndex) in yetkisection">
<div class="card-body" v-for="(yetkili, ibanIndex) in section.yetkililer">
<div class="row">
<div class="col-sm-3 col-12 mb-1 mb-sm-0 hizmet">
<div class="form-floating">
<input type="text" class="form-control" v-model="yetkili.yetkiliadi" placeholder=" "/>
<label>YETKİLİ KİŞİNİN ADI</label>
</div>
</div>
<div class="col-sm-3 col-12 mb-1 mb-sm-0 hizmet">
<div class="form-floating">
<input type="text" class="form-control" v-model="yetkili.yetkilieposta" placeholder=" "/>
<label>E-POSTA</label>
</div>
</div>
<div class="col-sm-2 col-12 mb-1 mb-sm-0 hizmet">
<div class="form-floating">
<input type="text" class="form-control" v-model="yetkili.yetkilitelefon" placeholder=" "/>
<label>TELEFON</label>
</div>
</div>
<div class="col-sm-3 col-12 mb-1 mb-sm-0 hizmet">
<div class="form-floating">
<input type="text" class="form-control" v-model="yetkili.yetkilinotu" placeholder=" "/>
<label>NOTLAR</label>
</div>
</div>
<div class="col-sm-1 col-12 mb-1 mb-sm-0">
<button class="btn btn-icon btn-secondary waves-effect waves-float waves-light" #click="removeYetkili(sectionIndex, ibanIndex)">
<i data-feather='x'>DELETE</i>
</button>
</div>
</div>
</div>
<div class="mt-1">
<div class="col-12 px-0">
<button type="button" class="btn btn-primary btn-sm btn-add-new" data-repeater-create #click="addNewYetkili(sectionIndex)">
<i data-feather="plus" class="me-25"></i>
<span class="align-middle">Add Item</span>
</button>
</div>
</div>
</section>
</div>
<button #click="addTag" class="btn btn-dark data-submit">SAVE</button>
</div>
</template>
</div>
Edited my answer to handle your new build and structure.
Showing both the approaches below:
new Vue({
el: "#app",
data() {
return {
data: {
name: "",
iban: "",
yetkili: ""
},
sections: [{ item: "" }],
yetkisections: [
{
yetkiliadi: "",
yetkilieposta: "",
yetkilitelefon: "",
yetkilinotu: ""
}
]
};
},
methods: {
addNewItem() {
this.sections.push({ item: "" });
},
removeItem(sectionIndex) {
this.sections.splice(sectionIndex, 1);
},
addNewYetkili() {
this.yetkisections.push({ yetkiliadi: "" });
},
removeYetkili(yetkisectionIndex) {
this.yetkisections.splice(yetkisectionIndex, 1);
},
async addTag() {
/* const res = await this.callApi('post', 'app/create_musteri', this.formData)
if (res.status === 200) {
console.log(res)}
else {
console.log("error");
} */
console.log(this.$data);
console.log(this.formData);
}
},
computed: {
formData() {
return {
data: {
...this.data,
sections: this.sections,
yetkisection: this.yetkisections
}
};
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<template>
<div class="container">
<div class="col-12">
<div class="mb-1 row">
<div class="col-sm-3">
<label class="col-form-label"
><span><i data-feather="file-text"></i></span>NAME</label
>
</div>
<div class="col-sm-6">
<input
type="text"
class="form-control"
placeholder="Item"
v-model="data.name"
/>
</div>
</div>
</div>
<div
class="col-12 sections"
v-for="(section, sectionIndex) in sections"
:key="sectionIndex"
>
<div class="col-sm-3">
<label class="col-form-label" for="iban"
><span><i data-feather="file-text"></i></span>IBAN NUMBER</label
>
</div>
<div class="col-sm-6">
<input
type="text"
class="form-control"
placeholder="Item"
v-model="section.item"
/>
<span
v-if="sections.length > 1"
class="float-right"
style="cursor: pointer"
#click="removeItem(sectionIndex)"
>X</span
>
</div>
</div>
<button class="btn btn-success mt-5 mb-5" #click="addNewItem()">
New Iban
</button>
<div>
<div>
<table class="fatura-table">
<colgroup>
<col style="width: 25%;;" />
<col style="width: 25%;;" />
<col style="width: 25%;;" />
<col style="width: ;" />
<col style="width: 70px;" />
</colgroup>
<thead>
<tr>
<th>YETKİLİ KİŞİNİN ADI</th>
<th>E-POSTA</th>
<th>TELEFON</th>
<th>NOTLAR</th>
<th></th>
</tr>
</thead>
</table>
</div>
<section>
<div
class="card-body"
v-for="(yetkili, yetkisectionIndex) in yetkisections"
:key="yetkisectionIndex"
>
<div class="row">
<div class="col-sm-3 col-12 mb-1 mb-sm-0 hizmet">
<div class="form-floating">
<input
type="text"
class="form-control"
v-model="yetkili.yetkiliadi"
placeholder=" "
/>
<label>YETKİLİ KİŞİNİN ADI</label>
</div>
</div>
<div class="col-sm-3 col-12 mb-1 mb-sm-0 hizmet">
<div class="form-floating">
<input
type="text"
class="form-control"
v-model="yetkili.yetkilieposta"
placeholder=" "
/>
<label>E-POSTA</label>
</div>
</div>
<div class="col-sm-2 col-12 mb-1 mb-sm-0 hizmet">
<div class="form-floating">
<input
type="text"
class="form-control"
v-model="yetkili.yetkilitelefon"
placeholder=" "
/>
<label>TELEFON</label>
</div>
</div>
<div class="col-sm-3 col-12 mb-1 mb-sm-0 hizmet">
<div class="form-floating">
<input
type="text"
class="form-control"
v-model="yetkili.yetkilinotu"
placeholder=" "
/>
<label>NOTLAR</label>
</div>
</div>
<div class="col-sm-1 col-12 mb-1 mb-sm-0">
<button
class="btn btn-icon btn-secondary waves-effect waves-float waves-light"
#click="removeYetkili(yetkisectionIndex)"
>
<i data-feather="x">DELETE</i>
</button>
</div>
</div>
</div>
<div class="mt-1">
<div class="col-12 px-0">
<button
type="button"
class="btn btn-primary btn-sm btn-add-new"
data-repeater-create
#click="addNewYetkili()"
>
<i data-feather="plus" class="me-25"></i>
<span class="align-middle">Add Item</span>
</button>
</div>
</div>
</section>
</div>
<button #click="addTag" class="btn btn-dark data-submit">SAVE</button>
</div>
</template>
</div>

Angular refresh page after disable DOM field form

I click Buy radio button, images upload field will be removed, but when i click submit, the page refresh. It works normally when I don't affect DOM
Please, explain me what happened ?
Here is my code
onSubmitPost() {
this.progress = true;
const fileList: FileList = this.event.target.files;
if (fileList.length > 0) {
const fileListLength = fileList.length;
const formData: FormData = new FormData();
formData.append('title', this.title);
formData.append('telephone', this.telephone);
formData.append('description', this.description);
formData.append('city', this.city);
if (this.isSell === true) {
for (let x = 0; x < fileListLength; x++) {
formData.append('thumbnail', fileList[x]);
}
}
const headers = new Headers();
headers.append('Accept', 'application/json');
headers.append('Authorization', 'clientId 7702919f7e72965');
this.http
.post('http://localhost:3000/api/post', formData, {
headers: headers
})
.map(res => res.json())
.subscribe(
data => {
this.Notificationervice.success('Success');
this.progress = false;
},
error => this.Notificationervice.error('Something wrong')
);
}
}
}
HTML Code
<div id="new-post" class="modal" materialize="modal">
<div class="modal-content">
<div class="row">
<form class="col s12" (submit)="onSubmitPost()" enctype="multipart/form-data">
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">web</i>
<input id="icon_prefix" type="text" class="validate" name="title" [(ngModel)]="title">
<label for="icon_prefix">Title</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">phone</i>
<input id="icon_telephone" type="tel" class="validate" name="telephone" [(ngModel)]="telephone">
<label for="icon_telephone">Telephone</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">mode_edit</i>
<textarea id="icon_prefix2" class="materialize-textarea" [(ngModel)]="description" name="description"></textarea>
<label for="icon_prefix2">Description</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">location_on</i>
<input type="text" id="autocomplete-input" class="autocomplete" materialize="autocomplete" [materializeParams]="[{'data': {'houston': null, 'Cali': null}}]"
[(ngModel)]="city" name="city">
<label for="autocomplete-input">City</label>
</div>
</div>
<div class="row">
<div class="col s6">
<p>
<input name="isSell" type="radio" id="buy" (change)="isSell = !isSell" [checked]="!isSell" />
<label for="buy">Buy</label>
</p>
</div>
<div class="col s6">
<p>
<input name="isSell" type="radio" id="sell" (change)="isSell = !isSell" [checked]="isSell" />
<label for="sell">Sell</label>
</p>
</div>
</div>
<div class="file-field input-field" *ngIf="isSell">
<div class="btn">
<span>Images</span>
<input type="file" multiple accept='image/*' name="post" (change)="onChange($event)">
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" placeholder="Upload one or more files">
</div>
</div>
<div class="modal-footer">
<input type="submit" class="modal-action modal-close waves-effect waves-green btn-flat" value="Submit">
</div>
</form>
</div>
</div>
</div>