How to pass form data to GAS - javascript

I am trying to pass data from a form into a Google Apps Script but when I press submit I am greeted by I blank screen.
Form:
<div id="nameDiv">
<form action="https://script.google.com/a/umbc.edu/macros/s/AKfycbztum1ImJZeXXYt0fFhwOAMUsB5zCsJQohrum4W7qiH/dev">
<label for="fname">First Name</label>
<input type="text" id="fname" name="firstname">
<label for="lname">Last Name</label>
<input type="text" id="lname" name="lastname" >
<input type="submit" value="Submit" onclick="google.script.run.nameSearch()">
</form>
</div>
Script:
function nameSearch(){
try {
var firstName = document.getElementById("fname").value
var lastName = document.getElementById("lname").value
var inputSheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1z3j7wxMLsXilyKDIH7XnE7VNQqF66fIH4B-mmuWwCJ8/edit#gid=1235654559");
var inputData = inputSheet.getDataRange().getValues();
for (var i = 1; i < inputData.length; i++) {
if (inputData[i][10] == firstName && inputData[i][11] == lastName) {
var result = inputData[i][14] + ": " + inputData[i][15]
}
}
document.getElementById('nameDiv').innerHTML =
"<center>Last Name:" + lastName + "</center>" +
"</br><center>First Name:" + firstName + "</center>"
} catch(e) {
alert(e)
}
}
I am trying to pass this data to the script so that it can use it to search a google sheet so I cannot just place the script in the html as a client side script. Any thought?

All the HTML-related methods (getElementById, innerHTML, etc.) should be in client-side script, and Apps Script methods should be in the server-side.
If I understand you correctly, you want to do the following:
When this form gets submitted, look for the row whose columns K and L match the inputted fields (indexes 10 and 11 from inputData array).
For this row, return data from columns O and P (indexes 14 and 15 from inputData array).
Write this returned data to the HTML.
If all this is correct, then you could do this:
Add an onclick event in the submit input that will fire a client-side function (a function that is declared inside the tags in the HTML). There is no need to use a for this. The HTML body could be something like this:
<div id="nameDiv">
<label for="fname">First Name</label>
<input type="text" id="fname" name="firstname">
<label for="lname">Last Name</label>
<input type="text" id="lname" name="lastname" >
<input type="submit" value="Submit" onclick="clientNameSearch()">
</div>
From this client-side function called clientNameSearch(), retrieve the values from fname and lname, and use these as parameters when you call a server-side function called nameSearch):
function clientNameSearch() {
var firstName = document.getElementById("fname").value;
var lastName = document.getElementById("lname").value;
google.script.run.withSuccessHandler(onSuccess).nameSearch(firstName, lastName);
}
This server-side function iterates through all rows with content in the spreadsheet, and returns the result for the first row whose columns K and L match the inputted data:
function nameSearch(firstName, lastName){
try {
var inputSheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1z3j7wxMLsXilyKDIH7XnE7VNQqF66fIH4B-mmuWwCJ8/edit#gid=1235654559");
var inputData = inputSheet.getDataRange().getValues();
for (var i = 1; i < inputData.length; i++) {
if (inputData[i][10] == firstName && inputData[i][11] == lastName) {
var result = inputData[i][14] + ": " + inputData[i][15];
return result;
}
}
} catch(e) {
alert(e)
}
}
This result is then passed as a parameter to a client-side function called onSuccess via a success handler. This is necessary since server-side functions called by google.script.run don't return anything directly, as specified here. Then onSuccess writes the result to the HTML:
function onSuccess(result) {
document.getElementById('nameDiv').innerHTML = "<div>" + result + "</div>";
}
Full code:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div id="nameDiv">
<label for="fname">First Name</label>
<input type="text" id="fname" name="firstname">
<label for="lname">Last Name</label>
<input type="text" id="lname" name="lastname" >
<input type="submit" value="Submit" onclick="clientNameSearch()">
</div>
</body>
<script>
function clientNameSearch() {
var firstName = document.getElementById("fname").value;
var lastName = document.getElementById("lname").value;
google.script.run.withSuccessHandler(onSuccess).nameSearch(firstName, lastName);
}
function onSuccess(result) {
document.getElementById('nameDiv').innerHTML = "<div>" + result + "</div>";
}
</script>
</html>
And the Code.gs would be like:
function nameSearch(firstName, lastName){
try {
var inputSheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1z3j7wxMLsXilyKDIH7XnE7VNQqF66fIH4B-mmuWwCJ8/edit#gid=1235654559");
var inputData = inputSheet.getDataRange().getValues();
for (var i = 1; i < inputData.length; i++) {
if (inputData[i][10] == firstName && inputData[i][11] == lastName) {
var result = inputData[i][14] + ": " + inputData[i][15];
return result;
}
}
} catch(e) {
alert(e)
}
}
function doGet(e) {
return HtmlService.createHtmlOutputFromFile("your-html-name");
}
I'm not sure you want to write the result to the HTML, but in any case, at this point it shouldn't be difficult to modify this so that it writes exactly what you want and where you want.
Reference:
google.script.run.myFunction(...) (any server-side function)
withSuccessHandler(function)
I hope this is of any help.

