Selectize.js: cloning of the element and destroy() issue
Asked Answered
G

4

11

I'm using Selectize.js and I need to clone html subform with transformed select elements. After I clone and insert subform select functionality is broken.

I have read that one of the solution is to call destroy() method for cloned selects and after initialize selectize for them again.

I tried to follow this advice and my code looks like:

   $(formFields).find("select").each(function(){
    if (this.selectize) {
        this.selectize.destroy();
    }
});

What I expect to see is standard select elements, but I see selectized elements with not working dropdown functionality. Any ideas?

Gooseherd answered 7/1, 2015 at 19:9 Comment(0)
S
15

The selectize object is added to the original select / input element instance. Make sure to add a [0] to specify the selectize object:

$(this)[0].selectize.destroy();

See Selectize API Docs for specific example.

Additionally, I have seen a lot of unanswered questions about cloning selectize.js elements. Here is approximately how I went about the process:

// Trigger when add row button clicked
$('.row-add').click(function() {

    // Find last row in table (or div) to clone from
    var lastRow = $("myTable").find('tr').last();

    // Determine if selectize.js is in use on any element and disable
    // before cloning.
    var selectizeElements = {};
    lastRow.find('select').each(function() {
        if ($(this)[0].selectize) {

            // Store last row's current options and value(s) to
            // restore after destroying for clone purposes.
            selectizeElements[$(this).attr('id')] = {
                inputOptions: $(this)[0].selectize.options,
                inputValue:   $(this)[0].selectize.getValue()
            }

            // Destroy the selectize.js element
            $(this)[0].selectize.destroy();
        }
    });

    // Clone last row
    newRow = lastRow.clone().insertAfter(lastRow);

    // Clear any data that was already entered in the cloned row
    newRow.find( 'input,select,textarea' ).each(function() {
        $(this).val( '' );
        $(this).attr( 'checked', false );
    });

    // Re-enable any selectize.js fields if needed, adding back
    // any options and selected values to the original row.
    if (!$.isEmptyObject(selectizeElements) {
        $.each(selectizeElements, function(key, value) {
            lastRow.find('select#'+key).selectize();
            newRow.find('select#'+key).selectize();
        })

        // Copy back options and values to cloned row
        $.each(selectizeElements, function(key, value) {
            lastRow.find('select#'+key)[0].selectize.addOption(value.inputOptions);
            lastRow.find('select#'+key)[0].selectize.setValue(value.inputValue);
        });
    }

    // I usually update the id and name attribute index number here so
    // that each form element has a unique id and name.
});

You can find some working example code in this Repo

Semiliterate answered 9/2, 2015 at 22:58 Comment(0)
U
5
// When add button is clicked
$('#add').on('click',function(){
   $('.combobox').each(function(){ // do this for every select with the 'combobox' class
      if ($(this)[0].selectize) { // requires [0] to select the proper object
         var value = $(this).val(); // store the current value of the select/input
         $(this)[0].selectize.destroy(); // destroys selectize()
         $(this).val(value);  // set back the value of the select/input
      }
   });
   $('#monsters .form-group:first')
      .clone() // copy
      .insertAfter('#monsters .form-group:last'); // where
      selectizeme(); // reinitialize selectize on all .combobox
});

try visit here: http://mariolurig.com/selectize-demo.htm

Unvoiced answered 30/10, 2017 at 1:27 Comment(0)
P
1

// i equal to duplcate number
let i = 0;
var original = document.querySelector(".duplcate");
$(document).ready(function() {
    $(".selectize-select").selectize({
        sortField: "text",
    });

});
$("#add-student-btn").click(function() {
    // Determine if selectize.js is in use on any element and disable
    // before cloning.
    var selectizeElements = {};
    $(original)
        .find("select")
        .each(function() {
            if ($(this)[0].selectize) {

                selectedValue = $(this)[0].selectize.getValue();
                selectizeElements[$(this).attr("id")] = {
                    inputOptions: Object.values($(this)[0].selectize.options),
                    inputValue: $(this)[0].selectize.getValue(),
                };
                // Destroy the selectize.js element
                $(this)[0].selectize.destroy();
            }
        });

    var clone = original.cloneNode(true); // "deep" clone
    i = i + 3;
    //    original.children[0].removeChild(original.children[0].children[2]);
    clone.id = "duplicater" + i; // there can only be one element with an ID
    clone.style.display = "block";
    clone.children[0].children[1].children[0].id = "relation" + i;
    clone.children[0].children[0].children[0].id = i;
    this.parentNode.parentNode.insertBefore(clone, this.parentNode);

    // Clear any data that was already entered in the cloned row
    $(clone)
        .find("input,select,textarea")
        .each(function() {
            $(this).val("");
            $(this).attr("checked", false);
        });
    // Re-enable any selectize.js fields if needed, adding back
    // any options and selected values to the original row.
    if (!$.isEmptyObject(selectizeElements)) {
        $.each(selectizeElements, function(key, value) {

            $(original)
                .find("select#" + key)
                .selectize();

        });
        $(clone)
            .find("select.selectize-select")
            .selectize();
        // Copy back options and values to cloned row
        $.each(selectizeElements, function(key, value) {
        //return back options and values to orginal element
            $(original).find('select#' + key)[0].selectize.addOption(value.inputOptions);
            $(original).find('select#' + key)[0].selectize.setValue(value.inputValue);
             //add options  to the cloned elements
             $(clone).find('select#' + key)[0].selectize.addOption(value.inputOptions);

        });

    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


<form method="post" class="flexAlignCenter flexColumn">
            <div class="formGroup">
                <div class="inputDetails flexAlignStart flexColumn">
                    <label for="name">Name</label>
                    <input type="text" id="name" name="name" placeholder="" required>
                </div>
                <div class="inputDetails flexAlignStart flexColumn">
                    <label for="phone">Phone</label>
                    <input type="number" id="phone" name="phone" placeholder=""
                        max="999999999">
                
                </div>

            </div>

            <div class="formGroup">
                <div class="inputDetails flexAlignStart flexColumn">
                    <label for="password">password</label>
                    <input type="password" id="password" name="password"
                        placeholder="enter password">
                        
                </div>
            



            </div>
            <div class="formGroup">

                <div class="inputDetails flexAlignStart flexColumn">
                    <label for="name">Address</label>
                    <input type="text" id="address" name="address" placeholder="Enter address">
                </div>


            </div>
            <div class="formGroup duplcate">
                <div class="formGroup">
                    <div class="inputDetails flexAlignStart flexColumn">
                        <label for="name">Student</label>

                        <select name="student[]" class="form-control selectize-select" id="0">
                            <option>choose Student</option>                                          
                             <option value='1'>Student1</option>
                            <option value='2'>Student2</option>
                            <option value='3'>Student3</option>
                            <option value='4'>Student4</option>
                        </select>
                    </div>

                    <div class="inputDetails flexAlignStart flexColumn">
                        <label for="name">RelationShip</label>
                        <select name="relation[]" class="form-control selectize-select" id="relation0">
                           <option >choose relationShip</option>
                           <option value="1">Father</option>
                           <option value="2">Mother</option>
                           <option value="3">Sister</option>
                        </select>
                    </div>
                    
                </div>
            </div>
            <div class="add-new-dev-type">
                <div class="addClass">
              
                  <span id="add-student-btn" style="font-size:32px; ">&#43;</span>
                    <span >Add student</span>
                </div>
                <input type="submit" value="submit" />
            </div>
            
    </form>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.13.3/js/standalone/selectize.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.13.3/css/selectize.min.css" rel="stylesheet"/>

if you have a lot of onchange functions that change other selectize options, you should make a hidden copy from the elements you want to duplicate and add it before the visible one. The cloned one will be created from the hidden one.

Potomac answered 12/9, 2021 at 7:30 Comment(0)
R
0

I'll just add my own solution here as well. Thanks to @David Cramblett for his useful answer.

$('select')
   .each(function(index, el) {
      el.selectize.destroy()
   })

This loops through all select elements and unselectizes them. Even though I think running destroy on all select elements at once would have been preferable (it does not work that way); but this works fine for me.

Recap answered 29/4, 2023 at 18:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.