How to create a drop down menu with values from spreadsheet? - javascript

I'm trying to create a drop down menu and the values inside are in a specific column of a spreadsheet.
I tried making cells with foo but i don't know how to call them to my html file. Is this efficient? Or can you show me another way to call them to my html file.
Tried this code but no idea on how to return this to html.
function email_dropdown(divname)
{
var open_sheet = SpreadsheetApp.openByUrl(')getSheetByName');
SpreadsheetApp.setActiveSpreadsheet(open_sheet);
var active_sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('*********');
active_sheet.activate();
var dropdown = "<select id = 'email_dropdown'> Email";
var row_val = active_sheet.getRange("**").getValues();
var row_length = row_val.length;
var row_data = active_sheet.getRange("**");
for (var row = 2; row <= row_length; row++)
{
dropdown = dropdown + row_data.getCell(**).getValue();
}
dropdown = dropdown + "</select>"
Logger.log(dropdown);
}

Cool, You have gotten most of this solved :) Now you need to do something like the following since you have the values in the array
function yourTestfunction() {
var exampleValues = ['one', 'two', 'three'];
// after your values have been stored in the array
var sheetValuesEl = document.querySelector("#js_sheetValues");
// populate select with values
for(var i = 0; i < exampleValues.length; i++) {
// Create the option
var optionValue = document.createElement("option");
// Set the option text
optionValue.textContent = exampleValues[i];
// Add the option to the select drop down
sheetValuesEl.appendChild(optionValue);
}
}
yourTestfunction()
<select id="js_sheetValues"></select>

Related

How do I add a new value to a Google Sheet from a text field in a Web App and then automatically update the associated dropdown?

