2013-09-27 11 views
5

Ich benutze Backbone Marionetten CollectionView. Ich versuche anzugeben, dass die Sammlung geladen wird, also verwende ich die leere Ansicht, um einen Loader anzuzeigen.Backbone Marionette: Verwenden von emptyView zum Laden

Dies ist jedoch schlechte Logik, weil Sammlungen manchmal leer sind, und daher wird es zu einem defekten Loader.

Ich habe versucht, dieses Skript verwenden, aber es hat nicht funktioniert: https://github.com/surevine/marionette-loadingview-plugin

Hat jemand eine bessere Lösung? Heres meines aktueller Code:

//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" 
    }) 
}) 

Antwort

4

Was ich in der Regel tun ist, um den ‚Antrag‘ hören und ‚sync‘ Ereignis der Sammlung/Models. Etwas wie folgt aus:

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

Hm Ich mag diese Lösung wirklich, aber ich denke nicht, daß Collection: { 'request' korrekt ist. Die Synchronisierung wird aufgerufen, die Anforderung jedoch nicht. – azz0r

+0

Sie können das wahrscheinlich beheben, indem Sie nach dem Rendern der Ansicht die Methode 'fetch' aufrufen. Zum Beispiel: 'view = new View(); $ ('body'). append (view.render(). el); view.collection.fetch() '. – gbsice

+0

Das scheint irgendwie unordentlich, direkte Manipulation Dom und alle – azz0r

1

Sie können einfach einige statische HTML-Code in das Element liefern, wo Sie planen, Ihre Ansicht zu zeigen. Der statische Inhalt wird beim Laden der Seite angezeigt. Wenn das Modell erfolgreich Daten zurückgibt, werden Sie die Ansicht anzeigen und dadurch den statischen Inhalt überschreiben.

Überprüfen Sie diese jsFiddle, die es zeigt. Der statische Inhalt sagt nur "Loading ...", aber natürlich können Sie es mit Spinner-Gif's und so weiter machen. 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> 

Code:

// 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(); 
Verwandte Themen