Javascript 和 HTML - 将下拉索引值作为对象属性传递会返回未定义
2020-02-17
129
我是这门语言的新手,遇到了障碍。我花了几个小时搜索这个特定问题,但似乎无法弄清楚为什么我的情况如此难以解决。我确信我只是需要一双知道他们在看什么的眼睛。
我试图将下拉列表选择的索引传递到我的 Code.gs 函数中,以便我可以在其他位置使用它来选择电子表格中的某一行数据。我设置了对象 driverPicked 并赋予它属性 selected,然后寻找 selected index 属性。由于我对此还很陌生,我很难理解像这样嵌套属性的后果,并且可以使用一些线索来解决“TypeError:无法读取未定义的属性‘selected’(第 39 行,文件“Code”)”错误我已经遇到了几个小时了。
有很多类似的答案,但我无法弄清楚它们到底是如何适用于我的 - 所以请原谅我!
var url = "REDACTED";
function doGet(e){
//var x = document.getElementById("driver").selectedIndex;
var driverIndex = userClicked();
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("Results_2019");
var listDrivers = ws.getRange(4,1,ws.getRange("A3").getDataRegion().getLastRow(),1).getValues();
var infoHeading = ws.getRange(3, 1, 1, 8).getValues();
var driverInfo = ws.getRange(driverIndex, 1, 1 ,8).getValues();
var tmp = HtmlService.createTemplateFromFile("page");
tmp.title = "GLTC Driver List";
//tmp.listDrivers = listDrivers.map(function(r){r[0];});
tmp.listDrivers = [].concat.apply([], listDrivers);
tmp.infoHeading = [].concat.apply([], infoHeading);
tmp.driverInfo = [].concat.apply([], driverInfo);
tmp.driverIndex = driverIndex;
return tmp.evaluate();
}
function include(filename){
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
function userClicked(driverPicked) {
console.log(driverPicked);
var driverName = driverPicked.value;
return driverName;
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<!--Import Google Icon Font-->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<?!= include("page-css"); ?>
</head>
<body>
<h1><?= title; ?></h1>
<div class="input-field">
<select id="driver">
<option disabled selected>Choose Driver</option>
<? for(var i=0;i<listDrivers.length;i++){ ?>
<option class="selected">
<?= listDrivers[i]; ?>
</option>
<? } ?>
</select>
</div>
<h5><?= infoHeading; ?></h5>
<h5><?= driverInfo; ?></h5>
<h5><?= driverIndex; ?></h5>
<script>
document.getElementById("driver").addEventListener("change", doStuff); // add onchange listener to the select element instead of options
function doStuff(event) {
var driverPicked = {};
driverPicked.driver = event.target.value;
driverPicked.selected = event.target.options.selectedIndex;
userClicked(driverPicked);
}
</script>
<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<?!= include("page-js"); ?>
</body>
</html>
2个回答
代码中存在一些问题:
- DOM 元素的 ID 必须是唯一的,因此在呈现选项时,您需要将索引添加到 ID 或使用类名。
-
对于
select
元素,请使用change
事件,而不是click
。 -
您可以在
doStuff
函数中将事件对象作为参数访问,而不必手动查询 DOM 元素。 我不确定您为什么需要获取索引,但为了获取驱动程序的名称,您可以执行以下操作:
<div class="input-field">
<select id="driver">
<option disabled selected>Choose Driver</option>
<? for(var i=0;i<listDrivers.length;i++){ ?>
<option class="selected"> // use class instead of id here
<?= listDrivers[i]; ?>
</option>
<? } ?>
</select>
</div>
document.getElementById("driver").addEventListener("change", doStuff); // add onchange listener to the select element instead of options
function doStuff(event) {
var driverPicked = {};
driverPicked.driver = event.target.value;
driverPicked.selected = event.target.options.selectedIndex;
google.script.run.userClicked(driverPicked);
}
function userClicked(driverPicked) {
var driverName = driverPicked.value;
return driverName;
}
这是一个可运行的示例,其中包含一些模拟
select
选项:
document.getElementById("driver").addEventListener("change", doStuff); // add onchange listener to the select element instead of options
function doStuff(event) {
var driverPicked = {};
driverPicked.driver = event.target.value;
driverPicked.selected = event.target.options.selectedIndex;
userClicked(driverPicked);
}
function userClicked(driverPicked) {
console.log(driverPicked);
var driverName = driverPicked.value;
return driverName;
}
<div class="input-field">
<select id="driver">
<option disabled selected>Choose Driver</option>
<option class="selected"> Driver 1</option>
<option class="selected"> Driver 2</option>
</select>
</div>
Clarity
2020-02-17
这里做了一些简化。主要简化是,我不再通过
google.script.run
调用该函数,而是直接调用它。
更新
我忘记在初始响应中包含它了。元素
id
应该是唯一的。如果您循环遍历所有元素,但不更改它们的 id 值,那么您编写的 HTML 不正确,并且函数
getElementById(...)
将返回元素数组,而不仅仅是元素数组(因此,其余代码将无法按预期工作)
参见下面的演示
document.getElementById("driver").addEventListener("change", doStuff);
function doStuff() {
var driverPicked = {};
selectBox = document.getElementById("driver");
driverPicked = selectBox.options[selectBox.selectedIndex];
console.log('User changed value to: ');
console.log(driverPicked);
// will this work on other browsers?
// google.script.run.userClicked(driverPicked);
// I am using this instead for demo purposes
userClicked(driverPicked);
}
function userClicked(driverPicked) {
var driverName = driverPicked.value;
var driverText = driverPicked.text;
console.log('name/value: ' + driverName + ' text: ' + driverText);
return driverName;
}
<div class="input-field">
<select id="driver">
<option disabled>Choose Driver</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
<option value="4">Four</option>
</select>
</div>
blurfus
2020-02-17