如何使用formset_media_js处理inlineformset_factory内部的JavaScript事件

问题描述 投票:0回答:1

我有一个用formset_media_js实现的inlineformset_factory,这两个本身可以正常工作。我需要实现的是能够处理inlineformset_factory内部的某些复选框和输入字段的启用和禁用状态。

我有一个可在页面加载时创建的第一组表单集上使用的javascript,但是当用户添加新的表单集时,javascript无法使用。

我如何处理用户使用javascript添加的新表单集输入字段?

如果选中了“是章节”,则“是子章节”和“数量”被禁用,默认情况下inlineformset_fatory在页面加载时创建1个表单集,在此表单集上javascript起作用。但是,当用户使用“添加其他预算项”按钮添加另一个表单集时,javascript将不再起作用。例如,如果我将inlineformser_factory配置为在页面加载时创建3个表单集,则javascript在这3个表单集上起作用,但在用户添加的表单集上不起作用。

enter image description here

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]处调用(包括)此表单

<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

:在此模板上,我有JavaScript,可在其中控制复选框和输入字段的启用和禁用状态。我认为,通过在迭代表单集的for循环内调用脚本,我将能够控制用户添加的表单集的输入字段。仅适用于页面加载时创建的表单集。
{% 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 django django-forms formset inline-formset
1个回答
0
投票

这是由朋友编写的,最终开发出的JavaScript。谢谢FunkyBob!

© www.soinside.com 2019 - 2024. All rights reserved.