0

Im using Select2 Bootstrap https://select2.github.io/ for Remote Data Fetching Via Ajax and All this inside a Jquery Repeater http://briandetering.net/repeater

<div data-repeater-item class="mt-repeater-item">
                                <!-- jQuery Repeater Container -->
<div class="mt-repeater-input">
 <label class="control-label">First Team</label>
  <br/>
 <select name="equipe_1" id="select2-button-addons-single-input-group-sm" class="form-control js-data-example-ajax">
</select>
 </div>
 <div class="mt-repeater-input">
 <label class="control-label">Second Team</label>
<br/>
<select name="equipe_2" id="select2-button-addons-single-input-group-sm" class="form-control js-data-example-ajax">
</select>
</div>
                                <div class="mt-repeater-input">
                                    <a href="javascript:;" data-repeater-delete class="btn btn-danger mt-repeater-delete">
                                        <i class="fa fa-close"></i> Delete</a>
                                </div>
                            </div>

This is my HTML but when i Click on the Add button i have the form cloned but the slect2 dropdonw is not working.

My Componement Select2 JS File

$(".js-data-example-ajax").select2({
            placeholder: "Choose a Team...",
            width: "off",
            allowClear: true,
            multiple:false,
            ajax: {
                url: "http://test.dev/teamsearch",
                dataType: 'json',
                type: "POST",
                delay: 2000,
                data: function(params) {
                    return {
                        q: params.term, // search term
                        page: params.page,
                        _token: CSRF_TOKEN
                    };
                },
                processResults: function(data, page) {
                    // parse the results into the format expected by Select2.
                    // since we are using custom formatting functions we do not need to
                    // alter the remote JSON data
                    return {
                        results: data
                    };
                },
                cache: true
            },
            escapeMarkup: function(markup) {
                return markup;
            }, // let our custom formatter work
            minimumInputLength: 4,
            maximumSelectionLength: 1,
            templateResult: formatRepo,
            templateSelection: formatRepoSelection
        });

my Jquery Repeater File:

var FormRepeater = function () {

    return {
        //main function to initiate the module
        init: function () {
            
             $('.mt-repeater').each(function(){
          $(this).repeater({
           show: function () {

                        $(this).slideDown();


              },

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

              ready: function (setIndexes) {

              }

          });
         });
        }

    };

}();

jQuery(document).ready(function() {
    FormRepeater.init();

});

Im using Select2 ajax to load a list of team inside.

How can i make select2 working when jquery repeater clone my form ? Thank's

Tncoders
  • 11
  • 2
  • 3

3 Answers3

0

take a look at jQuery form repeater and select2 dont work together. The basic problem is that you need to call .select2() on each new select box after the repeater creates it

Community
  • 1
  • 1
Bindrid
  • 3,655
  • 2
  • 17
  • 18
0

Don't know if this answer comes too late or it's not need anymore at all but I decided it can probably help someone in the future.

So I had this problem a while back and I solved it by doing what Bindrid said and put a call for .select2() inside every Add action the user does on form repeater. I'm using C# MVC 5, jquery-repeater v1.2.1 and select2 v4.0.3.

Feel free to help improve this code.

My ViewModel:

public class MedicalCareViewModel
{
   [Display(Name = "ICD")]
   [Require(ErrorMessage = "This field is required")]
   public List<RelatedICDViewModel> RelatedICD { get; set; }
}

public class RelatedICDViewModel
{
   public int Code { get; set; }

   public string AbbreviatedDescription { get; set; }
}

My Controller:

public ViewResult MedicalCare(int id)
{
   var medicalCare = MedicalCareService.GetById(id);
   var model = Mapper.Map<MedicalCareViewModel>(medicalCare);

   // This is for pre-loaded data, if you don't have to show pre-loaded data skip this
   // Here's the catch, you'll have to iterate through your selected values in the 
   // select box and for each element you'll have to create a list of 
   // selected items with just the item selected so you can then 
   // iterate in the view and 'show' the form-repeater it's values.
   // Since each select list item have the Selected propertie set to true
   // select2 will know what to do
   foreach(var ICD in model.RelatedICD)
      ViewData[$"Index[{model.RelatedICD.IndexOf(ICD)}]"] = new List<SelectlistItem> 
   {
      new SelectListItem
      {
         Value = ICD.Code.ToString(),
         Text = ICD.AbbreviatedDescription,
         Selected = true
      }
   };

   return View(model);
}

My View:

@model MedicalCareViewModel
@using(Html.BeginForm("MedicalCare", "MedicalHistory", new {area = "Medical"}, FormMethod.Post, new { enctype = "multipart/form-data"} ))
{
   // other form fields
   // Initialize the repeater by setting an ID to a div
   <div id="rpRelatedICD">
      <div data-repeater-list="RelatedICD">
         // This conditional is for pre-loaded data, if you don't need to 
         // show pre-loaded data just use the else part
         @if(Model.RelatedICD.Any())
         {
            for(var i = 0; i < Model.RelatedICD.Count; i++)
            {
            <div data-repeater-item>
               // It's important to define a class to the select box so 
               // you can on every add action on the repeater call the 
               // select2 initializer
               @Html.DropDownListFor(model => model.RelatedICD, ViewData[$"Index[{i}]"] as List<SelectListItem>, new {@class = "RelatedICD"})
               <input data-repeater-delete type="button" value="Remove" class="ui-button ui-corner-all ui-widget" role="button">
            </div>
            }
         }
         else
         {
            <div data-repeater-item>
               // It's important to define a class to the select box so 
               // you can on every add action on the repeater call the 
               // select2 initializer
               @Html.DropDownListFor(model => model.RelatedICD, new List<SelectListItem>(), new {@class = "RelatedICD"})
               <input data-repeater-delete type="button" value="Remove" class="ui-button ui-corner-all ui-widget" role="button">
            </div>
         }
         <div>
                <input data-repeater-create="" type="button" value="Add" class="ui-button ui-corner-all ui-widget" role="button">
         </div>
      </div>
   </div>
}

My JS:

<script type="text/javascript">
   $(document).ready(function() {
      initializeICDRepeater();
      initializeICDSelect2();
   });

   function initializeICDRepeater() {
      $("#rpRelatedICD").repeater({
         initEmpty: false,
         show: function() {
            $(this).slideDown();
            // like Bindrid said, on every Add action call the select2 initializer
            initializeICDSelect2(); 
         },
         hide: function(deleteElement) {
            $(this).slideUp(deleteElement);
         }
      });
   }

   function initializeICDSelect2() {
       $(".RelatedICD").select2({
       ajax: { /* your ajax definition */ },
       allowClear: true // || false it's your choice
       });
   }
</script>
0

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

This waits just for a fraction of second before initializing the select2 ensuring that the items are already duplicated when the select2 is initialized.

<script type="text/javascript">
    $("#clone-button").click(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

Sapnesh Naik
  • 11,011
  • 7
  • 63
  • 98
  • I dont understand this : $("p").mouseover(function() it's an event listener to mouseover over a html p tag ?? i need to call the select2 init when i hit the button clone – Tncoders Dec 22 '17 at 04:07