Bad Value, Constant Error - javascript

I am a brand new coder, and I want my code to work with this process:
I fill out a form that leads to a spreadsheet
I want that spreadsheet to check certain values in another spreadsheet to see if they match (there are lots of values in that spreadsheet and I want the program to run through the whole column)
If they match, I want to have an email sent to me with the matching person's name, which is displayed in the same row in the spreadsheet I will be comparing to.
My not working code:
function myFunction(e) {
var genderSheet1 = e.values[19];
var genderSheet2 = SpreadsheetApp.openById("To Populate");
if (genderSheet1===genderSheet2) {
var userName = e.values[1];
var userEmail = "email";
var subject = "WORKER FOUND?";
var message = "Dear " + userName + "," +
"\n\n\nThis is the finder" +
MailApp.sendEmail(userEmail, subject, message, {attachments:file.next().getBlob()});
}
}
Please help!

I will go based on a few assumptions
Your code has an alteration in SpreadsheetApp.openById("To Populate") and To Populate is a real ID in the actual code and not "To Populate" as is written here
You have set a trigger to execute the script on Form submit in the script triggers
I also note that you have not mentioned what the problem is so I will have to point out some of the problems in your code as I see it.
First of all var genderSheet1 = e.values[19]; will be a string value, while var genderSheet2 = SpreadsheetApp.openById("To Populate"); is an object, so if (genderSheet1===genderSheet2) will always return a false.
Then we have this bit MailApp.sendEmail(userEmail, subject, message, {attachments:file.next().getBlob()}) however, there is no file defined anywhere in the code. The syntax you are using would indicate that you should have a DriveApp method that returns a fileIterator object. What is the attachment you are trying to send?
Please refer to the form submit trigger event objects in the documentation to see what you should expect when using that event handler.

Related

Update value of INPUT in externally loaded FORM not working

total programming novice here - I don't know much of javascript, wasn't programming since university (about 10 years ago) - trying to solve one specific problem on my website.
I am using CRM Bitrix24 and I have an unsubscribe form from this CRM placed on my website. I need to setup the form the way that the email is loaded from URL parameter.
I have done that simply by loading the input and set input.value = "email from URL". My problem is that the form has some kind of validation, and even though there is a text filled in the input field, the form is giving me the error: Field is required.
Screenshot here: https://ibb.co/Ns33GVN
The code of external form look like this:
<script data-b24-form="inline/120/8y7xg2" data-skip-moving="true">(function(w,d,u){var s=d.createElement('script');s.async=true;s.src=u+'?'+(Date.now()/180000|0);var h=d.getElementsByTagName('script')[0];h.parentNode.insertBefore(s,h);})(window,document,'https://cdn.bitrix24.com/b7014957/crm/form/loader_120.js');</script>
My JS:
function emailPopup(){
var params = new window.URLSearchParams(window.location.search);
var email = params.get('email');
const emailCollection = document.getElementsByName("email");
for (let i = 0; i < emailCollection.length; i++) {
if (emailCollection[i].name == "email") {
//emailCollection[i].focus();
emailCollection[i].value = email;
}
}
} window.addEventListener('load', function () {
emailPopup();
})
I tried to understand how the validation is done, but with no luck. The field has autocomplete = yes, so once it is submitted, next time it's not shooting the error, but the form is sent with the email submited at the first attempt, even though it is showing another one when hitting the SUBMIT button. It seems like it's only showing the email address from URL parameter, but in fact it's using wrong value, it's even empty (first attempt) or wrong (second attempt).
Is there a way how to force the field to pretend it was modified by user? Any ideas?
I have tried to setup similar environment here in jsfiddle: https://jsfiddle.net/e395wf6m/17/
Thanks a lot for any feedback!
I have a theory and it seems to be correct, as I tested it in your fiddle.
My theory is that the validation is done by firing a change event, so you need to trigger it. Luckily JavaScript let us do it:
if (emailCollection[i].name == "email") {
//emailCollection[i].focus();
emailCollection[i].value = email;
// to trigger the change event
emailCollection[i].dispatchEvent((new Event('change')));
}
As I said, it worked when I tested it on your fiddle, let me know if it works for you =]

