2013-09-27 10 views
5

Używam Backbone Marionettes CollectionView. Próbuję wskazać, że kolekcja jest ładowanie, todo więc używam emptyView do wyświetlania programu ładującego.Marionetka szkieletu: użycie emptyView do załadowania

Jest to jednak zła logika, ponieważ czasami kolekcje są puste, a zatem staje się zepsutym programem ładującym.

Próbowałem za pomocą tego skryptu, ale nie zrobił praca: https://github.com/surevine/marionette-loadingview-plugin

Czy ktoś ma lepsze rozwiązanie? Oto mój obecny kod:

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

Odpowiedz

4

Zazwyczaj słucham zdarzeń "Żądanie" i "Synchronizacja" kolekcji/modelu. Coś takiego:

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 ja naprawdę podoba Ci się to rozwiązanie, ale nie sądzę collectionEvents: { 'żądanie' jest prawidłowa. Synchronizacja zostanie wywołana, ale żądanie nie. – azz0r

+0

Prawdopodobnie można to naprawić, wywołując metodę "POBIERZ" PO renderowaniu widoku. Na przykład: 'view = new View(); $ ("body"). append (view.render(). el); view.collection.fetch() '. – gbsice

+0

To wydaje się trochę nieporządne, włączając w to bezpośrednią manipulację domem i wszystko, co jest – azz0r

1

Możesz po prostu podać trochę statycznego kodu HTML w elemencie, w którym chcesz pokazać swój widok. Statyczna zawartość zostanie wyświetlona po załadowaniu strony i gdy model pomyślnie zwróci dane, wyświetli widok, a tym samym nadpisze statyczną zawartość.

Sprawdź jsFiddle, który to demonstruje. Statyczna treść po prostu mówi "Ładowanie ...", ale oczywiście możesz sprawić, że będzie wyglądać tak fantazyjnie, jak lubisz, używając spinner gif i wszystkich innych. 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> 

Kod:

// 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(); 
Powiązane problemy