2013-12-15 4 views
5

Poniżej znajduje się aktualna struktura kodu, którą mam na miejscu dla kolekcji, którą ręcznie skonstruowałem. Mam plik json na moim serwerze, który teraz próbuję załadować i zasadniczo usunąć ręczny i skonstruować kolekcję na podstawie tych danych. Zastanawiałem się, co powinienem zmienić poniżej na mój kod, żeby to pomieścić.kręgosłup wypełnia kolekcję z zewnętrznego json'a

 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

Więc obecnie mówisz 'new GameCollection (some_big_array_of_stuff)', ale teraz chcesz załadować kolekcję z serwera? –

+0

Tak, nie chciałbym używać ręcznej tablicy obiektów, które stworzyłem do testowania, ale teraz chcę spróbować załadować obiekt json, który mam na serwerze i spróbować przeanalizować te dane. Nie wiem, jak sobie z tym poradzić. – Anks

Odpowiedz

10

Jest to jedna z wielu rzeczy, które można kochać w grze Backbone. Nie wiem, czego używasz dla twojego backendu, ale oświadczasz, że masz plik json na twoim serwerze, mam nadzieję, że plik json jest pełen modeli, które powinny być w twojej kolekcji. A teraz jest magiczny kod (drumroll proszę ..):

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

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

Nie za dużo, prawda? Oczywiście istnieje kilka opcji, które można dodać lub zmienić na fetch, więc sprawdź dokumentację tutaj: http://backbonejs.org/#Collection-fetch. Backbone wykorzystuje jQuery.ajax() być domyślny, więc sprawdź docs tutaj, aby zobaczyć wszystkie opcje: http://api.jquery.com/jQuery.ajax/

Nie należy potrzebują niestandardowej parse w swojej kolekcji, chyba że twoje modele na serwerze nie pasują do modeli szkieletowych.

Co warto wiedzieć: fetch jest asynchroniczny. Potrzeba czasu, aby porozmawiać z serwerem, a reszta skryptu javascript będzie kontynuowana i zakończona. Prawdopodobnie będziesz musiał przynajmniej dodać funkcję zwrotną do opcji success, która zostanie wywołana po zakończeniu fetch i dobrze jest dodać coś do error, na wypadek gdyby coś poszło nie tak. Możesz dodać dane jako ciąg zapytania, aby twój backend mógł go użyć, używając opcji data, dane muszą być obiektem. Oto przykład:

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 powinien odbierać dane jako JSON, więc url powinien albo wyłącznym JSON zwrot lub być skonfigurowany do wykrywania żądania AJAX i odpowiedzieć na nią z JSON.

+0

Dobrze. Ale trudną częścią początkującego (możliwego) jest to, że 'fetch' jest wywołaniem AJAX i musisz dołączyć' render' do niektórych zdarzeń (powiedz '' reset'' lub coś ukrytego za 'callbackiem 'sukcesu). –

+0

@muistooshort, dobra uwaga, dodam kilka wskazówek do odpowiedzi. – RustyToms

+1

To powinno to zrobić. Jeśli OP ma detektory skonfigurowane dla zmiany w kolekcji, która sprawi, że będzie działała bez wywołania zwrotnego, ale myślę, że w większości sytuacji będzie wymagane wywołanie zwrotne. – RustyToms

1

Po pierwsze musisz pobrać z serwera, jak powiedział RustyToms. Drugą kwestią jest, jak zmusić widok kolekcji do ponownego renderowania się po zebraniu danych z serwera, jak komentuje muistooshort.

Podczas manipulowania lub sync musisz zrobić to wiele razy, gdy w aplikacji jest więcej niż jedna kolekcja.

Robi takie pochodzi z marionetka, ale w zwykłym Backbone można naśladować metody Lalkowych w CollectionView i zrobić takie:

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

Potem, gdy gromadzenie danych pobrane z serwera, zbieranie wywoła zdarzenie reset , widok kolekcji zauważył to zdarzenie i ponownie się renderował.

Dla więcej niż jednej kolekcji można wyodrębnić kod do obiektu nadrzędnego w aplikacji i dziedziczyć z niego.

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

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

Wiem, że w tym momencie jest trochę stary, ale chciałem odpowiedzieć, bo ktoś na tym utknął.

Kod wydaje się pochodzić z samouczka znaleźć tutaj: http://codebeerstartups.com/2012/12/a-complete-guide-for-learning-backbone-js/

ja też ponownie przeznaczona aplikację demo znaleźć w tym poradniku i miał problemy renderowania przy użyciu danych zewnętrznych.

Pierwszą rzeczą, o której mowa jest to, że dane muszą zostać przekonwertowane na prawidłowy JSON, inaczej otrzymasz błąd o wartości .parse().

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

lub

error: SyntaxError: Unexpected token n 

W pliku źródła danych, własności obiektu muszą być w cudzysłowie. Powinno to wyglądać mniej więcej tak:

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

drugie, gdy jest oczywiste, dane zewnętrzne się ładuje, musimy to uczynić. Rozwiązałem to (być może niegodnie), przenosząc polecenie render() do funkcji powodzenia twojego 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); 
    } 
}); 

pewnością istnieją lepsze sposoby, aby to osiągnąć, ale ta metoda bezpośrednio konwertuje kod nauczył w tutorialu w coś, co działa z danymi zewnętrznymi.