How to detect Event Listeners and their actions on input fields

I have purchased a booking plugin (wordpress) to add to a site.
https://wpamelia.com/
I cannot show the site I am working on, but here a demo from plugin developers
https://sports.wpamelia.com/#book
Once you have chosen your date and time, you end up on a form with input fields.
I was able to pre-fill this form with data that I could pass via the URL.
My URL would look something like this: https://sports.wpamelia.com/?first=Jim&last=Tester&email=something%40something.com&phone=0222222222#book
But here is the problem:
Even though I managed to use jQuery to pre-fill the input fields of the form, as soon as I click confirm the fields' content is erased and the error "Please enter... " appears for each of them.
So again:
STEP 1: I open the booking page with an URL containing data in the query string
STEP 2: Using jQuery, I manage to pre-fill the form that appears after having chosen date and time (first name, last name ...)
STEP 3: I click "Confirm"
RESULT: all the fields are empty and for each one the error message "Please enter first name" (etc..) appears
I've messaged the plugin developers. Only answer was that there is indeed no functionality to take the data from the Query String into the form fields yet.
MY QUESTIONS:
1) How could I find out, with chrome inspector or other tools, why exactly the content I pre-fill into the form is ignored?
---> I've tried things like getEventListeners in the chrome inpector's console, but I don't really see how to get information out of that
2) Would anyone know what the issue is and/or how I could bypass it?
---> there is a lot of javascript from the plugin developers behind that and something is expecting manual entering of the data into the fields...
---> but even when trying to fake manual entering with things like $(this).trigger("change").val(function(i,val){return 'aaaa';}); this didn't solve the problem....
(If anyone is interested, I can post later my javascript/jQuery functionality to get the form fields pre-filled with data from Query String... interesting code as you have to wait until the fields appear for jQuery to recognise them..)
Thanks so much for any help!
cheers
Admino
#Admino - this may not be the best solution and I know this is an old question so you may not need it now but after not finding a better one it at least worked for me.
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
function valueOutput(element) {
element.dispatchEvent(new Event('input'));
}
jQuery(function() {
jQuery(document).on('change', 'input', function(e) {
valueOutput(e.target);
});
// you may want to perform more validations here if needed
// just checking here if email is present (but not checking for valid email address)
var fname = getUrlVars()["first"];
var lname = getUrlVars()["last"];
var email = getUrlVars()["email"];
var phone = getUrlVars()["phone"];
var custom1 = getUrlVars()["custom1"]; // you know this field label is Order Number
if (email.length > 0) {
// run an interval until the elements are present on the page (form displayed)
var checkInputs = setInterval(function() {
if (jQuery('.amelia-app-booking label[for="customer.email"]').length > 0) {
var em = jQuery('.amelia-app-booking label[for="customer.email"]').closest('.el-form-item').find('.el-input__inner');
// this checks to see if an Amelia customer is already present
if (em.val() == '') {
em.prop('value', email).val(email).trigger('change');
jQuery('.amelia-app-booking label[for="customer.firstName"]').closest('.el-form-item').find('.el-input__inner').prop('value', fname).val(fname).trigger('change');
jQuery('.amelia-app-booking label[for="customer.lastName"]').closest('.el-form-item').find('.el-input__inner').prop('value', lame).val(lame).trigger('change');
jQuery('.amelia-app-booking label[for="customer.phone"]').closest('.el-form-item').find('.el-input-group__prepend').siblings('.el-input__inner').prop('value', phone).val(phone).trigger('change');
}
// for custom fields I check the label text to find the correct input
if (custom1 != '') {
jQuery('.amelia-app-booking label:contains("Order Number")').closest('.el-form-item').find('.el-input__inner').prop('value', custom1).val(custom1).trigger('change');
}
// form info is updated so clear the interval
clearInterval(checkInputs);
}
}, 500);
}
});
You may want to try a different method than url params to sync this info so it's not so public in the url string. This code may not need both the prop and val jquery setters but I just left them for you to try. Hope it helps (and to others I'm open to a better solution)!

