Why isn't my text field being added to the page? - javascript

I'm working on the interactivity of a simple HTML form.
Specifically, there is a dropdown select box for job roles. If 'other' is selected, then a text field should appear, asking the user to be more specific.
I'm a beginner and want to do this without jQuery.
Here is a snippet of the HTML I am working with:
<fieldset class="basic">
<legend>Basic Info</legend>
<label for="name">Name:</label>
<input type="text" id="name" name="user_name">
<label for="mail">Email:</label>
<input type="email" id="mail" name="user_email">
<label>Job Role</label>
<select id="title" name="user_title">
<option value="full-stack js developer">Full Stack JavaScript Developer</option>
<option value="front-end developer">Front End Developer</option>
<option value="back-end developer">Back End Developer</option>
<option value="designer">Designer</option>
<option value="student">Student</option>
<option value="other">Other</option>
</select>
</fieldset>
My intuition tells me to first build the text field and add it's attributes.
I will then use an if condition to test whether or not the selected option is 'other'. If it is, then I will append the newly created text field to the page.
This hasn't been working so far. To try and debug this, I have tried console logging the elements I am trying to work with. I don't think I'm understanding how this works as it's printing out 'undefined' and 'null'.
Here is my JS:
// TASK: Add interactivity to form
'use strict';
// Hold DOM elements for easy access
var pageBody = document.querySelector('body');
var jobRoleSelect = document.getElementById('title');
console.log(jobSelected);
var jobSelected = jobRoleSelect.options[jobRoleSelect.selectedIndex].value;
var basicSection = document.querySelector('basic');
console.log(basicSection);
// Job Role section of the form. Reveal a text field when the "Other" option is selected from the "Job Role" drop down menu
if(jobSelected === 'other') {
var otherText = document.createElement('input');
// Add an text input field. Use the id of "other-title"
otherText.setAttribute('id', 'other-title');
otherText.setAttribute('type', 'text');
otherText.setAttribute('name', 'other_field');
otherText.setAttribute('placeholder', 'Your Title');
var otherLabel = document.createElement('label');
otherLabel.setAttribute('for', 'other_field');
otherLabel.innerHTML = 'other';
basicSelection.appendChild(otherLabel);
basicSelection.appendChild(otherText);
}

You need to set up an event listener to listen for the "change" event that is fired when the user makes a selection from the dropdown menu. Also you are referencing "basicSelection" instead of "basicSection" in your if statement.
'use strict';
var jobRoleSelect = document.getElementById('title');
var basicSection = document.getElementsByClassName('basic')[0];
document.getElementById("title").addEventListener("change", function(){
var jobSelected = jobRoleSelect.options[jobRoleSelect.selectedIndex].value;
console.log(jobSelected);
if(jobSelected === 'other') {
var otherText = document.createElement('input');
// Add an text input field. Use the id of "other-title"
otherText.setAttribute('id', 'other-title');
otherText.setAttribute('type', 'text');
otherText.setAttribute('name', 'other_field');
otherText.setAttribute('placeholder', 'Your Title');
var otherLabel = document.createElement('label');
otherLabel.setAttribute('for', 'other_field');
otherLabel.innerHTML = 'Other:';
basicSection.appendChild(otherLabel);
basicSection.appendChild(otherText);
}
});
<fieldset class="basic">
<legend>Basic Info</legend>
<label for="name">Name:</label>
<input type="text" id="name" name="user_name">
<label for="mail">Email:</label>
<input type="email" id="mail" name="user_email">
<label>Job Role</label>
<select id="title" name="user_title">
<option value="full-stack js developer">Full Stack JavaScript Developer</option>
<option value="front-end developer">Front End Developer</option>
<option value="back-end developer">Back End Developer</option>
<option value="designer">Designer</option>
<option value="student">Student</option>
<option value="other">Other</option>
</select>
</fieldset>

