2016-04-05 4 views
0

Я пытаюсь использовать flexselect.js, чтобы упростить использование ящиков выбора и jquery.formset.js для динамического добавления новых форм форм.reinitialize flexselect.js после добавления новых элементов управления с помощью javascript

enter image description here

Я использование встроенных FormSets здесь. Самая верхняя строка - это форма, в то время как поля в серых квадратах и ​​формах формируют поля. Поля ввода с «-----------» представляют собой поля выбора, которые flexselect.js преобразует в поля ввода.

Все работает хорошо, пока я не добавлю новую форму формы с JQuery (jquery.formset.js), нажав «Добавить элемент» в свой интерфейс.

enter image description here

новая форма добавляется jquery.formset, как ожидалось, но первое поле (один я выделен красным цветом) не правильно загружено flexselect.js, следовательно, его пустой вместо содержащего «------- ----- "как тот, что находится поверх него (тот, который я выделил желтым цветом). Когда я нажимаю на поле ввода, фокус покидает поле ввода и переходит в поле, выделенное желтым цветом. Короче говоря, flexselect работает только для выделенных ящиков, которые присутствовали, когда firstselect был сначала инициализирован.

Может ли кто-нибудь сказать мне, как повторно инициализировать 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> 

ответ

0

Я нашел рабочее решение для указанной задачи. Это связано с тем, как работает jquery.formset.js. Если кто-то другой ударит по этому кирпичу, вот как я его исправил.

Когда вы нажимаете «Добавить элемент», jquery.formset.js знает контейнер, который содержит первоначально отображаемые формы форм. Из этого следует, этот алгоритм:

  1. Clone один из formset форм
  2. добавить его в DOM после последнего formset формы контейнера
  3. Пересчитать и изменить id, name и другие атрибуты
  4. и т.д.

flexselect.js с другой стороны работает, ища указанные select теги в DOM и добавляя к ним некоторые данные.

Добавление клонирования select s, которое уже было обработано обратно в 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; 
     }); 

to .....

$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> 

Это, как я установил его. Надеюсь, это поможет кому-то другому.