【问题标题】:reinitialize flexselect.js after adding new select controls with javascript使用 javascript 添加新的选择控件后重新初始化 flexselect.js
【发布时间】:2016-04-05 16:18:54
【问题描述】:

我正在尝试使用 flexselect.js 使选择框更易于使用,并尝试使用 jquery.formset.js 来动态添加新的表单集表单。

我在这里使用内联表单集。最上面一行是表单,而灰色框中的字段和 formset 表单字段。 带有“-----------”的输入字段是flexselect.js已经转换为输入字段的选择框。

在我通过单击 UI 上的“添加项目”使用 JQuery(jquery.formset.js) 添加新的表单集表单之前,一切正常。

jquery.formset 按预期添加了一个新表单,但flexselect.js 未正确加载第一个字段(我用红色突出显示的那个),因此它的空白而不是包含“--------- ---”就像它上面的那个(我用黄色突出显示的那个)。当我单击输入字段时,焦点离开输入字段并转到以黄色突出显示的字段。简而言之,flexselect 仅适用于 flexselect 首次初始化时出现的选择框。

任何人都可以告诉我如何在我添加新的表单集表单时重新初始化flexselect,以便 flexselect 停止忽略新添加的选择框。

我在下面添加相关代码:

<script type="text/javascript">

    jQuery(document).ready(function() {
        // This initializes flexselect
        $("select.flexselect").flexselect();

        // this initializes jquery.formset.js and is used for adding new formset forms
        $(".inline.{{ posting_form.prefix }}").formset({
            prefix: "{{ posting_form.prefix }}",
            addText: "Add item",
            deleteText: "Remove",
            added: function(){  // called when the formset form has been added
                $('select.flexselect').flexselect();
                // maybe some more code here.......
            },
        });
    });
</script>

【问题讨论】:

    标签: jquery django


    【解决方案1】:

    我找到了解决上述问题的有效方法。这与jquery.formset.js 的工作方式有关。万一其他人撞到了这块砖头,这就是我修复它的方法。

    当您单击“添加项目”时,jquery.formset.js 知道包含您最初显示的表单集表单的容器。然后它遵循这个算法:

    1. 克隆其中一个表单集表单
    2. 将其添加到最后一个表单集表单容器之后的 DOM
    3. 重新计算并更改idname等属性

    另一方面,flexselect.js 通过在 DOM 中查找指定的 select 标记并向它们添加一些数据来工作。

    通过将已被操作的克隆selects 添加回 DOM 是导致意外行为的原因。

    我想不出比修改jquery.formset.js 的源代码更好的办法了。我是这样改的(从第 75 行开始):

    $addBtn.click(function() {
                var nextIndex = parseInt($('#id_' + options.prefix + '-TOTAL_FORMS').val());
                var row = $('.' + options.formCssClass + ':first').clone(true).get(0);
                $(row).removeAttr('id').insertAfter($('.' + options.formCssClass + ':last'));
                $(row).find('input,select,textarea,label').each(function() {
                    updateElementIndex(this, options.prefix, nextIndex);
                    // If this is a checkbox or radiobutton, set uncheck it.
                    // Fix for Issue 1, reported by Wilson.Andrew.J:
                    var elem = $(this);
                    if (elem.is('input:checkbox') || elem.is('input:radio')) {
                        elem.attr('checked', false);
                    } else {
                        elem.val('');
                    }
                });
                var formCount = nextIndex + 1;
                $('#id_' + options.prefix + '-TOTAL_FORMS').val(formCount);
                // If we've got more than one form, enable delete buttons:
                if (formCount > 1) { $('a.' + options.deleteCssClass).show(); }
                // If a post-add callback was supplied, call it with the added form:
                if (options.added) options.added($(row));
                return false;
            });
    

    到.....

    $addBtn.click(function() {
                var nextIndex = parseInt($('#id_' + options.prefix + '-TOTAL_FORMS').val());
                var row = $('.' + options.formCssClass + ':first').clone(true).get(0);
                // formset.js does not know that the form has been manipulated by flexselect.js. By cloning the form as
                // it is, it clones elements that have already had events and stuff attached to them. This is what
                // causes the weird behavior with flexselect.js
    
               // first we'll remove the class and style attributes
                $(row).find('select.flexselect').last().removeAttr("class style");
               // next, remove the input field that was previously generated by flexselect
                $(row).find('input.flexselect').remove();
    
                $(row).removeAttr('id').insertAfter($('.' + options.formCssClass + ':last'));
                $(row).find('input,select,textarea,label').each(function() {
                    updateElementIndex(this, options.prefix, nextIndex);
                    // If this is a checkbox or radiobutton, set uncheck it.
                    // Fix for Issue 1, reported by Wilson.Andrew.J:
                    var elem = $(this);
                    if (elem.is('input:checkbox') || elem.is('input:radio')) {
                        elem.attr('checked', false);
                    } else {
                        elem.val('');
                    }
                });
    
                // At this point, formset.js has done most of the major lifting. We can now add the attributes that
                // flexselect.js needs which is just a select with a CSS class called 'flexselect'.
                $(row).find("select").attr("class", "flexselect");
                var formCount = nextIndex + 1;
                $('#id_' + options.prefix + '-TOTAL_FORMS').val(formCount);
                // If we've got more than one form, enable delete buttons:
                if (formCount > 1) { $('a.' + options.deleteCssClass).show(); }
                // If a post-add callback was supplied, call it with the added form:
                if (options.added) options.added($(row));
                return false;
            });
    

    然后我调整了初始化代码如下:

    <script type="text/javascript">
        jQuery(document).ready(function($) {
            $("select.flexselect").flexselect();
    
            $(".inline.{{ posting_form.prefix }}").formset({
                prefix: "{{ posting_form.prefix }}",
                addText: "Add item",
                deleteText: "Remove",
                added: function(){
                    $('select.flexselect').last().removeData("flexselect");
                    $('select.flexselect').flexselect();
                },
            });
        });
    </script>
    

    这就是我修复它的方法。希望对其他人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-28
      • 2017-09-17
      • 1970-01-01
      • 1970-01-01
      • 2017-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多