2013-09-27 14 views
5

Sto usando Backbone Marionettes CollectionView. Sto cercando di indicare che la raccolta si sta caricando, così sto usando il emptyView per visualizzare un loader.Marionetta backbone: using emptyView per il caricamento

Tuttavia questa è una cattiva logica, perché a volte le raccolte sono vuote e quindi diventa un loader danneggiato.

Ho provato ad utilizzare questo script, ma non ha funzionato: https://github.com/surevine/marionette-loadingview-plugin

Qualcuno ha una soluzione migliore? Ecco il mio codice corrente:

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

risposta

4

Quello che faccio di solito è ascoltare gli eventi "richiesta" e "sincronizzazione" della raccolta/modello. Qualcosa del genere:

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 Mi piace molto questa soluzione, ma non penso collectionEvents: { 'richiesta' è corretto. la sincronizzazione viene chiamata, ma la richiesta no. – azz0r

+0

Probabilmente puoi risolvere il problema chiamando il metodo 'fetch' DOPO il rendering della tua vista. Ad esempio: 'view = new View(); $ ('Body') aggiungere (view.render() el.).; view.collection.fetch() '. – gbsice

+0

Sembra un po 'disordinato, coinvolge la manipolazione diretta di dom e tutto – azz0r

1

È possibile fornire semplicemente del codice HTML statico nell'elemento in cui si prevede di mostrare la visualizzazione. Il contenuto statico verrà visualizzato al caricamento della pagina e quando il modello restituisce correttamente i dati, mostrerai la vista e quindi sovrascrivi il contenuto statico.

Dai un'occhiata a questo jsFiddle che lo dimostra. Il contenuto statico dice solo "Caricamento in corso ..." ma ovviamente puoi renderlo elegante come ti piace con le gif di spinner e tutto il resto. 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> 

Codice:

// 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(); 
Problemi correlati