jazzband / django-smart-selects

chained and grouped selects for django forms
https://django-smart-selects.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
1.1k stars 348 forks source link

Having a chained fk field triggers "unsaved changes" in admin interface #261

Closed cookieofcode closed 4 years ago

cookieofcode commented 6 years ago

Checklist

Put an x in the bracket when you have completed each task, like this: [x]

Steps to reproduce

  1. Django 2.0.1, django-smart-selects 1.5.3 (or 1.5.4) and django-jet.
  2. Create Chained field (for example "breed" and "species")
  3. Go to admin interface and create new entry (for example "animal")

Actual behavior

When leaving the page without changing anything, a message "You have unsaved changes" appears. This is due to the "change listener" in the django-admin interface: `onFormInputChanged: function($inputs) { $inputs.off('change', this.onFormInputChanged);

    if (!self.changeDetected) {
        $(window).bind('beforeunload', this.onWindowBeforeUnload);
    }

    this.changeDetected = true;
},`

grafik

To disable this behaviour you can uncomment $selectField.trigger('change'); but this leads to unexpected behaviour.

The bug is related to #91

Expected behavior

Don't change the content of the field (via 'change'), when nothing is selected but still work as expected.

Has anyone a suggestion how to solve this problem?

cookieofcode commented 6 years ago

Partial fix:

 if (!val || val === ''){
                    empty_option.prop('selected', true);
                    options.push(empty_option);

                    $selectField.html(options);
                    //$selectField.trigger('change');   // don't trigger change if empty > unfortunately field stays 
                                                                        // blank instead of "--------"
                    return;
                }
                $.getJSON(url, function(j){
                    var prev_value = $(elem_id).children("option[selected='selected']").val(); // get prev_value
                    auto_choose = j.length == 1 && auto_choose;
                    // Append empty label as the first option
                    if (!(init_value || auto_choose)) {
                        empty_option.prop('selected', true);
                    }
                    options.push(empty_option);

                    // Append each option to the select
                    $.each(j, function (index, optionData) {
                        var option = $('<option></option>')
                            .prop('value', optionData.value)
                            .text(optionData.display);
                        if (auto_choose || init_value && optionData.value == init_value) {
                            option.prop('selected', true);
                        }
                        options.push(option);
                    });

                    $selectField.html(options);
                    var width = $selectField.outerWidth();
                    if (navigator.appVersion.indexOf("MSIE") != -1)
                        $selectField.width(width + 'px');

                   // check if changed and trigger then
                    if (parseInt(init_value) !== parseInt(prev_value))
                        $selectField.trigger('change');
                });
manelclos commented 4 years ago

@cookieofcode is this still happening with the latest master version?

cookieofcode commented 4 years ago

@manelclos Thanks for asking. I can't check as I have no longer access to the project.