2013-12-15 5 views
5

Di seguito è la struttura di codice corrente che ho in atto per una raccolta che ho creato manualmente. Ho un file json sul mio server che sto cercando di caricare e sostanzialmente rimuovo quello manuale e costruisco una collezione basata su quei dati. Mi chiedevo che cosa avrei bisogno di cambiare sotto al mio codice per aiutare a sistemare questo.backbone popola la raccolta da json esterno

 var Game = Backbone.Model.extend({ 
      defaults: { 
       name: 'John Doe', 
       age: 30, 
       occupation: 'worker' 
      } 
     }); 


     var GameCollection = Backbone.Collection.extend({ 
      model: Game, 
      url: 'path/to/json', 

      parse: function(response) { 
       return response; 
      } 
     }); 

     var GamesView = Backbone.View.extend({ 
      tagName: 'ul', 

      render: function() { 
       //filter through all items in a collection 
       this.collection.each(function(game){ 
        var gameView = new GameView({model: game}); 
        this.$el.append(gameView.render().el); 
       }, this) 

       return this; 
      } 
     }); 

     var GameView = Backbone.View.extend({ 
      tagName: 'li', 

      template: _.template($('#gameTemplate').html()), 

      render: function() { 
       this.$el.html(this.template(this.model.toJSON())); 
       return this; 
      } 
     }); 

     var gameCollection = new GameCollection([ 
      { 
       name: 'John Doe', 
       age: 30, 
       occupation: 'worker' 
      }, 
      { 
       name: 'John Doe', 
       age: 30, 
       occupation: 'worker' 
      }, 
      { 
       name: 'John Doe', 
       age: 30, 
       occupation: 'worker' 
      } 
     ]); 

     var gamesView = new GamesView({collection: gameCollection}); 

     $(document.body).append(gamesView.render().el); 
+0

Quindi stai dicendo 'nuova GameCollection (some_big_array_of_stuff)' ma ora vuoi caricare la raccolta dal server? –

+0

Sì, mi piacerebbe non usare la matrice manuale di oggetti che ho creato per il test, ma ora voglio provare a caricare un oggetto json che ho sul server e provare ad analizzare quei dati. Non sono sicuro di come procedere. – Anks

risposta

10

Questa è una delle tante cose da amare su Backbone. Non so cosa stai usando per il tuo back-end, ma dichiari di avere un file JSON sul tuo server, si spera che un file JSON sia pieno dei modelli che dovrebbero essere nella tua collezione. E ora ecco il codice magico (rullo di tamburi per favore ..):

var GameCollection = Backbone.Collection.extend({ 
    model: Game, 
    url: 'path/to/json/on/external/server', 
}); 

var gameCollection = new GameCollection(); 
gameCollection.fetch(); 

Non c'è molto, vero? Naturalmente ci sono diverse opzioni che puoi aggiungere o modificare a fetch, quindi dai un'occhiata qui: http://backbonejs.org/#Collection-fetch. Backbone utilizza jQuery.ajax() come valore predefinito, quindi controlla i documenti qui per vedere tutte le opzioni: http://api.jquery.com/jQuery.ajax/

Non dovresti avere bisogno dell'analisi personalizzata nella tua raccolta a meno che i tuoi modelli sul server non corrispondano ai tuoi modelli di backbone.

Cose da sapere: fetch è asincrono. Ci vuole tempo per parlare con il server, e il resto del tuo javascript andrà avanti e completato. Probabilmente avrai bisogno di aggiungere almeno una funzione di callback all'opzione success, che verrà chiamata al termine di fetch, ed è bene aggiungere qualcosa a error, nel caso qualcosa vada storto. È possibile aggiungere dati come stringa di query in modo che il back-end possa utilizzarli utilizzando l'opzione data, il dato deve essere un oggetto. Ecco un esempio:

gameCollection.fetch({ 
    data: {collection_id: 25}, 
    success: function(){ 
    renderCollection(); // some callback to do stuff with the collection you made 
    }, 
    error: function(){ 
    alert("Oh noes! Something went wrong!") 
    } 
}); 

