1

让多选 jQuery 插件在 Backbone.js 应用程序中工作的魔术是什么?我尝试过使用 SumoSelect、Bootstrap-Multiselect、Chosen 和 jQuery UI 的 MultiSelect。

我有一个模型,它是集合。我在 View 的渲染方法中设置了例如 SumoSelect 插件,代码如下

render : function() {   
....

    // Time for DOM
    setTimeout(function(){
      $(".dropdown-features", this.$el).SumoSelect()
    }, 100);

    return this;                            
},

类 dropdown-features 在模板文件中定义如下

<div class="filter-header">
    <strong>${title}</strong>       
</div>              
        <div>
            <select class="dropdown-features">                   
                <option value="">Choose...</option>
            </select>
        </div>          
</div>

模型和集合通常像在 Backbone.js 应用程序中一样定义。

MyApp.Models = MyApp.Models || {};

(function () {
    'use strict';

    MyApp.Models.Facet = Backbone.Model.extend({

        idAttribute: "name"
    });

})();

MyApp.Collections = MyApp.Collections || {};

(function () {
    'use strict';

    MyApp.Collections.Facets = Backbone.Collection.extend({

        model: MyApp.Models.Facet,

        initialize : function(models, options) {
            if (_.isUndefined(options) ||
                _.isUndefined(options.label) ||
                _.isUndefined(options.title)) {
                throw new Error('Label and title must be given Facets collection in initialization.');
            } else {
                this.label = options.label;
                this.title = options.title;
            }
        },

        getName: function() {
            return this.title;
        },

        getLabel: function() {
            return this.label;
        },

        getFirstLabel: function() {
            return this.first().get('name');
        }
    });    
})();

如果我使用纯 HTML Select-tag 一切正常,但是当尝试使用上面提到的插件时,我无法将任何数据放入 Select Options 中。选择小部件更改为新样式,但不包含除“选择...”之外的任何内容。

我是 Backbone.js 的新用户,我之前在 Backbone.js 应用程序中没有使用过 UI 插件。

谢谢,

麦克风

4

2 回答 2

0

我发现了问题,花了我一点时间,但我明白了。似乎所有这些框架都在采取简单的方法(我不怪他们,我会做同样的事情)并且基本上在做:$(<element you give it>).parent()问题,当你在主干视图中时,在大多数情况下,el还没有附加到DOM。解决方案:

  • 您可以使用setTimeout(不是我的 T 恤,它丑陋且以后难以调试)
  • 你可以创建一个包装器(只需<div>在你的周围添加一个<select>
  • 你可以把它附加到它需要去的地方然后打电话SumoSelect()或等效

示例 1:

我不会向你展示如何去做,setTimeout因为我认为你已经掌握了它。

示例 2:

var WrapperView = Backbone.View.extend({
  tagName: 'div', // <<< ----------------- look here
  template: _.template('<option value="<%=value%>"><%=name%></option>'),
  initialize: function() {
    this.render();
  },
  render: function() {
    var view = this;
    var select = $('<select>');
    view.$el.append(select);
    myCollection.each(function(model){
      select.append(view.template(model.toJSON()));
    });
    select.SumoSelect(); // <<< ----------------- look here
    return this.el;
  }
});

$('body').append((new WrapperView()).el);

示例 3:

var WaitView = Backbone.View.extend({
  tagName: 'select', // <<< ----------------- look here
  template: _.template('<option value="<%=value%>"><%=name%></option>'),
  initialize: function() {
    this.render();
  },
  render: function() {
    var view = this;
    myCollection.each(function(model){
      view.$el.append(view.template(model.toJSON()));
    });
    return this.el;
  }
});

var waitview = new WaitView();
$('body').append(waitview.el);
waitview.$el.SumoSelect(); // <<< ----------------- look here

就个人而言,我最喜欢选项 2,它是最紧凑的选项,选项 1 我非常讨厌,选项 3 我可以保证你会忘记它,3 个月后回来,然后一头雾水;但最终,它是你的决定。以下是示例 2 和 3:http: //jsfiddle.net/ghcp2g2t/4/


PS.下次你问一个 JS 问题时,非常漂亮,请添加一个 jsfiddle 或任何类型的问题测试环境,跟踪 CDN url 并设置测试需要大量时间。

于 2016-01-11T17:30:52.550 回答
0

这可能是范围问题...

// Time for DOM
setTimeout(function(){
  $(".dropdown-features", this.$el).SumoSelect()
}, 100);

this.$el 可能是未定义的。这行得通吗?

var _this = this;

// Time for DOM
setTimeout(function(){
  $(".dropdown-features", _this.$el).SumoSelect()
}, 100);

或者我个人的偏好:

var _this = this;

// Time for DOM
setTimeout(function(){
  _this.$el.find('.dropdown-features').SumoSelect()
}, 100);
于 2016-01-11T21:36:23.827 回答