WARNING: I'm not a programmer by trade.
Ok. Got the disclaimer out of the way. So this might not be the best way to do this but here is the scenario. I have a dropdown that gets populated via a Google Sheet. The user chooses a selection from the list but this dropdown does not have all of the possible values it could have. There will likely be a time when the user needs a new value added. While I could manually update the spreadsheet as new values are requested that introduces an element of human availability to get this done and I'm not always available.
What I would prefer is a self-serve model. I want to supply the user with a text field where they can enter the new value and submit it to the Google Sheet. Then I would like the dropdown to be updated with the new value for the user to choose.
Now, I realize that I could just submit the value in the new field to the Google Sheet but that will require building a condition to see whether it is the dropdown or text field that has a value in it. I'd also need some type of error handling in case both the dropdown and text field have values. That seems like a bigger headache to program then my ask.
I'm not sure what code you would need to see to help make this work but here is what I think might help.
doGet function
function doGet(e){
var ss = SpreadsheetApp.openById(ssId)
var ws = ss.getSheetByName("External");
var range = ws.getRange("A2:D2");
var valuesArray = [];
for (var i = 1; i <= range.getLastColumn(); i++){
var lastRowInColumn = range.getCell(1, i).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
var list = ws.getRange(2,i,lastRowInColumn-1,1).getValues();
valuesArray.push(list);
}
var userEmail = Session.getActiveUser().getEmail();
var sourceListArray = valuesArray[2].map(function(r){ return '<option>' + r[0] + '</option>'; }).join('');
var productListArray = valuesArray[3].map(function(r){ return '<option>' + r[0] + '</option>'; }).join('');
var tmp = HtmlService.createTemplateFromFile("config");
tmp.productList = productListArray;
return tmp.evaluate();
}
Add to Google Sheet
function userClicked(tagInfo){
var ss = SpreadsheetApp.openById(ssId)
var ws = ss.getSheetByName("Data");
ws.appendRow([tagInfo.email, tagInfo.source, tagInfo.product, new Date()]);
}
Add record
function addRecord(){
var tagInfo = {};
tagInfo.product = document.getElementById("product").value;
google.script.run.userClicked(tagInfo);
var myApp = document.getElementById("source");
myApp.selectedIndex = 0;
M.FormSelect.init(myApp);
var myApp = document.getElementById("brand");
myApp.selectedIndex = 0;
M.FormSelect.init(myApp);
var myApp = document.getElementById("product");
myApp.selectedIndex = 0;
M.FormSelect.init(myApp);
}
How dropdowns are populated in the HTML.
<div class="input-field col s3">
<select id="product" onchange="buildURL()">
<option disabled selected value="">Choose a product</option>
<?!= productList; ?>
</select>
<label>Product</label>
</div>
Need to see anything else? I think it might be relatively easy to add the new value to the column but the tricky part seems to be the update of only that one dropdown and not the entire app. To me it seems like I want to trigger the doGet() function again but only for that specific dropdown. Thoughts?
UPDATE: current code to add new value to dropdown
function addProduct() {
let newProd = document.getElementById("newProduct").value;
google.script.run.withSuccessHandler(updateProductDropdown).addNewProduct(newProd);
document.getElementById("newProduct").value = "";
}
function updateProductDropdown(newProd){
var newOption = document.createElement('option');
newOption.value = newProd;
newOption.text = newProd;
document.getElementById('product').add(newOption);
}
UPDATE2: App Scripts function to add new value to column in spreadsheet
function addNewProduct(newProd){
var columnLetterToGet, columnNumberToGet, direction, lastRow, lastRowInThisColWithData, rng, rowToSet, startOfSearch, valuesToSet;
var ss = SpreadsheetApp.openById(ssId);
var ws = ss.getSheetByName("List Source - External");
lastRow = ws.getLastRow();
//Logger.log('lastRow: ' + lastRow)
columnNumberToGet = 9;//Edit this and enter the column number
columnLetterToGet = "I";//Edit this and enter the column letter to get
startOfSearch = columnLetterToGet + (lastRow).toString();//Edit and replace with column letter to get
//Logger.log('startOfSearch: ' + startOfSearch)
rng = ws.getRange(startOfSearch);
direction = rng.getNextDataCell(SpreadsheetApp.Direction.UP);//This starts
//the search at the bottom of the sheet and goes up until it finds the
//first cell with a value in it
//Logger.log('Last Cell: ' + direction.getA1Notation())
lastRowInThisColWithData = direction.getRow();
//Logger.log('lastRowInThisColWithData: ' + lastRowInThisColWithData)
rowToSet = lastRowInThisColWithData + 1;
valuesToSet = [newProd];
ws.getRange(rowToSet, 9).setValues([valuesToSet]);
return newProd;
}
SOLUTION to Update Materialize Dropdown
function updateProductDropdown(newProd){
newProdOption = document.getElementById('product');
newProdOption.innerHTML += '<option>' + newProd + '</option>';
var elems = document.querySelectorAll('select');
var instances = M.FormSelect.init(elems);
}
You can specify a client side callback function if you use google.script.run withSuccessHandler(callback) where your callback could update the list only and not the whole site.
Example:
google.script.run.withSuccessHandler(updateDropdownWidget).updateDropdownList(text_from_input)
Where updateDrownList(text_from_input) is a function in your Apps Script that adds text to the sheet using SpreadsheetApp for example, and returns the "text" to the callback function: updateDropdownWidget(text) which adds a new list item to the HTML drop-down list in your front end.
index.html:
<form>
<label for="newOption">New option for the dropdown:</label>
<input type="text" id="nopt" name="newOption">
<input type="button" value="Submit"
onclick="google.script.run.withSuccessHandler(updateDropdownWidget)
.updateDropdownList(document.getElementById('nopt').value)">
</form>
<label for="cars">Choose a car:</label>
<select name="cars" id="cars">
<?!= values; ?>
</select>
<script>
function updateDropdownWidget(text){
var option = document.createElement('option');
option.value = text;
option.text = text;
document.getElementById('cars').add(option);
}
</script>
Code.gs:
function doGet(e){
var ss = SpreadsheetApp.getActiveSheet();
var lastRow = ss.getDataRange().getLastRow();
var values = ss.getRange(1,1,lastRow,1).getValues();
var valuesArray = [];
for (var i = 0; i < values.length; i++){
valuesArray.push('<option value="'+values[i]+'">' +values[i]+ '</option>');
}
var tmp = HtmlService.createTemplateFromFile("index");
tmp.values = valuesArray;
return tmp.evaluate();
}
function updateDropdownList(text_from_input){
// Log the user input to the console
console.log(text_from_input);
// Write it to the sheet below the rest of the options
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = sheet.getDataRange().getLastRow();
sheet.getRange(lastRow+1,1).setValue(text_from_input);
// Return the value to the callback
return text_from_input;
}
Here's an example:
In my Stack Over Flow spreadsheet I four buttons which can be used to run any function in 3 script files and every time I load the sidebar it reads the functions in those script files and returns them to each of the select boxes next to each button so that I test functions that I write for SO with a single click and I can select any function for any button. Here's the Javascript:
$(function(){//JQuery readystate function
google.script.run
.withSuccessHandler(function(vA){
let idA=["func1","func2","func3","func4"];
idA.forEach(function(id){
updateSelect(vA,id);
});
})
.getProjectFunctionNames();
})
Here is GS:
function getProjectFunctionNames() {
const vfilesA=["ag1","ag2","ag3"];
const scriptId="script id";
const url = "https://script.googleapis.com/v1/projects/" + scriptId + "/content?fields=files(functionSet%2Cname)";
const options = {"method":"get","headers": {"Authorization": "Bearer " + ScriptApp.getOAuthToken()}};
const res = UrlFetchApp.fetch(url, options);
let html=res.getContentText();
//SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html), "Project Functions");
let data=JSON.parse(res.getContentText());
let funcList=[];
let files=data.files;
files.forEach(function(Obj){
if(vfilesA.indexOf(Obj.name)!=-1) {
if(Obj.functionSet.values) {
Obj.functionSet.values.forEach(function(fObj){
funcList.push(fObj.name);
});
}
}
});
//SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(funcList.join(', ')), "Project Functions");
return funcList;//returns to withSuccessHandler
}
Image:
Animation:

