Javascript, The <p> element displays [object HTMLInputElement] why does it display this? - javascript

I am trying to figure out Object Oriented Programming in javascript and instead of displaying the input on form it displays [object HTMLInputElement]
document.getElementById('submit').addEventListener('click', function() {
let uName = document.getElementById('uName').value;
info.showInfo();
});
class Information {
constructor(name) {
this.name = name;
}
showInfo() {
var z = document.createElement('p');
z.innerHTML = this.name;
document.body.appendChild(z);
}
}
const info = new Information(uName);
<form action="/home.php" method="get"></form>
<label for="fname">First name:</label>
<input type="text" name="name" id="uName" value="value" />
<button id="submit">Submit</button>

As #Teemu said in comment let uName is invisible for const info = new Information(uName);
Try following code.
uNameElement = document.getElementById('uName');
document.getElementById('submit').addEventListener('click', function() {
const info = new Information(uNameElement.value);
info.showInfo();
});
class Information {
constructor(name) {
this.name = name;
}
showInfo() {
var z = document.createElement('p');
z.textContent = this.name;
document.body.appendChild(z);
}
}
<form action="/home.php" method="get"></form>
<label for="fname">First name:</label>
<input type="text" name="name" id="uName" value="value" />
<button id="submit">Submit</button>
UPDATE: z.innerHTML replaced by z.textContent

Related

Displaying the content of an input for several divs

I want to give all .firstname-show the content from the input but I don't know how to do it. Here's code:
<input type="text" id="firstname" name="firstname" placeholder="First name">
<button id="firstname-btn" onclick="show()">SHOW</button>
<div class="firstname-show"></div>
<div class="firstname-show"></div>
function show() {
var name = document.getElementById('firstname').value;
document.querySelectorAll('.firstname-show').textContent = name;
}
Query selector will return an array so you have to iterate using for loop. see below function.
function show() {
var name = document.getElementById('firstname').value;
var elements = document.querySelectorAll('.firstname-show');
for(var i in elements){
elements[i].textContent = name;
}
}
https://jsfiddle.net/kagf25c1/
Since the querySelectorAll returns a collection, you can use the forEach method on the collection to browse each element and apply the processing you want
const show = () => {
let value = document.getElementById('firstname').value;
document.querySelectorAll('.firstname-show')
.forEach(div => div.textContent = value);
}
<input type="text" id="firstname" name="firstname" placeholder="First name">
<button id="firstname-btn" onclick="show()">SHOW</button>
<div class="firstname-show"></div>
<div class="firstname-show"></div>

How to pass form data to GAS

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")
}

Why doesn't work method of adding a contact to the array?

