Как использовать Select2 с представлениями Backbone Marionette вне DOM

Я пытаюсь интегрировать виджет Select2 с представлениями Backbone Marionette. Моя простая установка использует Marionette.CollectionView для создания и обработки тега select и Marionette.ItemViews для отображения тегов параметров.

В основном это выглядит так:

SelectCollectionView = Backbone.Marionette.CollectionView.extend({
  itemView : SelectItemView,
  tagName : "select",

  onRender : function() {
    this.$el.select2();
  },

  onClose : function() {
    this.$el.select2("destroy");
  }
}

SelectItemView = Backbone.Marionette.ItemView.extend({
  tagName : "option",

  render : function() {
    // create the needed option tags
  }
}

Как видите, я должен вызвать методы инициализации и уничтожения Select2 при рендеринге и закрытии, чтобы добавить необходимые дополнительные теги в DOM.

Эта установка работает очень хорошо, если представление, обрабатывающее тег select (SelectCollectionView), уже добавлено в DOM. Если это не так, дополнительные теги Select2 теряются, поскольку они не являются частью $el SelectCollectionView и, следовательно, не добавляются в DOM.

Интересно, как это изящно решить? Можно было бы добавить дополнительный контейнер div и визуализировать все внутри него, но это привело бы к созданию дополнительного кода для скрипта и модели DOM. Это также делает мой взгляд менее универсальным. Я просто надеюсь на лучшее решение, о котором я не думал.


person MerlinDE    schedule 29.05.2013    source источник
comment
я не понимаю, вы используете onRender, поэтому элементы select и все option уже отображаются и добавляются в дом. Почему тогда ваше решение не должно работать?   -  person Luke    schedule 30.05.2013
comment
@Luke Вызов render() на Backbone просто отображает представление в его текущем el. Этот el может просто существовать в памяти и не должен быть уже присоединен к DOM. Это создает проблемы со многими виджетами, которые полагаются на работу внутри DOM — одна из причин, по которой я выбрал Select2 вместо Chosen.   -  person MerlinDE    schedule 30.05.2013
comment
Вы пробовали использовать onShow вместо onRender ?   -  person David Sulc    schedule 30.05.2013


Ответы (2)


Как вы подозреваете, вам понадобится блок div, чтобы окружить ваш шаблон. К счастью, это действительно просто. Вместо того, что у вас есть сейчас:

SelectCollectionView = Backbone.Marionette.CollectionView.extend({
  tagName : "select"

Избавьтесь от tagName и в своем шаблоне (я предполагаю, что вы используете Handlebars или Underscore или что-то в этом роде) определите свой HTML:

шаблон.html

<select class="whatever-you-want"></select>

Тогда на ваш взгляд:

SelectCollectionView.js

SelectCollectionView = Backbone.Marionette.CollectionView.extend({
  template: _.template(templateHtml)

Marionette автоматически обернет div вокруг вашего <select>, а затем вся дополнительная разметка, добавленная select2, будет безопасно содержаться в $el представления.

person brettjonesdev    schedule 30.05.2013

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

    var Select2View = Mn.View.extend({
      template: _.template('<select class="form-control"><option></option></select>'),

      onRender:function() {
        this.$el.find('select').select2();
      }
    });

Важная часть здесь

this.$el.find('select').select2();

которые выбирают тег select внутри элемента. Но в моем примере я не использую представление коллекции. Если вам нужно получить данные, вы можете использовать:

this.$el.find('select').select2({data: ['1','2','3','4']});

Также select2 предоставляет очень хороший API для управления выбранными элементами во время выполнения.

person Yuliyan    schedule 18.04.2018