find values of custom attribute in html using Jquery

Click here for code
Inside loop of {listOfValue}
i want to find different column values filtered by data-week = {listofvalueObject}
and want to add data in each row based on column segregated by this data-week attributes value.
I have assigned the values form a list so it every column has different data-week value.
I have tried :
var allColumnValClass = j$('.columnVal').filter('[data-week]');
var allColumnValClass = j$('.columnVal').filter('[data-week='Something dynamic ']');
You should be able to select them like this:
var allColumnValClass = j$('.columnVal[data-week]')
and
var allColumnValClass = j$('.columnVal[data-week="' + Something dynamic + '"]')
Hope this helps.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='columnVal' data-week="1"></div>
<div class='columnVal' data-week="2"></div>
<div class='columnVal' data-week="3"></div>
<script>
var dataList = $(".columnVal").map(function () {
return $(this).data("week");
}).get();
for (var i = 0; i < dataList.length; i++) {
console.log(dataList[i]);
}
</script>
cheers

How can I get data of selected table rows?

I am using the following snippet and from this I can find the index of a row which one is selected on the basis of checkbox on every row of the table.How can I modify this snippet so that I can get the selected row data instead of index?
Please Help!!
<script>
function myfunction3() {
var element_table = document.getElementsByName('collection');
var element_tableRows = element_table[0].rows;
var selectedTr = new Array();
var data = "";
for (var i = 0; i < element_tableRows.length; i++) {
var checkerbox = element_tableRows[i].cells[0].firstChild;
if (checkerbox.checked) {
data = data+ element_tableRows[i].getAttribute("name");
}
}
var element_paragraph = document.getElementsByName('description');
element_paragraph.innerHTML = data;
alert(data);
}
</script>
as TJ says, i dont see any index in your code. but try something like this which is cleaner
$('.collection tr').each(function () {
//processing this row
$(this).find('td input:checked').each(function () {
// there is checkbox and it is checked, do your business with it
var value_of_checkbox = $(this).val(); // which is 'data' that you wanted
});
});

Javascript Multiple Dependant Dropdowns

