2013-03-28 23 views
28

Właśnie rozpoczął naukę ember.js (kupione screencast PeepCode) i uczę się od niej dość gładko, ale został uruchomiony na problem, kiedy próbuje pisać moją pierwszą aplikację Ember.Dlaczego nie mój ember.js modelu trasy miano?

Oto (zagnieżdżone) wyznaczania tras:

App.Router.map(function() { 
    this.resource('bases', { path: '/' }, function() { 
     this.resource('base', { path: ':base_id' }, function() { 
      this.resource('places', function() { 
       this.resource('place', { path: ':place_id' }); 
      }); 
     }); 
    }); 
}); 

Pozwala to adresy, takie jak to, że: domain.com/#/yokota-ab-japan/places/4c806eabd92ea093ea2e3872

yokota-ab-japan jest identyfikator ID podstawy (bazy lotniczej w Japonii) 4c806eabd92ea093ea2e3872 jest id z miejsca na Foursquare

Gdy trasa miejsc jest trafiony, ja setup dane o wywołaniu Foursquare API, iteracyjne nad JSON, aby utworzyć arr ay App Applace i zwróć tę tablicę.

App.PlacesRoute = Ember.Route.extend({ 
    model: function() { 
     var placesData = Ember.A(); 
     $.getJSON('https://api.foursquare.com/v2/venues/search?ll=35.744771,139.349456&query=ramen&client_id=nnn&client_secret=nnn&v=20120101', 
      function (data) { 
       $.each(data.response.venues, function (i, venues) { 
        placesData.addObject(App.Place.create({ id: venues.id, name: venues.name, lat: venues.location.lat, lng: venues.location.lng })); 
       }); 
      }); 

     return placesData; 
    } 
}); 

To wydaje się działać dobrze. I wyświetlić tablicę placesData używając tego szablonu:

