我有一个用formset_media_js实现的inlineformset_factory,这两个本身可以正常工作。我需要实现的是能够处理inlineformset_factory内部的某些复选框和输入字段的启用和禁用状态。
我有一个可在页面加载时创建的第一组表单集上使用的javascript,但是当用户添加新的表单集时,javascript无法使用。
我如何处理用户使用javascript添加的新表单集输入字段?
如果选中了“是章节”,则“是子章节”和“数量”被禁用,默认情况下inlineformset_fatory在页面加载时创建1个表单集,在此表单集上javascript起作用。但是,当用户使用“添加其他预算项”按钮添加另一个表单集时,javascript将不再起作用。例如,如果我将inlineformser_factory配置为在页面加载时创建3个表单集,则javascript在这3个表单集上起作用,但在用户添加的表单集上不起作用。
forms.py:在这个forms.py上,我具有inlineformset_factory,它在用户每次添加表单集时都会创建。
from django import forms
from django.forms import inlineformset_factory
from djangoformsetjs.utils import formset_media_js
from accounts.models import ProjectManager
from projects.models import Project, BudgetModel, BudgetModelItems
class CreateBudgetItem(forms.ModelForm):
class Media(object):
js = formset_media_js
class Meta:
model = BudgetModelItems
fields = ('budget_model',)
widgets = {
'budget_item_description': forms.Textarea(attrs={'rows': 2, 'cols': 50}),
'budget_item_item': forms.NumberInput(attrs={'size': 6}),
'budget_item_quantity': forms.NumberInput(attrs={'size': 6}),
}
BudgetItemFormset = inlineformset_factory(BudgetModel, BudgetModelItems,
form=CreateBudgetItem,
fields=('budget_model', 'budget_item_item',
'budget_item_description', 'budget_item_unit',
'budget_item_quantity', 'budget_item_is_chapter',
'budget_item_is_subchapter'),
extra=1,
can_delete=True,
can_order=True
)
views.py
from django.shortcuts import render, redirect
from django.forms import formset_factory
from accounts.models import ProjectManager
from projects.forms.create_project import CreateProjectForm
from projects.forms.create_budgetmodel import BudgetFormset, ProjectForBudgetModel
from projects.forms.create_budgetitem import CreateBudgetItem, BudgetItemFormset
from projects.models import BudgetModel, Project
def create_budget_item(request):
user = request.user.projectmanager
projects = Project.objects.filter(project_manager_id=user)
models = BudgetModel.objects.none()
project_form = ProjectForBudgetModel(user)
budget_item_form = CreateBudgetItem()
formset = BudgetItemFormset()
for project in projects:
models |= BudgetModel.objects.filter(project_id=project.pk)
budget_item_form.fields['budget_model'].queryset = models
if request.method == 'POST':
project_form = ProjectForBudgetModel(user, request.POST)
budget_item_form = CreateBudgetItem(request.POST)
if project_form.is_valid() and budget_item_form.is_valid():
# project_id = project_form.cleaned_data['project']
budget_model_id = budget_item_form.cleaned_data['budget_model']
formset = BudgetItemFormset(request.POST, instance=budget_model_id)
if formset.is_valid():
formset.save()
context = {'project_form': project_form,
'bi_form': budget_item_form,
'formset': formset,
'models': models}
return render(request, 'projects/create_budget_items.html', context)
budget_item_form.html:在create_budget_items.html]处调用(包括)此表单
:在此模板上,我有JavaScript,可在其中控制复选框和输入字段的启用和禁用状态。我认为,通过在迭代表单集的for循环内调用脚本,我将能够控制用户添加的表单集的输入字段。仅适用于页面加载时创建的表单集。<div data-formset-form> <div class="card"> <div class="card-body"> <div class="row"> <div class="col"> <table class="table"> <thead class="thead-light"> <tr> <th scope="col">Item</th> <th scope="col">Description</th> <th scope="col">Unit</th> <th scope="col">Quantity</th> <th scope="col">Is Chapter</th> <th scope="col">Is SubChapter</th> </tr> </thead> <tbody> <tr> <th>{{ form.budget_item_item }}</th> <td>{{ form.budget_item_description }}</td> <td>{{ form.budget_item_unit }}</td> <td>{{ form.budget_item_quantity }}</td> <td>{{ form.budget_item_is_chapter }}</td> <td>{{ form.budget_item_is_subchapter }}</td> </tr> </tbody> </table> </div> <div class="col-md-auto"> {% if form.ORDER %} <div class="row mt-1"> <div class="d-none">{{ form.ORDER }}</div> <button class="btn btn-info btn-block" type="button" data-formset-move-up-button> {% trans 'Move up' %} </button> </div> <div class="row mt-1"> <button class="btn btn-info btn-block" type="button" data-formset-move-down-button> {% trans 'Move down' %} </button> </div> {% endif %} </div> <div class="col col-lg-2 mt-1"> {% if form.DELETE %} <div class="d-none">{{ form.DELETE }}</div> <button type="button" class="btn btn-danger btn-block h-100" data-formset-delete-button> {% trans 'Delete' %} </button> {% endif %} </div> </div> </div> </div> </div>
create_budget_items.html
{% block dashboard_head %}
{{ formset.media }}
<script type="text/javascript">
function trackDisabled(trigger_id, ...targets) {
const checkbox = document.getElementById(trigger_id);
checkbox.addEventListener('change', e => {
console.log(e.target.checked);
{#console.log(trigger_id);#}
{#console.log(...targets);#}
if (e.target.checked === true) {
targets.forEach(x => {
const element = document.getElementById(x);
element.disabled = true;
element.checked = false;
element.value = ''
})
} else {
targets.forEach(x => document.getElementById(x).disabled = false)
}
})
}
</script>
{% endblock dashboard_head %}
{% block dashboard_content %}
<h1>Create Budget Items</h1>
<form method="post">
{% csrf_token %}
{{ project_form.project }}
<select name="budget_model" id="id_budget_model" class="form-control">
{% with value=bi_form.budget_model.value %}
{% for model in models %}
<option value="{{ model.pk }}" class="{{ model.project.pk }}"
{% if model.pk|slugify == value|slugify %}selected="selected"{% endif %}>
{{ model.budget_name }}
</option>
{% endfor %}
{% endwith %}
</select>
{% load formset_tags %}
<div id="formset" data-formset-prefix="{{ formset.prefix }}">
{{ formset.management_form }}
<div data-formset-body>
{% for form in formset %}
{% include "projects/budget_item_form.html" with form=form only %}
<script>
trackDisabled(
'{{ form.budget_item_is_chapter.auto_id }}',
'{{ form.budget_item_is_subchapter.auto_id }}',
'{{ form.budget_item_quantity.auto_id }}'
);
console.log('{{ form.budget_item_is_chapter.auto_id }}');
</script>
{{ form.errors }}
{% endfor %}
</div>
<script type="form-template" data-formset-empty-form>
{% escapescript %}
{% include "projects/budget_item_form.html" with form=formset.empty_form only %}
{% endescapescript %}
</script>
<div class="row mt-3 mr-1 ml-1">
<!-- This button will add a new form when clicked -->
<div class="col text-center">
<input class="w-75 btn btn-info" type="button"
value="{% trans 'Add another Budget Item' %}" data-formset-add>
</div>
<div class="col text-center">
<button class="w-75 btn btn-success" type="submit">
{% trans 'Create Models' %}
</button>
</div>
</div>
</div>
</form>
{% endblock dashboard_content %}
我有一个用formset_media_js实现的inlineformset_factory,这两个本身可以正常工作。我需要实现的是能够处理某些复选框的启用和禁用状态...
这是由朋友编写的,最终开发出的JavaScript。谢谢FunkyBob!