How to make dependent dropdown list from Google Sheet? - javascript

I have a Google sheet with custom HTML form. The form contains two <select> elements.
<div class="input-group mb-3">
<div class="input-group-prepend">
<label class="input-group-text" for="category_name">Категория</label>
</div>
<select class="custom-select" id="category_name" name="category_name" required>
<option value="" selected></option>
</select>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<label class="input-group-text" for="contragent_name">Контрагент</label>
</div>
<select class="custom-select" id="contragent_name" name="contragent_name">
<option value="" selected></option>
</select>
</div>
I want to get dependent dropdown list at the second selection (contragent_name).
Just two lists:
first: if selected value of category_name is not equal to 'Заработная Плата' --> contragent_name selection list must be populated with getContragent() (just values of one column)
second: if selected value of category_name is equal to 'Заработная Плата' --> contragent_name selection list must be populated with getStaffList() (just array with names) with required attribute.
I tried to write script but it does not work
<script>
(function () {
google.script.run.withSuccessHandler(
function (selectList) {
var select = document.getElementById("category_name");
for( var i=0; i<selectList.length; i++ ) {
var option = document.createElement("option");
option.value = selectList[i][0];
option.text = selectList[i][0];
select.add(option);
}
}
).getCategory();
}());
$(function() {
$('#category_name').on("change", function () {
if ($(this).val() !== 'Заработная Плата') {
function () {
google.script.run.withSuccessHandler(
function (selectList) {
var select = document.getElementById("contragent_name");
for( var i=0; i<selectList.length; i++ ) {
var option = document.createElement("option");
option.value = selectList[i][0];
option.text = selectList[i][0];
select.add(option);
}
}
).getContragent();
}()} else {
function () {
google.script.run.withSuccessHandler(
function (selectList) {
var select = document.getElementById("contragent_name");
select.required = true;
for( var i=0; i<selectList.length; i++ ) {
var option = document.createElement("option");
option.value = selectList[i];
option.text = selectList[i];
select.add(option);
}
}
).getStuffList();
}()}
});
});
</script>
Where I'm wrong and how to fix it?

HTML
<!DOCTYPE html>
<html>
<head>
<title>My Dependent Dropdown</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
</head>
<body>
<form>
<div class="form-group col-md-4">
<label for="category">Category</label>
<select id="category" class="form-control" required>
</select>
</div>
<div class="form-group col-md-4">
<label for="items">Items</label>
<select id="items" class="form-control" required>
</select>
</div>
</form>
<script src="https://code.jquery.com/jquery-3.5.1.slim.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
</body>
</html>
JS
var db = [["Vegetable","Carrot"],["Vegetable","Onion"],["Fruit","Apple"],["Fruit","Banana"]];
$(document).ready(function(){
var categoryLists = db.map(x => x[0]);
categoryLists = [... new Set(categoryLists)]; //get unique category values
categoryLists.forEach(x => $("#category").append(new Option(x, x))); //new Option("text", "value")
$("#category").on("change",updateItemLists).change(); //add event listner and trigger it once to show items
});
function updateItemLists(){
var category = $("option:selected", this).text(); //get category
var itemLists = db.filter(x => x[0] == category).map(x =>x[1]);
$("#items option").remove();
itemLists.forEach( (x, i) => $("#items").append(new Option(x,i))); //x: array value ; i: array index
};

Related

Run javascript code after template load and populate data from Google Sheet

