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

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.

Related

Setting dropdown values in Javascript

I have a dropdown with following HTML.
<select name="custom_123" id="custom_123_123" class="custom form-control form-control-full form-select searchable abcd-done" style="display: none;">
<option value="" selected="selected">None</option>
<option value="1">Alaska</option>
<option value="2">Newyork</option>
</select>
<div id="custom_123_123_abcd" class="abcd-container abcd-container-single abcd-container-
active" style="width: 100%"><a href="javascript:void(0)" class="abcd-single"
tabindex="-1"><span>Alaska</span></a>
</div>
I want to be able to select Newyork in the dropdown. For that, I am during the following.
var dropdown_id = document.querySelector('[id^="custom_123"]').id;
var dropdown_abcd = dropdown_id + 'abcd';
document.getElementById(dropdown_abcd).getElementsByClassName("abcd-single")[0].innerHTML = "Alaska";
But the same doesn't get applied. Can anyone help?
Here is an example based on your code:
const select = document.querySelector('[id^="custom_123"]');
select.value = 'Alaska';
Update on comment
If there are listeners on the select, here is an example on how to fire a change event.
const select = document.querySelector('[id^="custom_123"]');
select.value = 'Alaska';
select.dispatchEvent(new CustomEvent('change'));

How to make dependent dropdown list from Google Sheet?

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
};

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

JavaScript: Remove HTML form input group

I'm having some issues getting the removeElement function to work as expected. I want the addElement function to add a new input group with a dropdown and a Remove button (which it does). The Remove button should call the removeElement function, removing the respective input group, which it does the first time but no more.
Here is the Code:
function addElement(parentId, elementTag, elementId, html) {
// Adds an element to the document
var p = document.getElementById(parentId);
var newElement = document.createElement(elementTag);
newElement.setAttribute('id', elementId);
newElement.innerHTML = html;
p.appendChild(newElement);
}
function removeElement(elementId) {
// Removes an element from the document
var element = document.getElementById(elementId);
element.parentNode.removeChild(element);
}
var serviceID = 0; // reset number of services added
function addService() {
serviceID++; // increment for UID for new input
var html = `<div class="form-row"><div class="form-group col-6"><select name="service[]" class="form-control"><option value="basic">Basic Service</option><option value="full">Full Service</option><option value="tie">Ski Tie</option></select></div><div class="form-group col-3"><input type="button" class="btn btn-danger" onclick="javascript:removeElement('service' + serviceID + ''); return false;" value="Remove"></div></div>`;
addElement('services', 'div', 'service' + serviceID, html);
}
<div id="services">
<h4>Services</h4><br>
<div class="form-row">
<div class="form-group col-6">
<select name="service[]" class="form-control">
<option value="basic">Basic Service</option>
<option value="full">Full Service</option>
<option value="tie">Ski Tie</option>
</select>
</div>
</div><br>
There seems to be two issues in your code (based on what you have shared)
serviceID needs to be declared globally so that onclick handler can access the same.
No element is assigned the id as services
like
<h4 id="services">Services</h4><br>
Finally you need to invoke addService method as well.
Demo
var serviceID = 0;
function addElement(parentId, elementTag, elementId, html) {
// Adds an element to the document
var p = document.getElementById(parentId);
var newElement = document.createElement(elementTag);
newElement.setAttribute('id', elementId);
newElement.innerHTML = html;
p.appendChild(newElement);
}
function removeElement(elementId) {
// Removes an element from the document
var element = document.getElementById(elementId);
element.parentNode.removeChild(element);
}
function addService() {
serviceID++; // increment for UID for new input
var html = `<div class="form-row"><div class="form-group col-6"><select name="service[]" class="form-control"><option value="basic">Basic Service</option><option value="full">Full Service</option><option value="tie">Ski Tie</option></select></div><div class="form-group col-3"><input type="button" class="btn btn-danger" onclick="javascript:removeElement('service' + serviceID + ''); return false;" value="Remove"></div></div>`;
addElement('services', 'div', 'service' + serviceID, html);
}
addService() ;
<h4 id="services">Services</h4><br>
<div class="form-row">
<div class="form-group col-6">
<select name="service[]" class="form-control">
<option value="basic">Basic Service</option>
<option value="full">Full Service</option>
<option value="tie">Ski Tie</option>
</select>
</div>
</div>

