表单提交时触发 onchange 事件
2021-04-12
854
我希望用户能够记录他们执行的操作。我按类别对操作进行分组,然后使用两个选择菜单和 JS 仅向用户显示他们所选类别的操作。还有一个数量输入,它根据所选操作生成。
我的问题是,当我提交表单时,我收到错误:
未捕获的 TypeError:无法将属性“onchange”设置为 null
选择框和 JS 实现的功能在提交表单之前有效。
index.js
document.addEventListener("DOMContentLoaded", () => {
// First select
let cat_select = document.getElementById("id_post_cat");
cat_select.onchange = () => handleCatChange(cat_select.value);
// Second select
let desc_select = document.getElementById("id_post_action");
desc_select.onchange = () => handleDescChange(desc_select.value);
});
const handleCatChange = (cat) => {
let quantity_div = document.getElementById("quantity_div");
quantity_div.innerHTML = "";
// Fetching the actions in the category selected and populating second select
fetch(`/action/${cat}`)
.then((response) => response.json())
.then((data) => {
let desc_select = document.getElementById("id_post_action");
let optionHTML = "<option>---------</option>";
data.actions.forEach((action) => {
optionHTML +=
'<option value"' + action.id + '">' + action.desc + "</option>";
});
desc_select.innerHTML = optionHTML;
})
.catch((err) => console.log(err));
};
const handleDescChange = (desc) => {
let quantity_div = document.getElementById("quantity_div");
quantity_div.innerHTML = "";
let time_actions = [
"Public transport instead of driving",
"Walk/cycle instead of drive",
];
let quant_actions = [
"Unplug unused electrical items",
"Repurpose a waste object",
"Use a reusable bag",
"Buy an unpackaged item",
"Buy a locally produced item",
"Buy a second hand item",
"Buy an object in bulk",
"Use a refillable bottle/to-go mug",
"Drink a tap beer instead of bottled beer",
];
if (time_actions.includes(desc)) {
formAdder("Distance* (km)");
} else if (quant_actions.includes(desc)) {
formAdder("Quantity*");
}
};
const formAdder = (label_content) => {
let quantity_div = document.getElementById("quantity_div");
// Label
let label = document.createElement("label");
label.innerHTML = `${label_content}`;
label.setAttribute("for", "id_post_quantity");
label.classList += "requiredField";
// Input
let input = document.createElement("input");
input.setAttribute("id", "id_post_quantity");
input.setAttribute("name", "post_quantity");
input.setAttribute("required", "");
input.classList += "form-control";
quantity_div.append(label, input);
};
views.py
@login_required
def record(request):
if request.method == 'POST':
form = NewPostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.poster = request.user
if request.POST.get('id_post_quantity'):
post.post_quantity = request.POST.get('id_post_quantity')
post.save()
return HttpResponseRedirect(reverse('index'))
return render(request, 'my_app/record.html', {
'form': NewPostForm
})
record.html
<form action="{% url 'record' %}" method="post">
{% csrf_token %}
{{form.post_cat|as_crispy_field}}
{{form.post_action|as_crispy_field}}
<div class="form-group" id="quantity_div">
</div>
<button class="btn btn-success" type="submit">Post</button>
</form>
如果能给出正确的指示,我将不胜感激,谢谢。
2个回答
似乎每个加载的页面都会调用 onchange。这意味着,当重定向到索引页(不存在选择框)时,getElementById 返回空值等。
我通过添加条件来检查元素是否存在于页面上来更改此设置:
document.addEventListener("DOMContentLoaded", () => {
// First select
let cat_select = document.getElementById("id_post_cat");
if (!!cat_select) {
cat_select.onchange = () => handleCatChange(cat_select.value);
}
// Second select
let desc_select = document.getElementById("id_post_action");
if (!!desc_select) {
desc_select.onchange = () => handleDescChange(desc_select.value);
}
});
有没有更优雅/正确的方法来解决同一问题?
Ewan Willsmer
2021-04-13
当我将提交事件更改为按钮单击事件时,这个问题就得到了解决。
ThisisFish
2022-09-30