I’m trying to create a web app, using Google Apps Script, in which when the the the certain condition are met, it will enable the Select Element with id="posAppDesired" then it will run the Google Apps Script to get the array of options, then return the array to the JavaScript and change the innerHTML of the Select Element. Then if the button with the id="addPositionId" is clicked, it will add a template and then it should load or duplicate the same option.
Here is the HTML code:
<!-- POSITION APPLIED FOR-->
<div class="form-row">
<div class="form-group col-sm-9">
<label for="posAppDesired">Select Desired Position</label>
<div class="input-group">
<select class="custom-select" id="posAppDesired" disabled>
<option selecte disabled>Choose...</option>
</select>
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="addPositionId"disabled>Add</button>
</div>
</div>
</div>
</div>
<!-- FOR TEMPLATE -->
<div class="form-row" id="desiredPosition"></div>
<!-- MY TEMPLATE -->
<template id="positionApplied">
<div class="form-group col-sm-9 posLine">
<div class="input-group">
<select class="custom-select templatePositionClass" id="templatePosition" aria-label="Example select with button addon">
<option selected>Choose...</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<div class="input-group-append">
<button class="btn btn-outline-secondary addPosButton" type="button">Add</button>
<button class="btn btn-outline-secondary removePosButton" type="button">Remove</button>
</div>
</div>
</div>
</template>
My JavaScript code:
<script>
var arrayOfPositions;
var currentlyAddedPositions = [];
document.getElementById("addPositionId").addEventListener("click", displayAddPosition);
document.getElementById("desiredPosition").addEventListener("click", afterDesiredPositionClicked);
function conditionOKAY(){
var rollNum = document.getElementById("rnum").value;
var appCat = document.getElementById("posCat").value;
document.getElementById("posAppDesired").disabled = false;
document.getElementById("addPositionId").disabled = false;
google.script.run.withSuccessHandler(positionCategoryCheck).getPositionCategory(IDNum, appCat);
}
function positionCategoryCheck(returnedPositions){
arrayOfPositions = returnedPositions.filter(function(r){ return true; });
var positionApplying = document.getElementById("posAppDesired");
uniquePositions(positionApplying, arrayOfPositions, 0);
}
function uniquePositions(el, arrayOfPositions, index){
// var currentlyAddedPositions = [];
el.innerHTML = '<option selected disabled style="font-color: #B0B0B0;" value=""> Select Desired Station</option>';
arrayOfPositions.forEach(function(r){
if(currentlyAddedPositions.indexOf(r[index]) === -1){
var option = document.createElement("option");
option.textContent = r[index];
el.appendChild(option);
currentlyAddedPositions.push(r[index]);
}
});
}
//------FOR DESIRED POSITION/S----////
function displayAddPosition(arrayOfPositions){
var addPosition = document.getElementById("desiredPosition");
var positionTemplate = document.getElementById("positionApplied");
var copyTemplate = positionTemplate.content.cloneNode(true);
addPosition.appendChild(copyTemplate);
var testPost = document.querySelector(".templatePositionClass").closest(".posLine");
var copiedPost = [];
testPost.innerHTML = '<option selected disabled style="font-color: #B0B0B0;" value=""> Select Desired Station</option>';
currentlyAddedPositions.forEach(function(r){
if(copiedPost.indexOf(r) === -1){
var option = document.createElement("option");
option.textContent = r;
testPost.appendChild(option);
copiedPost.push(r[0]);
}
});
}
function removePosition(){
document.getElementById("desiredPosition")
}
function afterDesiredPositionClicked(e){
if (e.target.matches(".addPosButton *, .addPosButton")){
displayAddPosition();
} else if (e.target.matches(".removePosButton *, .removePosButton")){
e.target.closest(".posLine").remove();
}
}
</script>
My Google Apps Script code:
function getPositionCategory(IDNum, appCat){
if(appCat == "Main"){
const ss = SpreadsheetApp.openByUrl(urlPrequalData);
const ws = ss.getSheetByName("VacantPositions");
const posSelection = ws.getRange(1,1,1, ws.getLastColumn()).getValues()[0];
var index = posSelection.indexOf(appCat)+1;
var posValues = ws.getRange(2, index, ws.getLastRow()-1, 1).getValues();
return posValues;
}
The JavaScript code above was able to add the template, and then change the innerHTML of the option element of that template. But if I click the add button again, the option element of the additional template does not change.
My aim is every time I clicked the "Add" button, it will load the template and right after the template loads, change the option in the Select Element of that template.

data transfer multiple var

I'm making a website that sells keyboards stuff and I want to transfer and display multiple options selected by a user in a text field separated with commas(,) I tried using document.getElementById("product", "product2") but it does not work.
Here's what I have for now.
<div class="input-name">
<label for="products">Cases: </label>
<select name="product" id="product" class="larger" onchange="change()">
<option selected>--Please select--</option>
<script>productlist1()</script>
</select>
</div>
<div class="input-name">
<label for="products">Keycaps: </label>
<select name="product" id="product2" class="larger" onchange="change()">
<option selected>--Please select--</option>
<script>productlist2()</script>
</select>
</div>
<div class="input-name">
<label for="subject" id="subjectLabel">RE: Enquiry on</label>
<input type="text" name="subject" id="subject" class="subject_1" readonly>
</div>
function storeSub() {
document.getElementById("product").selectedIndex = sessionStorage.productIndex;
var product = document.getElementById("product").value;
sessionStorage.subject = product;
document.getElementById("subject").value = sessionStorage.subject;
}
function productlist1() {
var select = document.getElementById("product");
var options = ["Case1", "Case2", "Case3", "Case4"];
for (var i = 0; i < options.length; i++) {
var opt = options[i];
var el = document.createElement("option");
el.textContent = opt;
el.value = opt;
select.appendChild(el);
}
}
function productlist2() {
var select = document.getElementById("product2");
var options = ["Keycaps1", "Keycaps2", "Keycaps3", "Keycaps4"];
for (var i = 0; i < options.length; i++) {
var opt = options[i];
var el = document.createElement("option");
el.textContent = opt;
el.value = opt;
select.appendChild(el);
}
}
function change() {
var product = document.getElementById("product").value;
sessionStorage.product = product;
document.getElementById("subject").value = sessionStorage.product;
}
You can attach a change event listener changeSelection to both select elements. So once anything is selected or a selection is changed, the listener will be invoked and the event is automatically passed as an argument.
Now Inside changeSelection listener, you can get the selected option by event.target.value.
You can use a Set to uniquely keep track of the selections. To retrieve the selections as a comma-separated string, you just need to convert the Set to an array and join it with comma.
document.addEventListener("DOMContentLoaded", function(){
let select1 = document.getElementById("product");
let options1 = ["Case1", "Case2", "Case3", "Case4"];
options1.forEach(option => {
let el = document.createElement("option");
el.textContent = option;
el.value = option;
select1.appendChild(el);
})
select1.addEventListener('change', changeSelection)
let select2 = document.getElementById("product2");
let options2 = ["Keycaps1", "Keycaps2", "Keycaps3", "Keycaps4"];
options2.forEach(option => {
let el = document.createElement("option");
el.textContent = option;
el.value = option;
select2.appendChild(el);
})
select2.addEventListener('change', changeSelection)
});
const selections = new Set();
function changeSelection(event){
selections.add(event.target.value)
let subjectInput = document.getElementById("subject");
subjectInput.value = Array.from(selections).join(',');
}
<div class="input-name">
<label for="products">Cases: </label>
<select name="product" id="product" class="larger">
<option selected>--Please select--</option>
</select>
</div>
<div class="input-name">
<label for="products">Keycaps: </label>
<select name="product" id="product2" class="larger">
<option selected>--Please select--</option>
</select>
</div>
<div class="input-name">
<label for="subject" id="subjectLabel">RE: Enquiry on</label>
<input type="text" name="subject" id="subject" class="subject_1" readonly>
</div>

bootstrap 4 selectpicker how to add 'subtext' dynamically

Working with Bootstrap-4 I'm trying to dynamically add 'data-subtext' next to all the option texts of a selectpicker. Using the below code is ok with creating the list of options out of the array. But I failed to find how to add the data-subtext text as well.
Here is the relevant code:
<!---HTML part,use function to insert list of options ------>
<div class="form-group mr-2">
<div class="col-mr-2">
<div class="input-group">
<div class="input-group-append">
<select class="selectpicker w-100" data-show-subtext="true" data-live-search="true" id="buttNameSel" name="buttNameF" onChange="replacButtName()">
<option data-subtext="mysubtext_list" >select-from:</option>
<!------ autofill the options---------->
</select>
</div>
</div>
</div>
</div>
<script type="text/javascript" >
// set option list of names
selButtname = document.getElementById( 'buttNameSel' );
var opt;
for (i=0; i < nItems;i++) {
buttName = ButtNamesSplitList[i];
opt = document.createElement("option");
opt.text=buttName ;
selButtname.add(opt);
}
$('.selectpicker').selectpicker('refresh');
</script>
You an update your code to add the attribute like this:
<script type="text/javascript" >
// set option list of names
selButtname = document.getElementById( 'buttNameSel' );
var opt;
for (i=0; i < nItems;i++) {
buttName = ButtNamesSplitList[i];
opt = document.createElement("option");
opt.text=buttName ;
opt.setAttribute("data-subtext", "your_sub_text"); //add subtext here
selButtname.add(opt);
}
$('.selectpicker').selectpicker('refresh');
</script>
You can find more information how setAttribute works from this documentation: https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute

Why select field not displaying?

I'm trying to add select field by both ways first is dynamically and giving values to select fields.
while trying with dynamically so it is working well. but when trying to display some select field by
giving value to '1st room child' select field so first time im receiving the output but second time its
doesn't worked
$(function () {
/*here my values to increment whenever added newly form */
var i = 1;
i++;
var max_fields = 6;
var this_button_work_for_click_to_add_rooms = $(".this_button_work_for_click_to_add_rooms");
var this_is_field_wrapper = $(".this_is_field_wrapper");
//here we starting counting...
var input_count = 1;
//add buttong dynamically over here...
$(this_button_work_for_click_to_add_rooms).click(function (event) {
/* Act on the event */
if (input_count < max_fields) {
input_count++;
var add_fields = '<div><div class="row"><div class="form-group"><div class="col-xs-1"><h6>Options -</h6><h6 class="#">Adults(12+)</h6><select id="selected_adults[]" name="selected_adults[]" class="form-control"><option value="1">1</option><option selected="selected" value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option></select></div><!-- </div><div class="form-group"> --><div class="col-xs-1"><h6>' + input_count + ' Room</h6><h6 class="m_label">Child(0-12)</h6><select id="selected_childs[]" name="selected_childs[]" onchange="displayingNumberOfChildAge(this);" class="form-control"><option>select</option><option id="first_child_col" value="1">1</option><option id="second_child_col" value="2">2</option></select></div><!-- </div><div class="form-group"> --><div id="childage0" class="col-xs-1"><h6></h6></div><div id="childage1" class="col-xs-1"><h6></h6></div>remove</div><!-- here ending form group --></div><!-- here ending row --></div>';
$(this_is_field_wrapper).append(add_fields);
}
});
$(this_is_field_wrapper).on('click', '.remove_input_button', function (e) {
e.preventDefault();
$(this).parent('div').remove();
input_count--;
});
});
function addFields() {
var number = document.getElementById("selected_childs[]").value;
var childage = document.getElementById("childage0");
//Create array of options to be added
var array = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
while (childage.hasChildNodes()) {
childage.removeChild(childage.lastChild);
}
if (number == 1) {
// statement
for (i = 0; i < number; i++) {
var h = document.createElement("h6");
h.setAttribute("id", "firstever");
var h1 = document.createElement("h6");
h1.appendChild(document.createTextNode("select child age"));
childage.appendChild(h1);
h.appendChild(document.createTextNode("Children Age " + (i + 1)));
childage.appendChild(h);
var selectList = document.createElement("select");
selectList.setAttribute("id", "mySelect");
selectList.setAttribute("class", "form-control");
childage.appendChild(selectList);
childage.appendChild(document.createElement("br"));
//Create and append the options
for (var j = 0; j < array.length; j++) {
var option = document.createElement("option");
option.setAttribute("value", array[j]);
option.text = array[j];
selectList.appendChild(option);
}
}
} else {
// statement
for (i = 0; i < number; i++) {
childage = document.getElementById("childage" + i);
var h1 = document.createElement("h6");
h1.setAttribute("id", "secondever");
h1.appendChild(document.createTextNode("select child age"));
childage.appendChild(h1);
var h = document.createElement("h6");
h.appendChild(document.createTextNode("Children Age " + (i + 1)));
childage.appendChild(h);
var selectList = document.createElement("select");
selectList.setAttribute("id", "mySelect");
selectList.setAttribute("class", "form-control");
childage.appendChild(selectList);
childage.appendChild(document.createElement("br"));
//Create and append the options
for (var j = 0; j < array.length; j++) {
var option = document.createElement("option");
option.setAttribute("value", array[j]);
option.text = array[j];
selectList.appendChild(option);
}
}
}
}
<!DOCTYPE html>
<html>
<head>
<title>Welcome|Home</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<form method="POST" action="<?php echo base_url(); ?>index.php/dynamically_added_controller/Dynamically/addingValues">
<div class="this_is_field_wrapper">
<div class="row">
<div class="form-group">
<div class="col-xs-1">
<h6>Options -</h6>
<h6 class="#">Adults(12+)</h6>
<select id="selected_adults[]" name="selected_adults[]" class="form-control">
<option value="1">1</option>
<option selected="selected" value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
<div class="col-xs-1">
<h6>1st Room</h6>
<h6 class="m_label">Child(0-12)</h6>
<select id="selected_childs[]" name="selected_childs[]" value="" onchange="addFields()" class="form-control">
<option>--select--</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
</div>
<div id="childage0" class="col-xs-1">
<h6></h6>
</div>
<div id="childage1" class="col-xs-1">
<h6></h6>
</div>
<div class="col-xs-1">
Click & Add Rooms
</div>
</div>
</div>
</div>
<button type="submit" value="submit">click to submit</button>
</form>
</body>
</html>
As you have seen the problem is while attempting second time to display select field by giving value to '1st room child' select field so it is not working.
Your problem is something called "delegation." When you dynamically add something to the DOM that wasn't there when it was first loaded, you have to look through a pre-existing parent first.
Consider this. You have an existing element: <div id="loaded"></div>
Then, you dynamically add something in that div: <button type="button" id="someButton">
In order to get to listen for that click, you have to go through the parent div since it's an original part of the DOM.
$('#loaded').on('click', '#someButton', function () {
//do something
});

Javascript - added Orange once in fruitslist drop down list

<html>
<head>
<script>
function addfruits()
{
for(i = 0; i < document.getElementById("fruits").options.length; i++)
{
if(document.getElementById("fruits").options[i].selected)
{
var fruitslist = document.getElementById("fruitslist");
var option = document.createElement("option");
option.text = document.getElementById("fruits").options[i].text;
fruitslist.add(option);
}
}
}
</script>
</head>
<body>
<select id="fruits" name="fruits[]" multiple>
<option value="apple">Apple</option>
<option value="orange">Orange</option>
<option value="pear">Pear</option>
<option value="grape">Grape</option>
</select>
<input type="submit" name="submit" value=">>" onclick="addfruits()" />
<select id="fruitslist" name="fruitslist[]" style="width: 70px;" multiple>
</select>
</body>
</html>
From above code, first I select Orange from drop down list and click >> button, the Orange value will added in fruitslist drop down list. After that. I select Orange again from drop down list and click >> button, the Orange value will added again in fruitslist drop down list. However, I just want the Orange value added in fruitslist drop down list once. How should I modify it? Can someone help me?
Here is the fix.
<html>
<head>
<script>
function addfruits()
{
for(i = 0; i < document.getElementById("fruits").options.length; i++)
{
if(document.getElementById("fruits").options[i].selected && !isAddedAlready(document.getElementById("fruits").options[i].text))
{
var fruitslist = document.getElementById("fruitslist");
var option = document.createElement("option");
option.text = document.getElementById("fruits").options[i].text;
fruitslist.add(option);
}
}
}
function isAddedAlready(text) {
var fruitslist = document.getElementById("fruitslist");
if(fruitslist.length ==0) return false;
for(var i=0; i<fruitslist.length; i++) {
if(fruitslist.options[i].text === text) return true;
}
return false;
}
</script>
</head>
<body>
<select id="fruits" name="fruits[]" multiple>
<option value="apple">Apple</option>
<option value="orange">Orange</option>
<option value="pear">Pear</option>
<option value="grape">Grape</option>
</select>
<input type="submit" name="submit" value=">>" onclick="addfruits()" />
<select id="fruitslist" name="fruitslist[]" style="width: 70px;" multiple>
</select>
</body>
</html>
Try changing your addFruits function to the following:
function addfruits()
{
for (var i = 0; i < document.getElementById("fruits").options.length; i++)
{
if (document.getElementById("fruits").options[i].selected)
{
var optionText = document.getElementById("fruits").options[i].text;
var fruitslist = document.getElementById("fruitslist");
var found = false;
//Does the item clicked on already exist in the destination list?
for (var j = 0; j < fruitslist.length; j++) {
if (fruitslist[j].text == optionText) {
found = true;
break;
}
}
//If the item does not exist, add it to the list.
if (!found) {
var option = document.createElement("option");
option.text = optionText;
fruitslist.add(option);
}
}
}
}
The important thing to do here is first check that the fruitslist does not contain the item that was clicked on, hence that additional for-loop.

Categories

Resources