I am teaching myself how to code. My first project is a webApp using Apps Script. I've managed to complete most of it on my own except for one thing... I can't seem to output the items from a Multiple Select box into a comma separated array of values.
Currently, I've managed to return a single value when only one of the list items is selected. Reference: example 1
But if I choose more than one, nothing happens. Reference: example 2
Essentially, what I'm trying to accomplish is this:
If... Bill and Mary] ... are selected from a list, their corresponding ages are output as... {33,44}. Or if... [Bill, Mary, and Joe] ...are selected, the result is {33,44,21}.
The data is pulled from a single sheet with 2 columns ('Staff' & 'Ages'). The list is also dynamically infinite.
In case my request is confusing, this resource clearly demonstrates what I'm trying to achieve but I just can't seem to crack it.
Hopefully this advanced community can help me solve this challenge.
Now, here's the Code.gs and Javascript for reference.
(NOTE: I'm looking for a Javascript solution only please. Also, pardon my formatting of this virgin post.)
Code.gs
function doGet(e){
var ss = SpreadsheetApp.openById(ssID);
var ws = ss.getSheetByName("Values");
var posts = ws.getRange(1,1,ws.getRange("A1").getDataRegion().getLastRow(),1).getValues();
var postListArray = posts.map(function(r){ return '<option>' + r[0] + '</option>'; }).join('');
var tmp = HtmlService.createTemplateFromFile("page");
tmp.posts = postListArray;
return tmp.evaluate();
}
function getAges(uStaff){
var ss = SpreadsheetApp.openById(ssID);
var ws = ss.getSheetByName("Values");
var data = ws.getRange(1, 1, ws.getLastRow(), 2).getValues();
var staffList = data.map(function(r){ return r[0]; });
var agesList = data.map(function(r){ return r[1]; });
var position = staffList.indexOf(uStaff);
if(position > -1){
return agesList[position];
} else {
return 'Invalid';
}
}
Javascript
document.getElementById("staff").addEventListener("change",getRecs);
function getRecs(){
var uStaff = document.getElementById("staff").value;
google.script.run.withSuccessHandler(updateAges).getAges(uStaff);
}
function updateAges(ages){
document.getElementById("age").value = ages;
}
HTML
<div class="row">
<div class="input-field col s6">
<select id="staff" multiple>
<?!= posts; ?>
</select>
<label for="staff" style="font-size: 20px;">Staff</label>
</div>
<div class="input-field col s6">
<input type="text" id="age" class="validate" disabled>
</div>
</div>
HTMLSelectElement.value
only returns the first selected value.HTMLSelectElement.selectedOptions
to get all selected HTMLOptionElement
valuevar uStaff = [...(document.getElementById("staff").selectedOptions)]
.map(e=>e.value);//uStaff is a array of staffs. eg ['Bill', 'Mary']
You should then modify your getAges
server function to work with a array argument instead of a single value. Alternatively, You should pass the whole data as 2D array to client side, use Map
to get the age
:
Server side:
function getData(){
var ss = SpreadsheetApp.openById(ssID);
var ws = ss.getSheetByName("Values");
var data = ws.getRange(1, 1, ws.getLastRow(), 2).getValues();
return data;
}
Client side:
document.getElementById("staff").addEventListener("change",getRecs);
var map = null;
function getRecs(){
if(!map) {//call server if data is not retrieved previously
google.script.run.withSuccessHandler(updateAges).getData()
} else {updateAges()};
}
function updateAges(arr){
if(!map) map = new Map(arr);//map of [[staffs,ages]]
let uStaff = document.getElementById("staff").selectedOptions;
let ages = [...uStaff].map(staff=>map.get(staff.value)).join();
document.getElementById("age").value = ages;
}