Try this:
Launch the dialog fill the text boxes and click submit. The view logs and see the next dialog.
function launchADialog() {
var html='<form><br /><input type="text" name="Name" /> Name: <br /><input type="text" name="Age" /> Age: <br />';
html+='<select name="Children" ><option value="0">None</option><option value="1">One</option><option value="2">Two</option></select> Children:<br />';
html+='<input type="button" value="Submit" onClick="google.script.run.processForm(this.parentNode);" /></form>';
var userInterface=HtmlService.createHtmlOutput(html);
SpreadsheetApp.getUi().showModelessDialog(userInterface, "The Form");
}
function processForm(form) {
Logger.log(JSON.stringify(form));
var s=Utilities.formatString('<br />Name: %s <br />Age:%s <br />Number Of Children: %s', form.Name, form.Age, form.Children);
s+='<br /><input type="button" value="Close" onClick="google.script.host.close();" />';
var userInterface=HtmlService.createHtmlOutput(s);
SpreadsheetApp.getUi().showModelessDialog(userInterface, "Form Data")
}

Related

Having trouble getting values from an array of objects in javascript

I am making a program to get user input from HTML forms and compile them into an object for each user. So, I have an HTML form, I make a constructor, then I set up a click event to make the object, then I put it in the variable, and then I am trying to put that variable in an array of objects, before finally using a for loop to get all of the information from each object in this array. However, I am having trouble with that last part (or at least I think). Every time I run the code, the console log does display the message, but it is coming up with undefined rather than the user input. Can someone help please?
function user(firstName, lastName, address) {
user.firstName = firstName;
user.lastName = lastName;
user.address = address;
}
var users = [];
document.addEventListener("submit", function(addUser) {
event.preventDefault();
var newUser = new user(
document.getElementById("userFName").value,
document.getElementById("userLName").value,
document.getElementById("userAdd").value
);
users.push(newUser);
for (let i = 0; i < users.length; i++) {
console.log("User" + (i + 1) + "'s first name is " + users[i].firstName + ", their last name is " + users[i].lastName + ", and their address is " + users[i].address);
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WWW</title>
<style>
</style>
</head>
<body>
<form>
<input id="userFName" placeholder="First Name">
<input id="userLName" placeholder="Last Name">
<input id="userAdd" placeholder="Address">
<button type="submit">Submit</button>
</form>
</body>
</html>
By assigning to user, you're assigning to a property of the constructor, not a property of the instance. new User will mutate the constructor and return an empty object whose internal prototype is user.prototype.
Assign to this instead inside the constructor, to change the instance that gets returned.
function user(firstName, lastName, address) {
this.firstName = firstName;
this.lastName = lastName;
this.address = address;
}
var users = [];
document.addEventListener("submit", function(addUser) {
event.preventDefault();
var newUser = new user(
document.getElementById("userFName").value,
document.getElementById("userLName").value,
document.getElementById("userAdd").value
);
users.push(newUser);
for (let i = 0; i < users.length; i++) {
console.log("User" + (i + 1) + "'s first name is " + users[i].firstName + ", their last name is " + users[i].lastName + ", and their address is " + users[i].address);
}
});
<form>
<input id="userFName" placeholder="First Name">
<input id="userLName" placeholder="Last Name">
<input id="userAdd" placeholder="Address">
<button type="submit">Submit</button>
</form>
Or use a plain object instead of a constructor.
const user = (firstName, lastName, address) => ({
firstName, lastName, address
});
const users = [];
document.addEventListener("submit", function(addUser) {
event.preventDefault();
var newUser = user(
document.getElementById("userFName").value,
document.getElementById("userLName").value,
document.getElementById("userAdd").value
);
users.push(newUser);
for (let i = 0; i < users.length; i++) {
console.log("User" + (i + 1) + "'s first name is " + users[i].firstName + ", their last name is " + users[i].lastName + ", and their address is " + users[i].address);
}
});
<form>
<input id="userFName" placeholder="First Name">
<input id="userLName" placeholder="Last Name">
<input id="userAdd" placeholder="Address">
<button type="submit">Submit</button>
</form>
make your life easier, use names in your forms!
const
myForm = document.querySelector('#my-form')
, users = []
;
myForm.onsubmit = e =>
{
e.preventDefault()
users.push({ firstName: myForm.userFName.value
, lastName : myForm.userLName.value
, address : myForm.userAdd.value
})
console.clear()
users.forEach( (user,i) => console.log(i,JSON.stringify(user)) )
myForm.reset() // clear inputs
myForm.userFName.focus()
}
<form id="my-form">
<input name="userFName" placeholder="First Name" required >
<input name="userLName" placeholder="Last Name" required >
<input name="userAdd" placeholder="Address" required >
<button type="submit">Submit</button>
</form>

How to know what type of variable user enter in JavaScript?

I tried to make a function that receive data from user and combine such data either by concatenation in case of string or by getting the sum as a result if the entered data was integer.
My main problem is that I don't know what what condition in if statement I use to JavaScript act according to data entered by user.
That's my last invented code to solve such problem
function GetFullName() {
var first = document.getElementById('FirstName').value;
var last = document.getElementById('LastName').value;
if (first == "string" || last == "string") {
document.getElementById('FullName').value = first + " " + last;
} else {
var first = parseInt(document.getElementById('FirstName').value);
var last = parseInt(document.getElementById('LastName').value);
document.getElementById('FullName').value = first + last;
}
document.getElementById('FirstName').focus();
}
<form>
First Name <input type="text" id="FirstName" />
Last Name <input type="text" id="LastName" />
<input type="button" value="submit" onclick="GetFullName()" />
<input type="reset" value="reset" />
<br />
Full Name <input type="text" id="FullName" />
</form>
when you get an element's value it will always be a string,
you can check of a variables type by typeof first
for your specific problem if you want to check if the user inputted integers then you will have to use isNaN
if(isNaN("123")) {
} else {
//this executes
}
All in all the new code would be:
if (isNaN(first) || isNaN(last)) {
document.getElementById('FullName').value = first + " " + last;
} else {
document.getElementById('FullName').value = parseInt(first) + parseInt(last);
}

I cannot connect javascript function with html <input> tags and onclick doesn't work

Hi I am working on a website and i stumbbled across an annoying thing. I cannot, for the love of anything, get to work my form to be able to do some maths and insert them into tag.
P.S nothing works for me, even GetElementsById... or other callouts :(
<script type="text/javascript">
function price(this.form){
var amount = form.elements[1].value;
var gold_price = 0.17;
var price_calc = 0;
price_calc = (amount/gold_price) + " M";
window.alert("price_calc");
form.elements[5].value = price_calc;
}
</script>
//this is input that i would like to get a number to work with in the function
<div>
<input type="text" id="amount" value="10" onchange="price(this.form)" onclick="price(this.form)" maxlength="4" required/>
</div>
//this is input I would like to write in in after function is done functioning :)
<input type="text" id="total_price" placeholder="Total:"/>
thanks for any help in advance.
thanks again,...
Declare your price function to receive an input parameter. Actually this.form as parameter is an invalid statement and leads to an error.
Instead pass this (inside your on* property) and select the input value.
// select #total_price
const totalPrice = document.getElementById( 'total_price' );
function price( input ) {
// Convert value to a number
var amount = +input.value;
var gold_price = 0.17;
var price_calc = 0;
price_calc = ( amount / gold_price ) + " M";
totalPrice.value = price_calc;
}
<input type="text" id="amount" value="10" oninput="price( this )" onclick="price( this )" maxlength="4" required/>
<br>
<input type="text" id="total_price" placeholder="Total:" />
This code working:
<input type="text" value="10" oninput="price(this)" maxlength="4" />
<input type="text" id="total_price" placeholder="Total:" />
<script>
function price(el){
var amount = parseInt(el.value);
var gold_price = 0.17;
var price_calc = (amount / gold_price) + " M";
window.alert("Total: " + price_calc);
document.getElementById('total_price').value = "Total: " + price_calc;
}
</script>

Two parameters on a function

I'm trying to make a button onclick event jump to another function if input fields is empty. The function inside the if-statement should have two parameter(one array, one string variable). The function is looping trough all input elements and check if they have a value, if not then add text to a variable that later on is assign to a p-element with .innerHTML.
It worked with only the input parameter, but when I tried to add msg, it stopped working. Maybe it's a simple reason, but I am new to this.
How can I make this work?
var assignment = document.getElementById("assignment");
var inputs = assignment.getElementsByTagName('input');
var btnCreate = document.getElementById("submit");
var message = document.getElementById("message");
var msg = "";
btnCreate.onclick = function() {
if (inputs[0].value === "" || inputs[1].value === "" || inputs[2].value === "") {
emptyInputs(inputs,msg);
}
message.innerHTML = msg;
}
function emptyInputs(input,text) {
for(var i = 0; i < input.length; i++) {
if (input[i].value === "") {
if(!text) {
missing();
}
text += "- " + input[i].name + "<br />";
}
function missing() {
text = "<strong>Please type in:</strong> <br />";
}
}
}
<section id="assignment">
<h1>Add new user</h1>
<form id="newUser">
<div class="inputGroup">
<label for="username">Username</label>
<input type="text" id="username" name="username" />
</div>
<div class="inputGroup">
<label for="password">Password:</label>
<input type="password" id="password" name="password"/>
</div>
<div class="inputGroup">
<label for="passwordConfirm">Confirm password:</label>
<input type="password" id="password2Confirm" name="confirmPassword"/>
</div>
<button id="submit" type="button">Opprett</button>
</form>
<p id="message"></p>
</section>
You were very close to solving your problem. The only thing is, JavaScript doesn't have ouput params.
When you pass an object or array you can modify the content and those changes will be reflect in your calling method. But this doesn't work for strings. Whatever the value of the string is when you use it as a param to call your method, it will still be the value no matter what your method does to it.
var
array = ['hello'],
object = { hello: true },
string = 'hello';
function modifyArray(inputArray) {
inputArray.push('bye');
}
function modifyObject(inputObject) {
inputObject.bye = true;
}
function modifyString(inputString) {
inputString += ', bye';
}
modifyArray(array);
modifyObject(object);
modifyString(string);
// This will print hello and bye
console.log('Content of array after calling method: ', array);
// This will print hello and bye
console.log('Content of object after calling method: ', object);
// This will just print hello
console.log('Content of string after calling method: ', string);
To solve your problem, create a text string inside the method that builds the error message and return that string as the method result.
var assignment = document.getElementById("assignment");
var inputs = assignment.getElementsByTagName('input');
var btnCreate = document.getElementById("submit");
var message = document.getElementById("message");
btnCreate.onclick = function() {
var
// Initialize the error message to an empty string.
msg = '';
// Check if either of the inputs is empty...
if (inputs[0].value === "" || inputs[1].value === "" || inputs[2].value === "") {
// ... and get a custom message prompting the user to fill in the empty data.
msg = emptyInputs(inputs);
}
// Display the error message, or clear it when msg is an empty string.
message.innerHTML = msg;
}
function emptyInputs(input) {
// Initialize the error text.
var
missingPrompt = "<strong>Please type in:</strong> <br />",
text = '';
// Iterate over the provided input elements.
for(var i = 0; i < input.length; i++) {
// Check if the value of the current input is an empty string...
if (input[i].value === "") {
// ... check if the error text is still empty...
if(text === '') {
// ... and if it is start with a default message.
text = missingPrompt;
}
// ... add the field name to the error message.
text += "- " + input[i].name + "<br />";
}
}
// Return the error message.
return text;
}
<section id="assignment">
<h1>Add new user</h1>
<form id="newUser">
<div class="inputGroup">
<label for="username">Username</label>
<input type="text" id="username" name="username" />
</div>
<div class="inputGroup">
<label for="password">Password:</label>
<input type="password" id="password" name="password"/>
</div>
<div class="inputGroup">
<label for="passwordConfirm">Confirm password:</label>
<input type="password" id="password2Confirm" name="confirmPassword"/>
</div>
<button id="submit" type="button">Opprett</button>
</form>
<p id="message"></p>
</section>
Here is the code without msg parameter, and it's working just fine.
var assignment = document.getElementById("assignment");
var inputs = assignment.getElementsByTagName('input');
var btnCreate = document.getElementById("submit");
var message = document.getElementById("message");
var msg = "";
btnCreate.onclick = function() {
msg = "";
if (inputs[0].value === "" || inputs[1].value === "" || inputs[2].value === "") {
emptyInputs(inputs);
}
message.innerHTML = msg;
}
function emptyInputs(input) {
for(var i = 0; i < input.length; i++) {
if (input[i].value === "") {
if(!msg) {
missing();
}
msg += "- " + input[i].name + "<br />";
}
function missing() {
msg = "<strong>Please type in:</strong> <br />";
}
}
}
<section id="assignment">
<h1>Add new user</h1>
<form id="newUser">
<div class="inputGroup">
<label for="username">Username</label>
<input type="text" id="username" name="username" />
</div>
<div class="inputGroup">
<label for="password">Password:</label>
<input type="password" id="password" name="password"/>
</div>
<div class="inputGroup">
<label for="passwordConfirm">Confirm password:</label>
<input type="password" id="password2Confirm" name="confirmPassword"/>
</div>
<button id="submit" type="button">Opprett</button>
</form>
<p id="message"></p>
</section>

Form error message when form contains certain text

I have a form that contains information fields for potential customers. Spammers are entering web addresses in the address field. I want to have an error message when the field contains "http://"
Here is the form code:
<label>First Name:</label> <input id="first_name" name="first_name" type="text" size="20" />
<label>Last Name:</label> <input id="last_name" name="last_name" type="text" size="20" />
<label>Address:</label> <input name="address" type="text" size="30" />
<label>City, State Zip:</label> <input name="city" type="text" size="20" value="City, State Zip"/>
<label>Phone Number:</label> <input name="phone" type="text" size="20" />
<label>Email:</label> <input id="email" name="email" type="text" size="30" />
Here is the error code I have:
function validateForm(){
message = '';
error = 0;
if (document.contact_form.first_name.value == '') {
message = 'First name is a required field\n';
error = 1;
}
if (document.contact_form.last_name.value == '') {
message = message + 'Last name is a required field\n';
error = 1;
}
if (document.contact_form.phone.value == '') {
message = message + 'Phone Number is a required field\n';
error = 1;
}
if (document.contact_form.email.value == '') {
message = message + 'Email is a required field\n';
error = 1;
}
if (WHAT GOES HERE TO SHOW THAT THE FIELD CAN'T CONTAIN ANY VARIATION OF 'http://?') {
message = message + 'That is not a valid address\n';
error = 1;
}
if (error) {
alert(message);
return false;
} else {
return true;
}
}
Use a regular expression.
if (/^http:\/\//.test(document.contact_form.email.value)) {
message = message + 'That is not a valid address\n';
error = 1;
}
I'm assuming you only want to test for http:// at the beginning of the string (just remove ^ if you want to test for it anywhere in the string).
You can use indexOf function as below:
if(document.contact_form.address.value.indexOf("http://") !== -1) {
message = message + "That is not a valid address\n";
error = true;
}
indexOf will return -1 if the value specified in the indexOf function parameter is not found in the string.
References:
http://www.w3schools.com/jsref/jsref_indexof.asp
How to check whether a string contains a substring in JavaScript?
Give your inputs in question a class, maybe something other than what I've done.
give your id's a useful name.
Makes coding a lot easier.
function validate() {
var inputs = document.querySelectorAll('.inputs'),
i = 0;
for (; i < inputs.length; i++) {
if (inputs[i].value == '') {
message = message + ' ' + inputs[i].id + ' is a required field\n';
};
};
};

Categories

Resources