How do I pass a value from an HTML form submission to a Google Sheet and back to HTML in a Google Apps Script Web App

I'm trying to create a basic time clock web app.
So far, I'm using this script to create this web app which takes the input values and puts them in this spreadsheet for the time stamping part.
I need it to use one of the values from the form and perform a lookup in this sheet (take the longId and find me the name) and return the (name) value to the html page as a verification for the end user that they were identified correctly. Unfortunately, I don't know enough to grasp what I'm doing wrong. Let me know if I need to provide more info.
Edit 1
I'm thinking that I wasn't clear enough. I don't need the user info from entry, I need the user from a lookup. The user will be entering their ID anonymously, I need to match the ID to their info, and bring the info back for them to verify.
Edit 2
Using the link provided by Br. Sayan, I've created this script using this spreadsheet as above to test one piece of this. The web app here spits out: undefined. It should spit out "Student 3" Still not sure what I'm doing wrong.
One way for the next button to grab the student input field:
<input type="submit" onclick="studentName(document.getElementById('student').value)" value="Next..."/>
That sends the value to this func in Javascript.html:
function studentName(value) {
google.script.run
.withSuccessHandler(findSuccess)
.findStudent(value);
}
Which sends it to a findStudent(value) in Code.gs
You do the lookup and the return value goes back to findSuccess( result ) back in Javascript.html. Handle the result from there.
Also consider keeping the stock preventDefault() code that comes with the Web App template in the Help > Welcome Screen.
Please try this one:
(source: technokarak.com)
Also please have a look at:
Retrieve rows from spreadsheet data using GAS
EDIT:
Please make these changes in your function and let us know.
function findValue() {
var data = SpreadsheetApp.openById("15DRZRQ2Hcd7MNnAsu_lnZ6n4kiHeXW_OMPP3squbTLE").getSheetByName("Volatile Data").getDataRange().getValues();
for(i in data) {
if(data[i][3] == 100000003) {
Logger.log("yes");
Logger.log(data[i][0]);
var student = [];
student.push(data[i][0]);
return student;
}
}
}
It is a complicated answer, I have had a lot of success with:
function process(object){
var user = Session.getActiveUser().getEmail();
var key = object.Key;
send(key);
}
function send(k){
var ss =
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastR = ss.GetLastRow();
ss.GetRange(lastR,1).SetValue(k);
}
On your html button you will need to have inside the tags
onClick="google.script.run
.withSuccessHandler(Success)
.process(this.parentNode);"
In order for this to work, obviously you will need to have your fields named accordingly.
Edit: The only thing I did not include in the code was a Success handler, which will be in your html of the GAS script. This should point you in a direction that can resolve that.
Hope this helps.

onFormSubmit trigger not working in google script