If the JS you've shown is included at the end of the document body then it will run once when the page first loads. I assume what you actually want is to have it run in response to the user changing what is selected, in which case you need to wrap your code in a function and make that an event handler for the change event.
var jobRoleSelect = document.getElementById('title');
jobRoleSelect.addEventListener('change', function() {
// your other code here
});
Note also that you need to allow for the user changing the selection to "Other", then changing it back to something else, then changing it to "Other" again, that is, your function would need to be able to remove the text input if not required for the current selection.
But I think it would be a lot simpler to just include the text element and label in your html and hide and show them as needed:
var jobRoleSelect = document.getElementById('title');
jobRoleSelect.addEventListener('click', function() {
var otherSelected = jobRoleSelect.value === 'other';
var otherElements = document.querySelectorAll('.other');
for (var i = 0; i < otherElements.length; i++) {
if (otherSelected)
otherElements[i].classList.remove('hidden');
else
otherElements[i].classList.add('hidden');
}
});
label {
display: block;
}
.hidden {
display: none;
}
<fieldset class="basic">
<legend>Basic Info</legend>
<label for="name">Name:</label>
<input type="text" id="name" name="user_name">
<label for="mail">Email:</label>
<input type="email" id="mail" name="user_email">
<label>Job Role</label>
<select id="title" name="user_title">
<option value="full-stack js developer">Full Stack JavaScript Developer</option>
<option value="front-end developer">Front End Developer</option>
<option value="back-end developer">Back End Developer</option>
<option value="designer">Designer</option>
<option value="student">Student</option>
<option value="other">Other</option>
</select>
<label class="other hidden" for="other-title">Other</label>
<input class="other hidden" type="text" id="other-title" name="other-field" placeholder='Your title'>
</fieldset>
I've given all (that is both) of the elements that need to be hidden or shown the other class, which means my code has to loop over them. You could instead wrap them in a div and just hide the div.
Note that I've done the hiding/showing via a class, which I add or remove via the elements' .classList. Unfortunately .classList isn't supported in IE<=9, but there is a polyfill, or of course you can just set the style.display directly or whatever.

You have so many errors in your code. But i have figured them out and came out with the solution. Use this
<fieldset class="basic">
<legend>Basic Info</legend>
<label for="name">Name:</label>
<input type="text" id="name" name="user_name">
<label for="mail">Email:</label>
<input type="email" id="mail" name="user_email">
<label>Job Role</label>
<select id="title" name="user_title">
<option value="full-stack js developer">Full Stack JavaScript Developer</option>
<option value="front-end developer">Front End Developer</option>
<option value="back-end developer">Back End Developer</option>
<option value="designer">Designer</option>
<option value="student">Student</option>
<option value="other">Other</option>
</select>
</fieldset>
<script>
'use strict';
// Hold DOM elements for easy access
var pageBody = document.querySelector('body');
var jobRoleSelect = document.getElementById('title');
//console.log(jobSelected);
var basicSelection = document.querySelector('.basic');
//console.log(basicSection);
jobRoleSelect.onchange = function(){
var jobSelected = jobRoleSelect.options[jobRoleSelect.selectedIndex].value;
// Job Role section of the form. Reveal a text field when the "Other" option is selected from the "Job Role" drop down menu
if(jobSelected == 'other') {
console.log('nice');
var otherText = document.createElement('input');
// Add an text input field. Use the id of "other-title"
otherText.setAttribute('id', 'other-title');
otherText.setAttribute('type', 'text');
otherText.setAttribute('name', 'other_field');
otherText.setAttribute('placeholder', 'Your Title');
var otherLabel = document.createElement('label');
otherLabel.setAttribute('for', 'other_field');
otherLabel.innerHTML = 'other';
basicSelection.appendChild(otherLabel);
basicSelection.appendChild(otherText);
}
}
</script>
Here is a work jsFiddle

Related

Update HTML dropdown list with Javascript