<script type="text/x-handlebars" data-template-name="places"> 
    <div> 
     {{#each place in controller}} 
      {{#linkTo 'place' place}} 
       {{place.name}} 
      {{/linkTo}} 
     {{/each}} 
    </div> 

    {{outlet}} 
</script> 

W linkTo linki do poszczególnych miejsce, gdzie chcę pokazać więcej szczegółów na temat tego miejsca. Oto konfiguracja trasa I ciągnąć dane o jednym miejscu, wypełnić jeden obiekt App.Place i powrócić go:

App.PlaceRoute = Ember.Route.extend({ 
    model: function (params) { 
     console.log('place route called'); 

     var place; 
     $.getJSON('https://api.foursquare.com/v2/venues/' + params.place_id + '?client_id=nnn&client_secret=nnn', 
      function (data) { 
       var v = data.response.venue; 
       place = App.Place.create({ id: v.id, name: v.name, lat: v.location.lat, lng: v.location.lng }); 
      }); 

     return place; 
    } 
}); 

Moim problemem jest to, PlaceRoute nie zostanie wywołana, gdy użytkownik kliknie link do to, ale zostanie wywołane, gdy strona zostanie odświeżona na tej trasie.

Według screencastu PeepCode Ember.js (o 12:25 w filmie wideo) stwierdza, że ​​"kontrolery rzadko wykonują połączenia z danymi, obiekty trasy obsługują to", więc myślę, że poprawiam wprowadzanie moje ajax wzywa w trasach (widziałem tak wielu różniących samouczki online, ale ponieważ Peepcode konsultowany z twórcami ember.js, poszłam z nim jako moim podstawowym źródłem uczenia się).

Jeśli nie jest to poprawne, czy można było zrobić lepiej, proszę dać mi znać.

Odpowiedz

48

Ember Dokumentacja na haku modelu „Hak można wdrożyć do konwersji URL do modelu dla tego trasie”

To wyjaśnia, dlaczego hak modelu jest wywoływany po odświeżeniu strony. Ale to dezorientuje wielu ludzi :-). Tak więc nie jest to właściwy haczyk w tym przypadku. Myślę, że powinieneś użyć haczyka setupController dla tego przypadku. Spróbuj tego:

App.PlaceRoute = Ember.Route.extend({ 
    setupController: function (controller, model) { 
     console.log('place route called'); 

     var place; 
     $.getJSON('https://api.foursquare.com/v2/venues/' + model.get('place_id') + '?client_id=nnn&client_secret=nnn', 
      function (data) { 
       var v = data.response.venue; 
       place = App.Place.create({ id: v.id, name: v.name, lat: v.location.lat, lng: v.location.lng }); 
      }); 

     controller.set("model", place); 
    } 
}); 

Dodatkowe 2 centy od siebie: Dlaczego hak Model wykonany tylko, gdy aplikacja jest wprowadzany poprzez URL/bezpośredniej nawigacji przeglądarki?

Ember ma założenie, że nie musisz wykonywać połączenia z hakiem modelu, jeśli używasz {{linkTo}}. W swoim szablonie miejsc używasz {{#linkTo 'place' place}} {{place.name}} {{/linkTo}}. Przejeżdżasz obiekt miejsce do swojej trasy. Ember zakłada, że ​​jest to ten sam obiekt, który otrzymasz podczas wykonywania haka modelu. Tak więc z widoku Embers nie ma potrzeby wywoływania haka modelu. Więc jeśli chcesz wykonać logikę pobierania, nawet jeśli używasz linkTo, użyj setupController hook.

+0

Dzięki za wyjaśnienie, pomaga zrozumieć, jak rzeczy działają. Ma to sens, skoro przechodzę przez to "miejsce", to nie sprawdza modelu na trasie. W "setupController", jak mogę uzyskać identyfikator place_id z adresu URL? – Chaddeus

+1

Ah sry, nie widziałem, że polegałeś na obiekcie params, chociaż szukałem go. Sądzę, że byłoby możliwe uzyskanie dostępu do paramu, ale nie byłbym łatwy. Dlaczego musisz ponownie wykonać połączenie AJAX, mimo że minąłeś to miejsce? Czy w odpowiedzi jest więcej szczegółów? – mavilein

+0

Ostatecznie chcę również zapytać inne API'd, aby zebrać więcej danych o miejscu (np. Zdjęcia na Instagramie). W moim prostym przykładzie, mogłem uciec po prostu mijając to miejsce. Podczas gdy będę budował swój własny interfejs API, aby połączyć ze sobą wszystkie różne wywołania API po stronie serwera, nie chciałbym, aby wszystkie dane przychodzące do aplikacji od razu ... tylko wtedy, gdy dostęp do danego miejsca jest możliwy. Wydaje się, że powinien to być typowy scenariusz. Jeszcze raz dziękuję za pomoc. – Chaddeus

3

podstawie odpowiedzi mavilein, ale krótsze i nadaje się do Ember Ember CLI z danych ...

import Ember from 'ember'; 

export default Ember.Route.extend({ 
    setupController: function(controller, model) { 
    controller.set("model", this.store.fetch('place', model.id)); 
    }, 
}); 

Należy również pamiętać, że pobranie metoda jest dostępna tylko z Ember Danych 1.0.0-beta.12.

http://emberjs.com/api/data/classes/DS.Store.html#method_fetch

14

FYI:

Można użyć haka modelu tego rodzaju rzeczy, po prostu przekazać identyfikator zamiast obiektu:

{{#link-to 'place' place.id}} 
    {{place.name}} 
{{/link-to}} 

Jak Ember nie wie który obiekt jest powiązany z podanym id, Ember jest zmuszony do przeładowania danych (więc Ember wywołuje hook modelu).

+1

Moim zdaniem powinno to być zaakceptowaną odpowiedzią, zaoszczędziło mi godzin bezużytecznych debugowania. Mój przypadek użycia, prawdopodobnie dość powszechny, odwiedza trasę typu '/ groups /: group_id', ale ładuje użytkowników należących do tej grupy jako model trasy, a nie samą grupę. Dzieje się tak dlatego, że mogę stronicować użytkowników bezpośrednio danymi ember, ponieważ stronicowanie wielu dzieci jest obecnie obarczone strachem i niebezpieczeństwem. – omnikron

+0

Ja także uważam, że to powinna być akceptowana odpowiedź, chociaż akceptowana również jest prawidłowa. Po prostu zaakceptowany czuje się bardziej jak obejście, gdy ten rozwiązuje problem w bardziej naturalny sposób. – Ernesto

Powiązane problemy