Backbone.view listenTo集合删除事件

时间:2014-06-11 00:47:48

标签: backbone.js

我正在试着正确地听取删除集合上的事件以重新渲染视图。

我的观点如下:

define(function(require) {
    var templ     = require('text!./../../templates/delete-deal-templ.html'),
        utils     = require('utils'),
        dealName  = '' ;


    return Backbone.View.extend({

        events: { 
             'click #delete-deal-btn' : 'deleteDealHandler',
        },

        template: _.template(templ),

        initialize: function() {
            this.listenTo(this.collection, 'remove', this.render);
        },

        render: function() {
            $(this.el).html(this.template({deals: this.collection}));
            ...
            return this;
        },

        deleteDealHandler: function(e) {
            e.preventDefault();
            ...
        }

    });
}); 

并使用这样的集合正确实例化:

DealEngine.getDeleteDealView = function() {
    require(['models/deal-model','views/delete-deal-view'], function(DealModel, DeleteDealView) {
        var DealCollection = Backbone.Collection.extend({
                model: DealModel,
                url: '/alldealsofbusiness/' + DealEngine.businessID
            }),
            dealCollection = new DealCollection(),   
            promise = dealCollection.fetch();
        promise.done(function(collection) {
            new DeleteDealView({collection: collection}).render();
            DealEngine.router.navigate('deletedeal');
            window.scrollTo(0, DealEngine.top_pos);
        }); 
        promise.fail(function() {
            var utils = require('utils');
            utils.growl('Your deals', 'could not be retrieved from our cloud, please try again!', 'error');
        });
    });
};

模板:

<div id="view-header" class="align-center">
    <h2>Delete a Deal</h2>
    <h5>Please note: Deals are automatically deleted after they have expired</h5>
</div>
<div class="row">
    <div class="col-xs-1 col-md-2"></div>
    <div class="col-xs-10 col-md-8">
        <div class="form-style" >
            <div id="select-deal" class="form-group dropdown">
                <a id="deal-select" class="btn btn-outline-inverse btn-lg dropdown-toggle" data-toggle="dropdown" role="button">
                    Select Deal
                    <span class="caret"></span>
                </a>
                <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
                    <% _.each(deals, function(deal) { %>
                        <li><a class="deal-option"><%= deal.deal.name %></a></li>
                    <% }); %>
                </ul>
            </div>
            <div class="col-xs-12 col-md-12">
                <div class="row align-center">
                    <div class="form-group">
                        <button id="delete-deal-btn" type="button" class="btn btn-outline-inverse btn-lg">Delete</button>
                    </div> 
                </div>
            </div>
        </div>
    </div>
    <div class="col-xs-1 col-md-2"></div>
</div>

this.collection对象有正确的数据,this.render是一个函数,但是,initial initial方法抛出

  

未捕获的TypeError:undefined不是函数

显然,我做错了什么,如果有人可以对此有所了解,我会很感激。

2 个答案:

答案 0 :(得分:0)

我注意到的一件事是你设置一个等于require调用的变量,我相信它是异步的。因此,即使该变量尚未设置,javascript也会继续处理...您可能想要尝试类似的内容:

    var templ = require('text!./../../templates/delete-deal-templ.html', function(templ){
//process logic in here
});

或者您可以在模块的define调用中将变量定义为依赖项。

我已将其重写为类似的内容,这对我有用(您必须对其进行修改以符合您要执行的操作)。请注意,当您从模型中获取属性时,您希望使用deal.get(&#39; name&#39;)而不是deal.name(除非该属性直接在对象上设置)。

    <script type="text/template" id="testTemplate">
        <div id="view-header" class="align-center">
            <h2>Delete a Deal</h2>
            <h5>Please note: Deals are automatically deleted after they have expired</h5>
        </div>
        <div class="row">
            <div class="col-xs-1 col-md-2"></div>
            <div class="col-xs-10 col-md-8">
                <div class="form-style">
                    <div id="select-deal" class="form-group dropdown">
                        <a id="deal-select" class="btn btn-outline-inverse btn-lg dropdown-toggle"
                           data-toggle="dropdown" role="button">
                            Select Deal
                            <span class="caret"></span>
                        </a>
                        <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
                            <% deals.each(function(deal) { %>
                            <li><a class="deal-option"><%= deal.get('name') %></a></li>
                            <% }); %>
                        </ul>
                    </div>
                    <div class="col-xs-12 col-md-12">
                        <div class="row align-center">
                            <div class="form-group">
                                <button id="delete-deal-btn" type="button" class="btn btn-outline-inverse btn-lg">
                                    Delete
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="col-xs-1 col-md-2"></div>
        </div>
    </script>

    <script type="text/javascript">
        (function (_, Backbone, $) {
$(document).ready(function () {
            var templateHtml = $('script#testTemplate').html();
            var templ = _.template(templateHtml);

            var view = Backbone.View.extend({
                template: templ,
                render: function () {
                    this.$el.html(this.template({deals: this.collection}));
                    return this;
                },
                initialize: function () {
                    this.collection.on('remove', this.render, this);
                }
            });

            var testModel = Backbone.Model.extend({
                defaults: {
                    name: 'test2'
                }
            });

            var dealCollection = new Backbone.Collection();
            dealCollection.add(new testModel());

            dealCollection.add(new testModel());

            var deleteDealView = new view({
                collection: dealCollection
            });

            var html = deleteDealView.render().$el.html();
            $('#test').append(html);
});
        })(_, Backbone, jQuery);
    </script>

顺便说一下,我会调查Marionette,它可以为你处理大部分样板渲染逻辑。 https://github.com/marionettejs/backbone.marionette/tree/master/docs

答案 1 :(得分:0)

好吧,我的问题的根源是将服务器响应传递给视图而不是集合。 这是正确的代码段:

var DealCollection = Backbone.Collection.extend({
            model: DealModel,
            url: '/alldealsofbusiness/' + DealEngine.businessID
        }),
        dealCollection = new DealCollection(),   
        promise = dealCollection.fetch();
    promise.done(function() {
        new DeleteDealView({collection: dealCollection}).render();
        DealEngine.router.navigate('deletedeal');
        window.scrollTo(0, DealEngine.top_pos);
    });