This issue is making me crazy.
I would like to update a dropdown list (select options) named "Title" (having 2 options ("Mr" & "Ms").
If i run with this way (updating the select option outside the function), the dropdown list is updated selecting the option #1. Also the input field named "e1" is updated.
var MyTitle = document.getElementById("Title");
MyTitle.selectedIndex = 1;
function bb(ff) {
document.getElementById("e1").value = ff;
}
google.script.run.withSuccessHandler(bb).FillUserDetails("gg");
<div class="input-field col s1">
<select id="Title" name="Title">
<option value="1">Mr</option>
<option value="2">Ms</option>
</select>
<label>Gender</label>
</div>
<input type="text" id="e1" name="e1" class="validate">
But If i run with this way (updating the select option inside the function), the dropdown list is not updated and still selecting the option #0. while the input field (e1) is update.
function bb(ff) {
var MyTitle = document.getElementById("Title");
MyTitle.selectedIndex = 1;
document.getElementById("e1").value = ff;
}
google.script.run.withSuccessHandler(bb).FillUserDetails("gg");
<div class="input-field col s1">
<select id="Title" name="Title">
<option value="1">Mr</option>
<option value="2">Ms</option>
</select>
<label>Gender</label>
</div>
<input type="text" id="e1" name="e1" class="validate">
Even using:
M.updateTextFields();
M.FormSelect.init(elems);
the problem persists. Any ideas?
I'm adding the code of the FillUserDetails() function.
in code.gs
function FillUserDetails(a) {
a="Hello";
return a
}
I hope this addition improves the clarity of the question.

How to make certain input fields appear when selected certain option in html?

I am working on a web form and here i want to make it so that you can select one of the three given types of options of contact and based on it a respective input field appears.How can i achieve that?
<select id="contact">
<option value="address">Address</option>
<option value="phone">Phone number</option>
<option value="website">Website</option>
</select>
i tried this at first but didnt know how to proceed further:
<form name="address" id="address" style="display:none">
<input type="text" name="address_"><br>
</form>
<form name="phone" id="phone" style="display:none">
<input type="text" name="phone_"><br>
</form>
<form name="website" id="website" style="display:none">
<input type="text" name="website_"><br>
</form>
Add an onselect handler to the option fields. Then inside the handler, call a function to append a dom node. Something like this:
<option value="address" onselect="handleSelection">Address</option>
function handleSelection() {
document.body.appendChild(someDomNode)
}
It's better to set the onchange EventListener to the parent <select id="contact"> element than it is to set a onselected or some other EvenListener to each of the <option> elements.
Note: I separated the javascript logic a little bit so it's easier to read.
document.getElementById('contact').addEventListener('change', function(e){
let value = e.target.value;
removeCreatedElements(); // remove all previously added, if any, before adding a new one
let input = createElement(value);
document.body.appendChild(input);
input.style.display = "block";
})
function createElement(value) {
let input = document.createElement("input");
input.type = "text";
input.id = value;
input.classList.add("dynamically-added");
input.placeholder = value;
return input;
}
function removeCreatedElements() {
let inputs = document.querySelectorAll(".dynamically-added");
for(let i=0; i < inputs.length; i++) {
document.body.removeChild(inputs[i]);
}
}
#contact {
margin-bottom: 40px;
}
<select id="contact">
<option value="address">Address</option>
<option value="phone">Phone number</option>
<option value="website">Website</option>
</select>

Javascript issue with selector session storage

Hello so I added some javascript to keep selection stored when page is reloaded in my select menu , but the issue is when I load the page for the first time nothing appears in my select menu (First choice of the select menu)
what appears
window.onload = function() {
var selItem = sessionStorage.getItem("SelItem");
$('#date').val(selItem);
}
$('#date').change(function() {
var selVal = $(this).val();
sessionStorage.setItem("SelItem", selVal);
});
<label class="op" for="date">Periode : </label>
<select id="date">
<option value="toutes">Toutes</option>
<option value="2019">Année en cours</option>
<option value="2018">Année pécédente</option>
<option value="2017">Année -2</option>
<option value="2016">Année -3</option>
<option value="2015">Année -4</option>
</select>
<br/><br/>
<input type="hidden" name="date" id="date1" class="datepicker w100" value="2015-01-01"type="date" placeholder="Du jj/mm/aaaa"> <input type ="hidden"name="date2" id="date2" value="2026-12-31"class="datepicker w100" type="date" placeholder="Au jj/mm/aaaa">
<br/>
So only set the value if there is something in storage.
if (selItem) $('#date').val(selItem);

How to get all the textboxes linked to a corresponding select field?

