Comment «charger» une liste déroulante dépendante lors du chargement de la page?

9

J'ai un formulaire avec une liste déroulante dépendante. Cette liste déroulante secondaire est masquée chaque fois que l'option principale sélectionnée n'a pas d'options secondaires et lors du premier chargement de la page. Chaque fois que le formulaire est soumis, seul le premier champ est effacé, car la plupart du temps les listes déroulantes restent les mêmes, cependant, car le script fonctionne chaque fois qu'il y a un changement dans la liste déroulante principale, car la charge sur ne ne constitue pas un changement, il conserve simplement l'option sélectionnée / soumise dans la liste déroulante principale et affiche simplement une liste déroulante secondaire vide, même lorsque l'option principale sélectionnée a des options secondaires. J'ai obtenu la plupart des JS à partir du menu déroulant d'un tutoriel, car je ne le connais pas très bien. Pour une compréhension plus visuelle:

Voici le formulaire lors du premier chargement de la page

entrez la description de l'image ici

Lorsque vous sélectionnez une option qui a des options secondaires, l'autre liste déroulante apparaît

entrez la description de l'image ici

Après avoir sélectionné une station et soumis, l'employé # efface, mais les deux autres sont censés rester, cependant, lorsque la page se recharge lors de la soumission, cela ressemble à ceci, et la station a été effacée selon le débogueur car il n'y en a pas techniquement. Je ne me soucie pas tellement du nettoyage de la station, mais plutôt du fait de ne pas avoir de liste déroulante vide qui ne devrait pas être vide.

entrez la description de l'image ici

Et quand je regarde les données qui sont restées dans le formulaire, seule la zone de travail est restée, car la liste déroulante dépendante ne se charge pas jusqu'à ce que vous sélectionniez une autre option dans la liste déroulante et si vous vouliez pouvoir voir à nouveau les options d'assemblage de boîtes , vous devez cliquer sur une autre option, puis revenir à l'assemblage de la boîte (par exemple)

Comment pourrais-je résoudre ce problème? Existe-t-il un moyen de forcer le javascript à tenter de se charger en premier pour qu'il vérifie si l'option qui reste a les options secondaires, si elle a été déclenchée ou non?

forms.py

class WarehouseForm(AppsModelForm):
    class Meta:
        model = EmployeeWorkAreaLog
        widgets = {
            'employee_number': ForeignKeyRawIdWidget(EmployeeWorkAreaLog._meta.get_field('employee_number').remote_field, site, attrs={'id':'employee_number_field'}),
        }
        fields = ('employee_number', 'work_area', 'station_number')


    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['station_number'].queryset = Station.objects.none()

        if 'work_area' in self.data:
            try:
                work_area_id = int(self.data.get('work_area'))
                self.fields['station_number'].queryset = Station.objects.filter(work_area_id=work_area_id).order_by('name')
            except (ValueError, TypeError):
                pass
        elif self.instance.pk:
            self.fields['station_number'].queryset = self.instance.work_area.stations.order_by('name')

views.py

def enter_exit_area(request):
    enter_without_exit = None
    exit_without_enter = None

    if request.method == 'POST':
        form = WarehouseForm(request.POST)
        if form.is_valid():
            emp_num = form.cleaned_data['employee_number']
            area = form.cleaned_data['work_area']
            station = form.cleaned_data['station_number']

            # Submission logic
                form = WarehouseForm(initial={'employee_number': '', 'work_area': area, 'station_number': station})

    else:
        form = WarehouseForm()
    return render(request, "operations/enter_exit_area.html", {
        'form': form,
        'enter_without_exit': enter_without_exit,
        'exit_without_enter': exit_without_enter,
    })

urls.py

urlpatterns = [
    url(r'enter-exit-area/$', views.enter_exit_area, name='enter_exit_area'),

    path('ajax/load-stations/', views.load_stations, name='ajax_load_stations'),
]

À la fin de ce code HTML se trouve le script qui gère la liste déroulante dépendante

enter_exit_area.html

{% extends "operations/base.html" %}
{% block main %}
    <form id="warehouseForm" action="" method="POST" data-stations-url="{% url 'operations:ajax_load_stations' %}" novalidate >
        {% csrf_token %}

        <div>
            <div>
                <label>Employee #</label>
                {{ form.employee_number }}
            </div>

            <div>
                <label>Work Area</label>
                {{ form.work_area }}
            </div>
            <div class="col-xs-8" id="my-hidden-div">
                <label>Station</label>
                {{ form.station_number }}
            </div>
        </div>
    </form>

    <script>
        function loadStations() {
            var url = $("#warehouseForm").attr("data-stations-url");
            var workAreaId = $(this).val();
            var $stationNumberField = $("#{{ form.station_number.id_for_label }}");

            $.ajax({
                url: url,
                data: {
                    'work_area': workAreaId
                },
                success: function (data) {
                    $("#my-hidden-div").show(); // show it
                    $stationNumberField.html(data);
                    // Check the length of the options child elements of the select
                    if ($stationNumberField.find("option").length === 1) {
                        $stationNumberField.parent().hide(); // Hide parent of the select node
                    } else {
                        // If any option, ensure the select is shown
                        $stationNumberField.parent().show();
                    }
                }
            });
        }
        $("#id_work_area").change(loadStations);
        $(document).ready(loadStations);
     </script>
{% endblock main %}

station_number_dropdown_options.html

<option value="">---------</option>
{% for station in stations %}
<option value="{{ station.pk }}">{{ station.name }}</option>
{% endfor %}
Mariana Gomez-Kusnecov
la source

Réponses:

3

Je vois que tu l'as $(document).ready(loadStations);.

Mais le problème est que dans loadStations, vous le faites var workAreaId = $(this).val();.

thissera documentet $(document).val()est une chaîne vide.

Soit coder en dur le sélecteur dans loadStations:

// var workAreaId = $(this).val();
var workAreaId = $("#id_work_area").val();

Ou déclenchez plutôt le changement depuis l'élément:

$("#id_work_area").change(loadStations);
// $(document).ready(loadStations);
$("#id_work_area").change();
Aaron
la source
La première option n'a pas fonctionné (elle ne chargerait rien) mais la seconde l'a fait, merci!
J'attribuerai