I add a new contact in the method: addToBook(). First I check the fields, if they are not empty, then I create the instance of the class LocalStorage and pass the field values and make JSON from it.
I want to see the new product in the array and LocalStorage but I get the error:
Uncaught TypeError: Can not read property 'push' of undefined"
Help me fix it.
class Contacts {
constructor() {
// Storage Array
this.contacts = [];
}
addToBook() {
let isNull = forms.name.value != '' && forms.phone.value != '' &&
forms.email.value != '';
if (isNull) {
// format the input into a valid JSON structure
let obj = new LocalStorage(forms.name.value,
forms.phone.value, forms.email.value);
this.contacts.push(obj);
localStorage["addbook"] = JSON.stringify(this.contacts);
console.log(this.contacts);
}
console.log(this.contacts);
}
}
let contacts = new Contacts();
class Forms {
constructor() {
// Blocks
this.addNewContact = document.getElementById("addNewContact");
this.registerForm = document.querySelector('.addNewContact-form');
// Forms
this.fields = document.forms.register.elements;
this.name = this.fields[0].value;
this.phone = this.fields[1].value;
this.email = this.fields[2].value;
// Buttons
this.cancelBtn = document.getElementById("Cancel");
this.addBtn = document.getElementById("Add");
this.BookDiv = document.querySelector('.addbook');
// display the form div
this.addNewContact.addEventListener("click", (e) => {
this.registerForm.style.display = "block";
if (this.registerForm.style.display = "block") {
this.BookDiv.style.display = "none";
}
});
this.cancelBtn.addEventListener("click", (e) => {
this.registerForm.style.display = "none";
if (this.registerForm.style.display = "none") {
this.BookDiv.style.display = "block";
}
});
this.addBtn.addEventListener("click", contacts.addToBook);
}
}
let forms = new Forms();
class LocalStorage {
constructor(name, phone, email) {
this.name = name;
this.phone = phone;
this.email = email;
}
}
<div class="AddNewContact">
<button id="addNewContact" type="button">Add new contact</button>
<i class="fas fa-search "></i>
<input type="text" placeholder="SEARCH BY NAME">
<button id="ImportData" type="button">Import data to book</button>
</div>
<div class="addNewContact-form">
<form name="register">
<label for="name">Name</label><input type="text" id="name" class="formFields">
<label for="phone">Phone</label><input type="text" id="phone" class="formFields">
<label for="email">E-Mail</label><input type="text" id="email" class="formFields">
<br><br>
<button id="Add" type="button">Add Now</button><button id="Cancel" type="button">Cancel</button>
</form>
</div>
When you pass a reference to a function like this:
this.addBtn.addEventListener("click", contacts.addToBook);
you loose the binding to this. Which you depend on when you call this.contacts.push(obj); in addToBook()
You can hard bind the reference you want this to be with:
this.addBtn.addEventListener("click", contacts.addToBook.bind(contacts);
You could also pass in a function that explicitly calls addToBook with the correct context:
this.addBtn.addEventListener("click", () => contacts.addToBook());

Get data for form input array using specific key

So, let's say I have an HTML form like this:
<form id="myForm">
<input type="text" name="dummy">
<input type="text" name="people[0][first_name]" value="John">
<input type="text" name="people[0][last_name]" value="Doe">
<input type="text" name="people[1][first_name]" value="Jane">
<input type="text" name="people[1][last_name]" value="Smith">
</form>
And I want to get a JavaScript array that matches the values of real. For example:
// If there was a sweet function for this...
var people = getFormDataByInputName( 'people' );
// Value of `people` is...
// [
// {
// 'first_name' : 'John',
// 'last_name' : 'Doe'
// },
// {
// 'first_name' : 'Jane',
// 'last_name' : 'Smith'
// }
// ]
Is there any easy way of doing that for just a specific form item (in this case, people)? Or would I have to serialize the entire form an then just extract the element I want?
I also thought of potentially using the following approach:
var formData = new FormData( document.querySelector( '#myForm' ) );
var people = formData.get( 'people' );
But that doesn't appear to work; people is just null after that.
You could do this with plain js using reduce method and return each person is one object.
const form = document.querySelectorAll('#myForm input');
const data = [...form].reduce(function(r, e) {
const [i, prop] = e.name.split(/\[(.*?)\]/g).slice(1).filter(Boolean)
if (!r[i]) r[i] = {}
r[i][prop] = e.value
return r;
}, [])
console.log(data)
<form id="myForm">
<input type="text" name="dummy">
<input type="text" name="people[0][first_name]" value="John">
<input type="text" name="people[0][last_name]" value="Doe">
<input type="text" name="people[1][first_name]" value="Jane">
<input type="text" name="people[1][last_name]" value="Smith">
</form>
function getObject(name, key) {
if(key.includes(name)) {
var splitStr = key.split(/\[|\]/g);
return {
index: splitStr[1],
key: splitStr[3],
}
}
return null;
}
function getFormDataByInputName(name) {
var formData = new FormData( document.querySelector('#myForm'));
var results = [];
for (var key of formData.keys()) {
var obj = getObject(name, key);
if (obj) {
if (results[obj.index]) results[obj.index][obj.key] = formData.get(key);
else results[obj.index] = { [obj.key]: formData.get(key) };
}
}
return results;
}
var people = getFormDataByInputName('people');
console.log(people);
<form id="myForm">
<input type="text" name="dummy">
<input type="text" name="people[0][first_name]" value="John">
<input type="text" name="people[0][last_name]" value="Doe">
<input type="text" name="people[1][first_name]" value="Jane">
<input type="text" name="people[1][last_name]" value="Smith">
</form>
Your code won't work because to HTML/JS name is just a string that it sends to the server when the form is submitted (the name in the name/value pairs). You might think it is arrays, but HTML/JS doesn't.
So no one-liner to get the job done. Try this: In your HTML, add <div class="name"> ...
(UPDATE: thanks for the idea, #Nenad, I've never tried one of these snippets)
var people = [];
$('.name').each(function() {
people.push({
first_name: $('input:nth-child(1)', this).val(),
last_name: $('input:nth-child(2)', this).val()
});
});
console.log(people);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="myForm">
<input type="text" name="dummy">
<div class="name">
<input type="text" value="John">
<input type="text" value="Doe">
</div>
<div class="name">
<input type="text" value="Jane">
<input type="text" value="Smith">
</div>
</form>
Use CSS attribute prefix selector, such as
form.querySelectorAll('[name^="people[]"]')
You can use a for-loop to get all peoples, as such
const MAX_PEOPLES = 2;
const list = [];
for (i = 0; i <= MAX_PEOPLES; i++) {
const eles = form.querySelectorAll(`[name^="people[${i}]`);
if (eles.length !== 2)
break;
list.push({
first_name: eles[0].value,
last_name: eles[1].value
});
}
that yields
[
{
"first_name":"John",
"last_name":"Doe"
},
{
"first_name":"Jane",
"last_name":"Smith"
}
]

Calling class function not responding as expected

I have a problem with calling the variable valio, when I put text into the input and after calling it, the console returns "now registered
undefined".
I have experience with this type of calling but never happened before so could some one explain me why this doesn't work as I expected ?
var name = document.getElementById("name");
var email = document.getElementById("email");
var comment = document.getElementById("comment");
class User{
constructor(username,comment,email){
this.username = username;
this.comment = comment;
this.email = email;
}
register(){
console.log(this.username + this.comment + " is now registered");
}
}
var valio = new User(name.value , comment.value, email.value);
<input id="name" type="text" value=""><br>
<input id="email" type="text" value=""><br>
<input id="subject" type="text" value=""><br>
<input id="comment" type="text" value=""><br>
Change ur variable name to uname.
var uname = document.getElementById("name");
var email = document.getElementById("email");
var comment = document.getElementById("comment");
class User{
constructor(username,comment,email){
this.username = username;
this.comment = comment;
this.email = email;
}
register(){
console.log(this.username + this.comment + " is now registered");
}
}
var valio = new User(uname.value , comment.value, email.value);
<input id="name" type="text" value=""><br>
<input id="email" type="text" value=""><br>
<input id="subject" type="text" value=""><br>
<input id="comment" type="text" value=""><br>
You put the reference to the name input field in a variable called name. However, name is already defined as a global variable of type string:
https://developer.mozilla.org/en-US/docs/Web/API/Window/name
It can probably not be overridden.
Try changing the variable name:
var username = document.getElementById("name");
var valio = new User(username.value , comment.value, email.value);
It appears that the name variable is conflicting with a keyword in javascript. Try renaming it to something else.
e.g.
var nameInput = document.getElementById("name");
Then pass in nameInput.value to the constructor.

Categories

Resources