I wonder if someone can help me.. I've written this code which is supposed to carry out the following workflow:
user fills in the form, form responses are recorded in excel sheet and various calculations take place, final values are appended into a template pdf, and this pdf is sent via email to the user.
The script does do all of that but only when I manually click "run", whereas I want it to execute whenever a form is submitted and I can't understand why it doesn't.
I would add a screenshot of my trigger but I can't as I don't have 10 reputation yet; but my trigger is set up as follows:
Run: onFormSubmit
Events: From spreadsheet, On form submit
I'll paste my code below, does anyone have any ideas as to why it might not be working? Any help would be hugely appreciated.
//Set out global variables
var docTemplate = ("1Ff3SfcXQyGeCe8-Y24l4EUMU7P9TsgREsAYO9W6RE2o");
var docName=("Calculations");
function onFormSubmit(e){
//Variables
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("Sheet3"));
var totalOutstandingPrincipalDebt = SpreadsheetApp.getActiveSheet().getRange("G25").getValue();
var totalOutstandingInterest = SpreadsheetApp.getActiveSheet().getRange("H25").getValue();
var totalOutstandingCompensation = SpreadsheetApp.getActiveSheet().getRange("I25").getValue();
var dailyInterestRate = SpreadsheetApp.getActiveSheet().getRange("J25").getValue();
var grandTotal = SpreadsheetApp.getActiveSheet().getRange("K25").getValue();
var userEmail = SpreadsheetApp.getActiveSheet().getRange("H24").getValue();
//Template Info
var copyId=DriveApp.getFileById(docTemplate).makeCopy(docName+' for '+userEmail).getId();
var copyDoc = DocumentApp.openById(copyId);
var copyBody = copyDoc.getActiveSection();
//Putting the data into the file
copyBody.insertParagraph(1,'Total Outstanding Principal Debt: £' + totalOutstandingPrincipalDebt);
copyBody.insertParagraph(2,'Total Outstanding Interest: £'+ totalOutstandingInterest );
copyBody.insertParagraph(3,'Total Outstanding Compensation: £'+ totalOutstandingCompensation);
copyBody.insertParagraph(4,'Grand Total: £' + grandTotal);
copyBody.insertParagraph(5,'Daily Interest Rate: £'+ dailyInterestRate);
copyDoc.saveAndClose();
//email pdf document as attachment
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
var subject = "Calculations";
var body = "Thank you very much for using our online calculator. Please find your results attached.";
MailApp.sendEmail(userEmail, subject, body, {htmlBody: body, attachments: pdf});
//Deletes temporary Document
DriveApp.getFileById(copyId).setTrashed(true);
}
It looks like instead of using the values attribute of the form submit event you are trying to look directly at the spreadsheet tab that gets values written to it. Think of it this way: you could attach this script to a Form instead of a spreadsheet and have it still work. At the time a form submission happens, the event object e has everything you need.
This is a problem because you have hardwired cell addresses, but the form will keep writing more rows. This means you won't see new rows as they accumulate.
But the big problem is that you're looking at that tab using getActiveSpreadsheet(). When a user submits a form response, there is no "active spreadsheet." The "active" thing was the form. So, in order to get the data that was submitted, you'll need to look in e.values -- this will contain the row of data you're currently trying to get to in lines 9-14.
btw, the reason it works when run manually is because "active spreadsheet" means something. As soon as you walk away, that spreadsheet isn't active.
EDIT:
Zehrazjp20 points out that they are using the spreadsheet for computation, not just reading raw values as from the Form Submit event. In this case, the best way is to replace:
var ss = SpreadsheetApp.getActiveSpreadsheet();`
with
var ssID = 'abcdefghijklmnop';
var ss = SpreadsheetApp.openById(ssID);
...using your spreadsheet's real ID, of course.

Global Variables not Accessible to Functions Javascript

I am using javascript to validate the information a user has put into a form. I have two functions in my code which both need to check that the information in two text fields is the same. One function is called when the form is submitted, the other when something is typed into the second field.
However neither function seems to be able to access these variables. Google Developer tools shows their value to be Null. The code works fine when I declare the variables within each function but I thought it should be possible to declare them just once
var user1 = document.getElementById('user1');
var user2 = document.getElementById('user2');
function validateText() {
var message2 = document.getElementById('confirmMessage');
if(user1.value !== user2.value) {
message2.innerHTML = "Your usernames must be the same!";
return false;
}
}
function checkUser() {
//Store the Confimation Message Object ...
var message = document.getElementById('confirmMessage');
//Compare the values in the user field
//and the confirmation field
if(user1.value == user2.value) {
//The usernames match.
// tell the user that they have entered the correct password
message.innerHTML = "Passwords Match!"
}
}
you need to define these variables after the document is loaded.
var user1, user2;
document.onload = function () {
user1 = document.getElementById('user1');
user2 = document.getElementById('user2');
}
If the user1 and user2 elements are created by Javascript or by HTML that is placed after the JS (perhaps you are inserting this JS in the head section) then they still dont exist when you first run your script. This means that the getElementById variables will not find anything and return null.
You need to make sure that you call getElementByID after the apropriate elements have been created. ONe easy way to do that is put the calls inside the validation functions but another possibility would be to put it in an onLoad handler.
I would prefer sticking them in the validators though - getting elements by ID is not an expensive operation (so you don't need to worry about performance) and the closer you fetch the data to when you use it the less stuff to worry about.

Categories

Resources