I am new to javascript and I'm struggling with the following code that will be in a form for registration of multiple candidates.
It creates 2 dependant select boxes (country and area) for each candidate.
Clicking the button 'Add Candidate' once allows the dependant boxes to work fine but clicking the button again stops it working. Accessing the selected values from the form when there is more than one candidate is also impossible as they will overwrite each other.
I have tried creating the select names as arrays using a count variable which I increment each time the ff function is called but I can't get it to work.
All help will be much appreciated!
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
<title>Select Populate Test</title>
<script>
var UnitedStates = new Array();
UnitedStates[0] = "Texas";
UnitedStates[1] = "California";
UnitedStates[2] = "Arizona";
UnitedStates[3] = "Nevada";
UnitedStates[4] = "Florida";
var UnitedKingdom = new Array();
UnitedKingdom[0] = "Surrey";
UnitedKingdom[1] = "Kent";
UnitedKingdom[2] = "Dorset";
UnitedKingdom[3] = "Hampshire";
function populateDropdown(arry)
{
document.myForm.stateSelect.options.length = 0;
for (var i = 0; i < arry.length; i++)
{
document.myForm.stateSelect.options[i] = new Option(arry[i], arry[i]);
}
}
function updateDropdown(str)
{
var stateArray
var selectedCountry;
var countryDropdown = document.myForm.countrySelect;
for (var i = 0; i < countryDropdown.options.length; i++)
{
if (countryDropdown.options[i].selected)
{
selectedCountry = countryDropdown.options[i].value;
}
}
if (selectedCountry == 1)
{
stateArray = UnitedStates;
populateDropdown(stateArray);
}
if (selectedCountry == 2)
{
stateArray = UnitedKingdom;
populateDropdown(stateArray);
}
}
counter = 0;
function ff()
{
counter++;
var box = document.getElementById("details"+counter);
var cselectBox = document.createElement("Select");
cselectBox.name="countrySelect";
cselectBox.onchange = function()
{
updateDropdown();
}
var option1 = document.createElement("OPTION");
option1.text="United States";
option1.value=1;
cselectBox.options.add(option1);
var option2 = document.createElement("OPTION");
option2.text="United Kingdom";
option2.value=2;
cselectBox.options.add(option2);
document.getElementById("details"+counter).innerHTML+="</p><p>"+counter+". Candidate Country";
box.appendChild(cselectBox);
var box2 = document.getElementById("detailsx"+counter);
var ccselectBox = document.createElement("Select");
ccselectBox.name="stateSelect";
document.getElementById("detailsx"+counter).innerHTML+="</p><p>"+counter+". Candidate City";
box2.appendChild(ccselectBox);
}
</script>
</head>
<body>
<form name="myForm" >
<input type="button" value="Add Candidate" onClick="ff(); populateDropdown(UnitedStates);"">
<!--- Note: 6 Candidates will be the maximum. -->
<div id="details1"><b></b></div>
<div id="detailsx1"><b></b></div>
<div id="details2"><b></b></div>
<div id="detailsx2"><b></b></div>
<div id="details3"><b></b></div>
<div id="detailsx3"><b></b></div>
<div id="details4"><b></b></div>
<div id="detailsx4"><b></b></div>
<div id="details5"><b></b></div>
<div id="detailsx5"><b></b></div>
<div id="details6"><b></b></div>
<div id="detailsx6"><b></b></div>
</form>
</body>
</html>
There are multiple problems here. We'll tackle the one you're dealing with first.
When you name multiple controls with the same name, like stateSelect, you'll get the first one each time you try to reference it. If you instead set the id to 'stateSelect' + counter, you'll get a unique id, which you can then retrieve with document.getElementById(). So in the function to populate the dropdown would look like this:
function populateDropdown(arry)
{
var stateSelect = document.getElementById('stateSelect'+counter);
stateSelect.options.length = 0;
for (var i = 0; i < arry.length; i++)
{
stateSelect.options[i] = new Option(arry[i], arry[i]);
}
}
here is the fiddle I used to verify those changes.
You'll also need to add an event to each country dropdown to repopulate the state dropdown when it changes, and the structure needs a little work for that. If you're not opposed to frameworks, knockout would make this incredibly simple to run.
Here is the fiddle with everything working correctly and comments added at key changes
Update: Added link to the fiddle(s)

JSF Extended Datatable Sorting and Filtering

I have a extended datatable, RICHFACES 3.3.3 with sorting and filtering enabled. The table is rendered dynamically. Based on the requirement, I need to disable certain rows(which contain editable fields) when the table is displayed.
I have that logic written in a Javascript function rowBlur(), and call it whenever the page is displayed. Hence, when the table is loaded the required rows are disabled as expected. The problem is whenever I filter/sort the table, the disabled rows get enabled again.
Is there any way I can call the javascript function whenever filter or sort happens?
Here is the code:
HtmlExtendedDataTable dynamicDataTable = new HtmlExtendedDataTable();
dynamicDataTable.setOnkeydown("filterAllOnEnter(event)");
function filterAllOnEnter(event) {
if(event.keyCode == 13) {
jQuery(".rich-filter-input").blur();
rowblur();
return false;
} else
return true;
}
// js code////////////
<script>
function show(){
val = '${myController.mergeWorkMap}';
}
</script>
<script>
function rowblur(){
for(var i=0;i<7;i++){
var firstCol = "myForm:dynamicTable:"+i+":col0" ;
var secondCol = "myForm:dynamicTable:"+i+":col1" ;
var merge =document.getElementById(firstCol).textContent;
var work =document.getElementById(secondCol).textContent;
var obj = JSON.parse(val).mergeWorkMap;
if(!(work == obj[merge])){
var col3 = "myForm:dynamicTable:" + i + ":col3";
var col4 = "myForm:dynamicTable:" + i + ":col4";
var col5 = "myForm:dynamicTable:" + i + ":col5";
var col6 = "myForm:dynamicTable:" + i + ":col6";
document.getElementById(col3).disabled = true;
document.getElementById(col4).disabled = true;
document.getElementById(col5).disabled = true;
document.getElementById(col6).disabled = true;
}
}
}
</script>
The rowblur() won't work properly on filtering, and on sorting the columns it won't work at all.

Categories