jQuery form repeater and select2 dont work togethe

2019-06-01 00:15发布

问题:

I am using Select2 and jQuery form repeater (https://github.com/DubFriend/jquery.repeater)

I have searched on google/so for 2 days, but cant seem to get it to work.

include jquery/select2.js/jquery.repeater.js

var form = $('#form');
form.find('select').select2();

form.repeater({
    show: function () {
    $(this).show(function(){
        form.find('select').select2('destroy').select2();
    });
    },
    hide: function (remove) {
      $(this).hide(remove);
    }
});

The problem is the jQuery.repeater clones the div tag in which the input and select elements are when select2 is already initialized and has already changed the DOM, so jQuery.repeater copies the changed DOM. I tried to destroy select2 before the repeat action is called, but that dindt work either.

回答1:

I'm working on a project where I use jQuery.repeater to repeat multiple select2 inputs. Following approach helped to solve my problem of initializing the inputs after they are loaded.

$('.job_repeater').repeater({
  show: function () {
    $(this).slideDown();
    $('.select2-container').remove();
    $('Replace with your select identifier id,class,etc.').select2({
      placeholder: "Placeholder text",
      allowClear: true
    });
    $('.select2-container').css('width','100%');
  },
  hide: function (remove) {
    if(confirm('Confirm Question')) {
      $(this).slideUp(remove);
    }
  }
});

More exact jQuery selectors will help to only remove/initialize the selects you want to.

The CSS line I use always after initializing the select2 to adjust the width to the parent div/container.

Best regards



回答2:

try this

include jquery/select2.js/jquery.repeater.js

var form = $('#form');
form.find('select').select2();

form.repeater({
    show: function () {
    $(this).show(function(){
        // you have not really created this second one
        // so the destroy does not work.
        // Since it is just a copy of the html,
        form.find('select').next('.select2-container').remove();
        form.find('select').select2();
    });
    },
    hide: function (remove) {
      $(this).hide(remove);
    }
});


回答3:

Here is a solution which initializes select2 on form repeater button clock.

<script type="text/javascript">

 

    $("p").mouseover(function(){

        setTimeout(function(){

 

            $(".select2").select2({

                placeholder: "Select a state",

                allowClear: true

            }); 

                  

        }, 100);

    }); 

 

</script>

For an in depth overview of the problem and solution see here



回答4:

When using the initEmpty: false option, initialising select2 at the show function doesn't work for the first row. In this case you can also initialise select2 when the ready function runs.

$('.repeater').repeater({
    isFirstItemUndeletable: false,
    initEmpty: false,
    ready: function () {
        $('.select2').select2({
            placeholder: "Select an option...",
        });
    },
    show: function () {
        $(this).slideDown();
        $('.select2').select2({
            placeholder: "Select an option...",
        });
    },
    hide: function () {
        $(this).slideUp();
    },
});


回答5:

I solved it by first initializing the original select2 on document ready and then targeting with $this each instance of the repeated selected2 element on the repeater show method. For instance, if you have a simple select dropdown and a multiple select your code should look like this:

$(document).ready(function () {
  $(".select2").select2({
       placeholder: "Select a state",
       allowClear: true
    });
});

$('.repeater').repeater({

        show: function () {
            $(this).slideDown();
            $(this).find('.select2-multiple').select2({

                placeholder: "Select Title",

                allowClear: true,

            });
            $(this).find('.select2').select2({

                placeholder: "Select Title",

                allowClear: true,

            });


        },
        hide: function (deleteElement) {
            if (confirm('Are you sure you want to delete this element?')) {
                $(this).slideUp(deleteElement);
            }
        }
    });


回答6:

Hope this is not too late, this is working on my end. Had to manually 'destroy' select2 and remove all attached attributes to all select elements so as not to confuse the script and return the element in its 'original' state.

$('.repeater').repeater({
    show: function (){
        $(this).slideDown(function(){
            var selects = $('body').find('.pm-select2');
            $.each(selects, function(i, selectElement){
                $(selectElement).removeClass('select2-hidden-accessible').next('.select2-container').remove();
                $(selectElement).removeAttr('data-select2-id tabindex aria-hidden');
                initSelect2(selectElement);
            });
        });
    },
    hide: function (){
        $(this).slideUp();
    },
    isFirstItemUndeletable: true
});

function initSelect2(selectElement) {
    $(selectElement).select2({
        minimumResultsForSearch: Infinity
    });
}


回答7:

If anyone else stumbles across this, I had the same problem in getting it to work and the solution is destroying the select2 and recreating.

I then had the issue that the select2 won't sit in the correct position when opened. For instance doing a repeat that results in a page scroll causes any select2 after the page scroll to then open in the position of the first.

To fix this (have the select2 open where it should (down the page)), set the dropdownParent to its immediate parent as so:

currentSelect2.select2({
    placeholder: "Select...",
    width: '100%', 
    allowClear: true,
    dropdownParent: $(this).parent()
});