2015-04-30 4 views
10

У меня есть раскрывающийся список select2, для которого я предоставляю функцию сопряжения. Он инициализируется так на начальной загрузке страницы:Инициализация select2 создана динамически

jQuery(document).ready(function() { 
    jQuery(".my_select2").select2({ 
     matcher: function(term, text) {...} 
    }); 
}); 

Это работает на начальной загрузке страницы.

Теперь у меня есть дополнительные раскрывающиеся меню (select элементы, созданные динамически (вытянут в с помощью AJAX, то есть jQuery(match).load(url). Эти дополнительные выпадающие списки не получают intialised, как ВЫБ.2 виджетов, что понятно, даже если они соответствуют исходной ВЫБ.2 селектор.

Итак, как я могу сказать jQuery для обработки этих динамически созданных элементов select как select2 элементов, которые необходимо инициализировать? Могу ли я установить какой-то «вахту» на соответствующие элементы, так что инициализация select2 запускается каждый раз на страницу добавлен соответствующий элемент?

Я помню live() b eing, введенный в jQuery некоторое время назад, который поддерживал соответствующие элементы до их создания, если я правильно понял. Я никогда не использовал эту функцию, и теперь она выглядит устаревшей. Но это похоже на то, что я ищу.

Это для плагина WordPress, который в настоящее время использует jQuery v1.11.2.

+3

Вы можете посмотреть https://github.com/uzairfarooq/arrive – SSA

+0

Это подразумевает, что jQuery не может наблюдать за создаваемыми предметами, без помощника. Или был создан 'came.js', чтобы упростить работу, когда jQuery не используется вообще? – Jason

+0

Если вы не можете запустить select2 после добавления элемента выбора в DOM, вы должны использовать наблюдателя dom mutation, как первый комментарий –

ответ

17

вы можете попробовать с DOMNodeInserted и искать выбора или класс вы назначая их

Demo

$('body').on('DOMNodeInserted', 'select', function() { 
    $(this).select2(); 
}); 

Update

DOMNodeInserted

Устаревший Эта функция удалена из веб-стандартов. Хотя некоторые браузеры все еще могут его поддерживать, он находится в процессе отбрасывания. Избегайте его использования и, если возможно, обновите существующий код;

Предложенный метод был бы что-то подобное с MutationObserver

$(function() { 
 
    $("button").on("click", function() { 
 
    $("#dynamic-container").append($("<select><option>test</option><select/>")); 
 
    }); 
 

 
    // select the target node 
 
    var target = document.getElementById('dynamic-container'); 
 

 
    if (target) { 
 
    // create an observer instance 
 
    var observer = new MutationObserver(function(mutations) { 
 
     //loop through the detected mutations(added controls) 
 
     mutations.forEach(function(mutation) { 
 
     //addedNodes contains all detected new controls 
 
     if (mutation && mutation.addedNodes) { 
 
      mutation.addedNodes.forEach(function(elm) { 
 
      //only apply select2 to select elements 
 
      if (elm && elm.nodeName === "SELECT") { 
 
       $(elm).select2(); 
 
      } 
 
      }); 
 
     } 
 
     }); 
 
    }); 
 
    
 
    // pass in the target node, as well as the observer options 
 
    observer.observe(target, { 
 
     childList: true 
 
    }); 
 

 
    // later, you can stop observing 
 
    //observer.disconnect(); 
 
    } 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script><link href="http://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet"/> 
 
<script src="http://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script> 
 

 

 
<button>Add new select</button> 
 
    <div id="dynamic-container"> 
 

 
    </div>

+0

Спасибо, что хорошо работает. Однако я хочу попытаться избежать частичного дублирования - выпадающие списки select2 инициализируются в двух отдельных местах. У меня есть помощник и триггер '.on ('change', ...)' в выпадающем меню, поэтому их нужно будет инициализировать и в обоих местах. Я посмотрю, как можно определить интернализацию в одном месте. – Jason

+0

Я согласен с этим в качестве ответа, так как он работает, поэтому разрешите исходный вопрос, хотя я все-таки изменил свой подход в результате ответа. Пакет https://github.com/uzairfarooq/arrive предложил обернуть это, чтобы упростить его использование (т. Е. Более абстрактное). Спасибо всем. – Jason

+0

@ Джейсон, чтобы все было ясно. [incoming.js] (https://github.com/uzairfarooq/arrive) не переносит DOMNodeInserted api. Внутри он использует новый [MutationObserver] (https://developer.mozilla.org/en/docs/Web/API/MutationObserver) api. DOMNodeInserted api [устарел] (https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events) и его следует избегать. –

11

я наткнулся на подобную ситуацию в последнее время, но сделал это в очень обычным способом:

$(document).ready(function() { 
 

 
//function to initialize select2 
 
    function initializeSelect2(selectElementObj) { 
 
    selectElementObj.select2({ 
 
     width: "80%", 
 
     tags: true 
 
    }); 
 
    } 
 

 

 
//onload: call the above function 
 
    $(".select-to-select2").each(function() { 
 
    initializeSelect2($(this)); 
 
    }); 
 

 
//dynamically added selects 
 

 
    $(".add-new-select").on("click", function() { 
 
    var newSelect = $("<select class='select-to-select2' multiple><option>option 1</option><option>option 2</option></select>"); 
 
    $(".select-container").append(newSelect); 
 
    initializeSelect2(newSelect); 
 
    }); 
 

 

 
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/css/select2.css" rel="stylesheet" /> 
 

 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/js/select2.min.js"></script> 
 
<div class="select-container"> 
 
    <select class='select-to-select2' multiple> 
 
    <option value='1'>option1</option> 
 
    <option value='2'>option2</option> 
 
    </select> 
 

 
    <select class='select-to-select2' multiple> 
 
    <option value='1'>option1</option> 
 
    <option value='2'>option2</option> 
 
    </select> 
 

 
</div> 
 
<div> 
 
    <button class="add-new-select">Add New Select</button> 
 
</div>

В случае функции .load найдите все элементы выбора, которые должны быть инициализированы в обратном вызове функции загрузки, и вызовите initializeSelect2 для каждого из этих элементов выбора.

Я надеюсь, что это поможет кому-то, кто ищет простое решение.

+1

Спасибо @Roshan Я использовал ваш код для получения select2. Я застрял, проблема только в одном из selct2 работает, другой выбор не получил select2 'initializeSelect2' –

+0

Добавили ли вы класс select-to-select2 в элемент select? – roshan

+0

@ankitsuthar Я использовал jQuery 'clone()' для дублирования элемента 'select', а Select2 работал только на первом, как вы сказали. Я узнал, что ** вам НЕ нужно применять Select2 к элементу, который вы хотите клонировать, но только к клонированным **. Клонирование 'select' с помощью Select2 уже применяется, создает ненадежные результаты. –

-1

Я работал так же, как решение рошана, но не прошел объект select в функции.Это для вывода таблицы из вызова ajax.

$(document).ready(function() { 

     function initSelect2() { 
      $("[id^='DDAlertFreq']").select2({ 
       minimumResultsForSearch: Infinity, 
       allowClear: false, 
       theme: "bootstrap" 
      }); 
     }; 

//define the dropdown and set to variable  
var DDAlertFrequency = '<select id="DDAlertFreq" ><option value="Fifteen_Minutes">15 Minutes</option><option value="Thirty_Minutes">30 Minutes</option><option value="Hour">Hour</option><option value="Two_Hours">2 Hours</option><option value="Three_Hours">3 Hours</option><option value="Four_Hours">4 Hours</option><option value="Six_Hours">6 Hours</option><option value="Eight_Hours">8 Hours</option><option value="Twelve_Hours">12 Hours</option><option value="Day">Day</option></select>' 

function RetrieveUserAlerts(uid) { 
       $.ajax({ 
        url: 'SavedSearches.asmx/LoadUserAlerts', 
        dataType: 'json', 
        method: 'post', 
        data: { userid: uid }, 
        success: function (data) { 
         var tbl = $("#tblAlerts > tbody"); 
         tbl.empty(); 
         $.each(data, function() { 
          userAlert.alert_idx = this['alert_idx']; 
          userAlert.Name = this['Name']; 
          userAlert.price_alert_low = this['price_alert_low']; 
          userAlert.alert_frequency = this['alert_frequency']; 
          userAlert.alert_max_per_day = this['alert_max_per_day']; 
          userAlert.alert_to_email = this['alert_to_email']; 
          userAlert.alert_to_sms = this['alert_to_sms']; 
          userAlert.active = this['active']; 
          userAlert.alert_start_date = moment(this['alert_start_date']).format("MM/DD/YY"); 
          userAlert.alert_end_date = moment(this['alert_end_date']).format("MM/DD/YY"); 
          userAlert.OpenSectionID = this['OpenSectionID']; 
// modify the dropdown to assign unique id and match selection 
          var selectAlert = DDAlertFrequency.replace("DDAlertFreq", "DDAlertFreq_" + userAlert.alert_idx).replace('"' + userAlert.alert_frequency + '"', '"' + userAlert.alert_frequency + '" selected'); 
          var tblRow = '<tr><td>' 
           + userAlert.Name 
          + '</td><td>' 
          + '<input id="txtPriceAlertLow_' + userAlert.alert_idx + '" type="text" class="form-control" value="' + userAlert.price_alert_low + '"/>' 
          + '</td><td>' 
          + '<input id="chkAlertToEmail_' + userAlert.alert_idx + '" type="checkbox" ' + ((userAlert.alert_to_email == true) ? "checked" : "") + ' />' 
          + '</td><td>' 
          + '<input id="chkAlertToEmail_' + userAlert.alert_idx + '" type="checkbox" ' + ((userAlert.alert_to_sms == true) ? "checked" : "") + ' />' 
          + '</td><td>' 
          + selectAlert //modified Select2 dropdown 
          + '</td><td>' 
          + '<input id="txtMaxPerDay_' + userAlert.alert_idx + '" type="text" class="form-control" value="' + userAlert.alert_max_per_day + '"/>' 
          + '</td><td>' 
          + userAlert.alert_start_date 
          + '</td><td>' 
          + userAlert.alert_end_date 
          + '</td><td>' 
          + '<input id="chkActive_' + userAlert.alert_idx + '" type="checkbox" ' + ((userAlert.active == true) ? "checked" : "") + ' />' 
          + '</td><tr>' 
          tbl.append(tblRow); 
          initSelect2(); //call the function to initialize all Select2 dropdowns created 
         }); 
        }, 
        error: function (err) { 
         console.log('Error (RetrieveUserAlerts): ' + JSON.stringify(err, null, 2)); 
        } 
       }); 
      }; 

Прошу прощения за посторонние вещи - я прокомментировал интересующие вас области. Надеюсь, это поможет другим!