fetch dovrebbe ricevere i dati come JSON, così il vostro URL deve sia esclusivo JSON ritorno o essere configurato per rilevare una richiesta AJAX e rispondere ad essa con JSON.

+0

Giusto. Ma la parte difficile per un (possibile) principiante è che 'fetch' è una chiamata AJAX ed è necessario collegare' render' ad alcuni eventi (ad esempio ''reset'' o qualcosa nascosto dietro una callback' success'). –

+0

@muistooshort, buon punto, aggiungerò alcuni suggerimenti alla risposta. – RustyToms

+1

Questo dovrebbe farlo. Se OP ha impostato gli ascoltatori per un cambiamento nella raccolta che lo farebbe funzionare senza una richiamata, ma penso che sarà necessaria una richiamata nella maggior parte delle situazioni. – RustyToms

1

In primo luogo è necessario recuperarlo dal server come ha detto RustyToms. E l'altra considerazione è come forzare la vista di raccolta a eseguire nuovamente il rendering una volta raccolti i dati dal server, come ha commentato muistooshort.

Se si manipola fetch o sync, è necessario farlo più volte quando sono presenti più raccolte nell'app.

Facendo tale è nativa con Marionette, ma in Backbone pianura è possibile simulare il metodo di CollectionView di Marionette e fare come:

//For the collection view 
var GamesView = Backbone.View.extend({ 
    initialize: function({ 
    this.listenTo(this.collection, 'reset', this.render, this); 
    }); 
    // Others 
}); 

Poi, quando i dati di raccolta recuperati dal server, la collezione sarà innescare un evento reset , la vista della raccolta ha notato questo evento e si rende nuovamente.

Per più di collezioni, è possibile estrarre il codice in un oggetto padre in app e ereditare da questo.

var App.CollectionView = Backbone.View.extent({ 
    initialize: //code as above 
}); 

var GamesView = App.CollectionView.extend({ 
    //Your code without initialize 
}); 
0

So che questo è un po 'vecchio, a questo punto, ma ha voluto rispondere per chiunque altro bloccato su questo.

Il codice sembra venire dal tutorial trovati qui: http://codebeerstartups.com/2012/12/a-complete-guide-for-learning-backbone-js/

anch'io riutilizzati l'applicazione demo trovato in quella tutorial e aveva problemi di rendering utilizzando i dati esterni.

La prima cosa è che i dati stessi devono essere convertiti in JSON valido, altrimenti si otterrà un errore .parse().

SyntaxError: JSON.parse: expected property name or '}' at line 3 column 9 of the JSON data 

o

error: SyntaxError: Unexpected token n 

Nel file di origine di dati, le proprietà degli oggetti devono essere circondati da virgolette. Esso dovrebbe essere simile a questo:

[ 
    { 
    "name": "John Doe", 
    "age": 30, 
    "occupation": "worker" 
    }, 
    { 
    "name": "John Doe", 
    "age": 30, 
    "occupation": "worker" 
    }, 
    { 
    "name": "John Doe", 
    "age": 30, 
    "occupation": "worker" 
    } 
] 

In secondo luogo, una volta che è chiaro i dati esterni sta caricando, abbiamo bisogno di farlo rendere. Ho risolto questo problema (forse senza vergogna) spostando il comando render() nella funzione riuscita del tuo gameCollection.fetch().

gameCollection.fetch({ 
    success: function(collection, response, options) { 
    console.log('Success!! Yay!!'); 
    $(document.body).append(gamesView.render().el); 
    }, 
    error: function(collection, response, options) { 
    console.log('Oh, no!'); 
    // Display some errors that might be useful 
    console.error('gameCollection.fetch error: ', options.errorThrown); 
    } 
}); 

ci sono modi certamente meglio per ottenere questo risultato, ma questo metodo converte direttamente il codice imparato nel tutorial in qualcosa che funziona con dati esterni.