How to get the index of a selected item in listbox and add to listbox two with button?

I am looking to get the index of the selected item in a list box to add the selected item to list box 2.
The listbox was created in HTML.
<div class="clearfix">
<div class="select-container">
<select name="sometext" size="5">
<?
var sheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(sheet.getSheets()[1]);
var lastRow = sheet.getLastRow();
var myRange = sheet.getRange("A1:A"+lastRow);
var data = myRange.getValues();
?>
<? for (var i = 0; i < data.length; ++i) { ?>
<option><?!= data[i] ?></option>
<? } ?>
</select>
</div>
<div class="buttons">
<div><button onclick='addMonitoredFolder()' id='button1'>Add</button></div>
</div>
So when I press button 'Add', I want the currently selected item in list box 1 to be added to listbox 2. It would be good that if the user selects multiple options in the list then it will add these or at least know how to handle this. I have function addMonitoredFolder in there because I was trying to figure it out by just can't get my head around it.
<div class="select-container">
<select name="sometext" size="5">
<option>option</option>
</select>
</div>
Thanks!
Here is code that can get multiple selections from a list, and transfer the choices to the second list:
index.html
<!DOCTYPE html>
<html>
<body>
<div>List Box One</div>
<select id="slctOne" multiple>
<option value="one">Value One</option>
<option value="two">Value Two</option>
<option value="three">Value Three</option>
<option value="four">Value Four</option>
</select>
<div>List Box Two</div>
<select id="slctTwo" multiple>
<option value="one">Value One</option>
<option value="two">Value Two</option>
<option value="three">Value Three</option>
<option value="four">Value Four</option>
</select>
<button onmouseup="getAndTransfer()">Get Choices</button>
<p>Hold down the Ctrl (windows) / Command (Mac) button to select multiple options.</p>
<!-- Use a templated HTML printing scriptlet to import JavaScript. -->
<?!= HtmlService.createHtmlOutputFromFile('JavaScript').getContent(); ?>
</body>
</html>
JavaScript.html
<script>
window.getAndTransfer = function() {
var allChoices = getMultiple();
putChoicesIntoSelectTwo(allChoices);
};
window.getMultiple = function() {
//console.log('getMultiple ran')
var allOptionNodesSelected = document.getElementById('slctOne').querySelectorAll('option:checked');
var howManySelected = allOptionNodesSelected.length;
console.log('number of option nodes: ' + howManySelected);
var optionElmt1 = allOptionNodesSelected[0];
console.log('optionElmt1.selected: ' + optionElmt1.selected);
var i=0,
arryAllOptions = [];
for(i=0;i<howManySelected;i+=1) {
console.log('optionElmt1.selected: ' + allOptionNodesSelected[i].value);
arryAllOptions.push(allOptionNodesSelected[i].value);
};
return arryAllOptions;
};
window.putChoicesIntoSelectTwo = function(theChoices) {
//Get select list two element
var selectListTwo = document.getElementById('slctTwo');
var allOptions = selectListTwo.getElementsByTagName("option"); //Get all current options inside of this select tag
var i = 0, thisOptionVal="";
//console.log(allOptions.length);
for (i=0;i<allOptions.length;i+=1) {
thisOptionVal = allOptions[i].value;
if (theChoices.indexOf(thisOptionVal) !== -1) {
allOptions[i].selected = true;
} else {
allOptions[i].selected = false;
};
};
};
</script>

Categories

Resources