Basically, I want to make a site with a button that repeatedly asks user for input. However, one of the inputs that the site asks for involves a select field and depending on the select field, have a corresponding text field appear or dissapear(values none). My javascript utilizes a for loop as the user can repeatedly press the button to add more and more select fields( and corresponding text field).
Here is jsfiddle
Below is the example code of what I'm trying to do.
HTML
<div><select class="DISPLAYTYPE" id="QBox" data-fieldtype="P">
<option value = "text">TextBox</option>
<option value = "check">CheckBox</option>
<option value = "radio">Radio</option>
</select></div>
<input type="number" min="1" value="LENGTH" class="quantumBox" id="P">
JAVASCRIPT
var textBoxList = document.getElementsByClassName("DISPLAYTYPE");
for (var i=0; i<textBoxList.length;i++){
textBoxList[i].addEventListener('change', function(){
var subParam = textBoxList[i].options[textBoxList.selectedIndex].value;
if(subParam ="text"){
//make ONLY corresponding input box appear
}else{
//make ONLY corresponding input box dissapear
}
})
};
EDIT: This is the Structure
[table id="rootPlacement"]
//insert here
[/table]
[button/] <--This will make a duplicate of invisible html and place it under invisible root
//The invisible html stuff we want to duplicate into //insert here
Given your feedback about the HTML structure in the comments, you can use the following to achieve what you are trying to. Just look into
You are trying to get the selected value inside the change event for the drop-down by using var subParam = textBoxList[i].options[textBoxList.selectedIndex].value; rather than using textBoxList[i] you can use this so that i becomes var subParam = this.options[this.selectedIndex].value.
For showing hiding the inputs you can use the function findRoot() which takes the target element object i.e ``selectand finds a parent with the class namedrootPlacement` and returns the node and then you can iterate it's children to show the selected node and hide the rest.
See a demo below
var textBoxList = document.querySelectorAll(".DISPLAYTYPE");
for (var i = 0; i < textBoxList.length; i++) {
textBoxList[i].addEventListener('change', function() {
var selectedType = this.options[this.selectedIndex].value;
let rootPlacement = findRoot(this, 'rootPlacement');
let children = rootPlacement.children;
for (var c = 0; c < children.length; c++) {
let element = children[c];
let elementType = element.type;
let isInputElement = typeof elementType !== 'undefined';
if (isInputElement) {
if (elementType == selectedType) {
element.style.display = 'inline';
} else {
element.style.display = 'none';
}
}
}
});
};
function findRoot(el, cls) {
while ((el = el.parentElement) && !el.classList.contains(cls));
return el;
}
input {
display: none;
}
<div class="rootPlacement">
<div>
<select class="DISPLAYTYPE" id="QBox1" data-fieldtype="P">
<option value="text">TextBox</option>
<option value="checkbox">CheckBox</option>
<option value="radio">Radio</option>
</select>
</div>
<input type="text" value="" class="quantumBox" id="P1">
<input type="checkbox" value="" class="quantumBox" id="q1">
<input type="radio" value="" class="quantumBox" id="r1">
</div>
<div class="rootPlacement">
<div>
<select class="DISPLAYTYPE" id="QBox2" data-fieldtype="P">
<option value="text">TextBox</option>
<option value="checkbox">CheckBox</option>
<option value="radio">Radio</option>
</select>
</div>
<input type="text" value="LENGTH" class="quantumBox" id="P2">
<input type="checkbox" value="" class="quantumBox" id="q2">
<input type="radio" value="LENGTH" class="quantumBox" id="r2">
</div>
<div class="rootPlacement">
<div>
<select class="DISPLAYTYPE" id="QBox3" data-fieldtype="P">
<option value="text">TextBox</option>
<option value="checkbox">CheckBox</option>
<option value="radio">Radio</option>
</select>
</div>
<input type="text" value="LENGTH" class="quantumBox" id="P3">
<input type="checkbox" value="" class="quantumBox" id="q3">
<input type="radio" value="LENGTH" class="quantumBox" id="r3">
</div>

How hidden/visible a label on value from a select into a form

Having:
<label for="option">Option:
<select name="option" required>
<option value="Yes">Yes</option>
<option value="No" selected>No</option>
</select>
</label>
<label for="mytext">Text:
<input name="mytext" type="text">
</label>
How solve for:
With OPTION to NO then MYTEXT need to be HIDDEN (label included);
With OPTION to YES then MYTEXT need to be VISIBLE (label included);
On loading of page MYTEXT need to be HIDDEN (label included).
Just use event listeners:
document.addEventListener('DOMContentLoaded', function() { // runs after all elements are loaded
// element selectors:
var mytextLabel = document.querySelector('label[for=mytext]');
var option = document.querySelector('select[name=option]');
var mytextInput = mytextLabel.querySelector('input');
mytextLabel.classList.add('hidden'); // hides 'mytext' after page load
option.addEventListener('change', function(event) { // runs after option is selected
// the actual logic is pretty straightforward:
if (event.target.value === 'Yes') {
mytextLabel.classList.remove('hidden'); // shows the label with input inside
mytextInput.required = true; // marks the input as required
} else {
mytextLabel.classList.add('hidden'); // hides the label with input inside
mytextInput.required = false; // marks the input as optional
}
});
});
.hidden {display: none;}
<form onsubmit="alert('sent'); return false;">
<label for="option">Option:
<select name="option" required>
<option value="Yes">Yes</option>
<option value="No" selected>No</option>
</select>
</label>
<label for="mytext">Text:
<input name="mytext" type="text" />
</label>
<button type="submit">Send</button>
</form>
EDIT: added switching of required attribute
EDIT: use CSS classes as suggested by #ScottMarcus (you probably don't want to override display: hidden in most cases, but it's still a better way than inline styles)
You just need to set up a CSS class the sets the element to be hidden and have that class applied to the element by default if you want it hidden from the start. Then, via a change event handler on the select, you toggle the use of that class with the .classList object's .toggle() method:
var input = document.querySelector("[name='mytext']");
document.querySelector("select[name='option']").addEventListener("change", function(){
input.classList.toggle("hidden");
});
.hidden { display:none; } /* This is appled to the input by default and toggled as needed */
<label for="option">Option:
<select name="option" required>
<option value="Yes">Yes</option>
<option value="No" selected>No</option>
</select>
</label>
<label for="mytext">Text:
<input name="mytext" type="text" class="hidden">
</label>

Categories