2013-09-27 4 views
5

私はBackbone Marionettes CollectionViewを使用しています。私はコレクションがロードされていることを指示しようとしているので、loadViewを表示するためにemptyViewを使用しています。バックボーンMarionette:読み込みにemptyViewを使用

ただし、コレクションが空の場合があり、壊れたローダーになることがあるため、これは悪いロジックです。

私はこのスクリプトを使用してみましたが、それは仕事をdidntの:https://github.com/surevine/marionette-loadingview-plugin

誰もがよりよい解決策を持っていますか?現在のコードは次のとおりです:

//loadingview 
define(["marionette", "text!app/templates/loading.html"], function(Marionette, Template) { 
    "use strict"; 
    return Backbone.Marionette.ItemView.extend({ 
    template: Template 
    }); 
}) 

//collection 
define(["marionette", "text!app/templates/events/collection.html", "app/collections/events", "app/views/events/item", 'app/views/loading'], function (Marionette, Template, Collection, Row, LoadingView) { 
    "use strict" 
    return Backbone.Marionette.CompositeView.extend({ 
    template: Template, 
    itemView: Row, 
    itemViewContainer: "ul", 
    emptyView: LoadingView, 
    initialize: function() { 
     this.collection = new Collection() 
     return this.collection.fetch() 
    } 
    }) 
}) 

//item 
define(["marionette", "text!app/templates/events/item.html"], function(Marionette, Template) { 
    "use strict"; 
    return Backbone.Marionette.ItemView.extend({ 
    template: Template, 
    tagName: "li" 
    }) 
}) 

答えて

4

私は通常、コレクション/モデルの '要求'と '同期'イベントを聞きます。このような何か:

var View = Backbone.Marionette.CompositeView.extend({ 
    template: Template, 
    itemView: Row, 
    itemViewContainer: "ul", 

    collectionEvents: { 
    'request': 'showLoading', 
    'sync': 'hideLoading' 
    }, 

    initialize: function() { 
    this.collection = new Collection(); 
    return this.collection.fetch(); 
    } 

    showLoading: function() { 
    this.$el.addClass('loading'); 
    }, 

    hideLoading: function() { 
    this.$el.removeClass('loading'); 
    } 
}); 
+0

フム、私は本当にこのソリューションのように、私はされるCollectionEventsを思ういけない:{ '要求が' 正しいです。 syncは呼び出されますが、要求は行いません。 – azz0r

+0

あなたのビューをレンダリングした後に 'fetch'メソッドを呼び出すことで、それを修正することができます。次に例を示します。 'view = new View(); $( 'body')。append(view.render()。el); view.collection.fetch() ' – gbsice

+0

これは面倒で、直接のDOM操作とすべての操作を伴います – azz0r

1

あなたは、単にあなたのビューを表示する予定の要素にいくつかの静的なHTMLを供給することができます。静的コンテンツはページの読み込みに表示され、モデルが正常にデータを返すと、ビューが表示され、静的コンテンツが上書きされます。

これを実証するjsFiddleをご覧ください。静的なコンテンツは単に「Loading ...」と書かれていますが、もちろんスピナーのgifやすべてで好きなだけファンシーにすることもできます。 http://jsfiddle.net/tonicboy/5dMjD/6/

HTML:

<header> 
    <h1>A Marionette Playground</h1> 
</header> 
<article id="main">LOADING...</article> 
<script type="text/html" id="sample-template"> 
    Store name: <span> <%= venue.name %> </span>. 
</script> 

はコード:

// Define the app and a region to show content 
// ------------------------------------------- 

var App = new Marionette.Application(); 

App.addRegions({ 
    "mainRegion": "#main" 
}); 

// Create a module to contain some functionality 
// --------------------------------------------- 

App.module("SampleModule", function (Mod, App, Backbone, Marionette, $, _) { 

    // Define a view to show 
    // --------------------- 

    var MainView = Marionette.ItemView.extend({ 
     template: "#sample-template" 
    }); 

    // Move this to outside the Controller 
    // as this gives access to other Views 
    // Otherwise you would have to declare a New Model inside every controller 
    var Book = Backbone.Model.extend({ 
     url: 'https://api.foursquare.com/v2/venues/4afc4d3bf964a520512122e3?oauth_token=EWTYUCTSZDBOVTYZQ3Z01E54HMDYEPZMWOC0AKLVFRBIEXV4&v=20130808', 
     toJSON: function() { 
      return _.clone(this.attributes.response); 
     } 
    }) 

// Define a controller to run this module 
    // -------------------------------------- 
    var Controller = Marionette.Controller.extend({ 

     initialize: function (options) { 
      this.region = options.region; 
      this.model = options.model; 
      // Listen to the change event and trigger the method 
      // I would prefer this as this is a cleaner way of binding and 
      // handling events 
      this.listenTo(this.model, 'change', this.renderRegion); 
     }, 
     show: function() { 
      this.model.fetch(); 
     }, 
     renderRegion: function() { 
      var view = new MainView({ 
       el: $("#main"), 
       model: this.model 
      }); 
      this.region.attachView(view); 
      this.region.show(view); 
     } 
    }); 


    // Initialize this module when the app starts 
    // ------------------------------------------ 

    Mod.addInitializer(function() { 
     // I would create the model here and pass it to the controller 
     var myBook = new Book(); 
     Mod.controller = new Controller({ 
      region: App.mainRegion, 
      model: myBook 
     }); 
     Mod.controller.show(); 
    }); 
}); 

// Start the app 
// ------------- 

App.start(); 
関連する問題