2012-07-03 13 views
28

Co to jest "właściwa droga" (lub przynajmniej opcje, jeśli nie ma jednego "sposobu Ember") na pasku nawigacyjnym? Czy powinienem jakoś spojrzeć na ContainerViews, czy powinienem po prostu użyć nowej funkcji gniazdka i trzymać nawigację w widoku mojej aplikacji?Właściwy sposób nawigacji z Emberem

Co to jest "właściwa droga" do ustawienia klasy .active na li w zależności od adresu URL (używam routingu)? Czy jest w tym jakiś pomocnik?

Odpowiedz

35

< data Update = „16.01.2013” ​​>

poprzednich przykładach są nieważne od ostatnich zmian w API Router, więc nie zamierzam naprawić te. Wszystkie aplikacje korzystające ze starego routera powinny przeprowadzić migrację jak najszybciej do najnowszej.

Oto zaktualizowane skrzypce: Source | Live Demo

Będę utrzymywać/naprawiać/dodawać funkcje co jakiś czas.

Edit kwi 3rd 2013:

alternatywna Sample - WIP: source | demo

ALL zawartości poniżej jest przestarzała

<Aktualizacja>

2012-Nov-09

Wystarczy dodać link do lepszej próbki, która również zajmuje część której PO chce ustawić klasę w bieżącym elemencie nawigacyjnym po wybraniu danej trasy

Źródło w JSFiddle (Kliknij here, aby zobaczyć, że działa)

Jeśli spojrzysz w NavigationController, zobaczysz "wybraną" właściwość, której używam do sprawdzenia metody isActive widoku podrzędnego NavigationItemView. Funkcja isActive zwróci wartość true lub false na podstawie wartości we właściwości menu tego samego widoku (zdefiniowanej w szablonie) i wartości w właściwości selected (kontrolera). Następnie sprawdź wyrażenia classNameBinding, które albo ustawia 'active', albo nic dla klasy danego dziecka. Sprawdź także ConnectOutlets, w którym zaznaczam ten element nawigacyjny zgodnie z wyborem.

To działa na ember-latest. Używam również trochę z Ember.Bootstrap, a także niektórych z oryginalnych funkcji/klas/etc Twitter Bootstrap (ale zamieniłem style na metro-bootstrap).

Nie wklejać tu wszystkiego z powodu przestrzeni i wszystkiego. Zostawię oryginalny kod i link do tego samego dla odniesienia do oryginalnego pytania/odpowiedzi.

będę aktualizacji tej nowej próbki tylko dlatego Ember jest zabawa =)

</Aktualizacja >

This fiddle pokazuje statyczny navbar z widoku, a wylot jest używany tylko do wyświetlania zawartości, lub możesz przejść bezpośrednio do ekranu, aby uzyskać dostęp do wyświetlania na see it running

Jak widać, może używać prostego widoku zawierającego linki akcji i wyświetlać ten widok w głównym widoku aplikacji. Pod-trasy pod "startem" również mają mini navbar, pochodzący z podobnego szablonu.

Kierownice:

<script type="text/x-handlebars" data-template-name="application"> 
    <h1>My Ember Application</h1> 
    {{view App.NavbarView controllerBinding="controller.controllers.navbarController"}} 
    <br /><hr /> 
    <div class="content"> 
     {{outlet}} 
    </div> 
</script> 

<script type="text/x-handlebars" data-template-name="navbar"> 
    <ul> 
     <li><a href="#" {{action gotoHome}}>Home</a></li> 
     <li><a href="#" {{action gotoStarting}}>Getting Started</a></li> 
     <li><a href="#" {{action gotoCommunity}}>Community</a></li> 
    </ul> 
</script> 

<script type="text/x-handlebars" data-template-name="getting-started-menu"> 
    <ul> 
     <li><a href="#" {{action gotoIndex}}>Overview</a></li> 
     <li><a href="#" {{action gotoMVC}}>About MVC</a></li> 
     <li><a href="#" {{action gotoEmber}}>About Ember</a></li> 
    </ul> 
</script> 

<script type="text/x-handlebars" data-template-name="home"> 
    <h2>Welcome</h2> 
    <br /> 
    <img src="http://emberjs.com/images/about/ember-productivity-sm.png" alt="ember logo" /> 
    <br /> 
    <br /> 
    <p>Bacon ipsum dolor sit amet qui ullamco exercitation, shankle beef sed bacon ground round kielbasa in. Prosciutto pig bresaola, qui meatloaf ea tongue non dolore et pork belly andouille ribeye spare ribs enim. Enim exercitation elit, brisket nisi ex swine in jerky consequat pastrami dolore sed ad. In drumstick cow, salami swine fatback short ribs ham ut in shankle consequat corned beef id. Deserunt prosciutto beef speck. Sirloin incididunt kielbasa excepteur irure.</p> 
    <p>Do beef ribs dolore swine chicken shankle, venison officia qui magna ea anim. Jerky shank shankle, tongue in pork loin commodo boudin elit cupidatat turducken id capicola meatball. Strip steak ham hock tenderloin, id chicken drumstick sint jerky. Dolore veniam cillum minim, pariatur est beef. Sunt fatback tri-tip ex chuck.</p> 
    <br /> 
    <br /> 
    <strong>Note</strong>: This is a basic template with no <i>bindings</i> 
</script> 

<script type="text/x-handlebars" data-template-name="starting"> 
    <h2>Getting Started with Ember</h2> 
    {{view App.StartingMenuView}} 
    <br /> 
    <br /> 
    <br /> 
    <p>Bacon ipsum dolor sit amet qui ullamco exercitation, shankle beef sed bacon ground round kielbasa in. Prosciutto pig bresaola, qui meatloaf ea tongue non dolore et pork belly andouille ribeye spare ribs enim. Enim exercitation elit, brisket nisi ex swine in jerky consequat pastrami dolore sed ad. In drumstick cow, salami swine fatback short ribs ham ut in shankle consequat corned beef id. Deserunt prosciutto beef speck. Sirloin incididunt kielbasa excepteur irure.</p> 
    <p>Do beef ribs dolore swine chicken shankle, venison officia qui magna ea anim. Jerky shank shankle, tongue in pork loin commodo boudin elit cupidatat turducken id capicola meatball. Strip steak ham hock tenderloin, id chicken drumstick sint jerky. Dolore veniam cillum minim, pariatur est beef. Sunt fatback tri-tip ex chuck.</p> 
    <br /> 
    <br /> 
    <strong>Note</strong>: This is a basic template has a menu view embedded 
</script> 

<script type="text/x-handlebars" data-template-name="about-mvc"> 
    <h2>About MVC</h2> 
    {{view App.StartingMenuView}} 
    <br /><br /> 
    <br /><p> 
     Model–View–Controller (MVC) is a software design for interactive computer user interfaces that separates the representation of information from the user's interaction with it.[1][8] The model consists of application data and business rules, and the controller mediates input, converting it to commands for the model or view.[3] A view can be any output representation of data, such as a chart or a diagram. Multiple views of the same data are possible, such as a pie chart for management and a tabular view for accountants. 
    </p> 
    Read more at <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" target="_blank">Wikipedia</a> 
    <br /> 
    <br /> 
    <strong>Note</strong>: This is a basic template has a menu view embedded 
</script> 

<script type="text/x-handlebars" data-template-name="about-ember"> 
    <h2>About Ember</h2> 
    {{view App.StartingMenuView}} 
    <br /><br /> 
    <br /> 
    <p>A framework for creating <strong>ambitious</strong> web applications</p> 
    Read more at <a href="http://emberjs.com/about/" target="_blank">emberjs.com</a> 
    <br /> 
    <br /> 
    <p>Bacon ipsum dolor sit amet qui ullamco exercitation, shankle beef sed bacon ground round kielbasa in. Prosciutto pig bresaola, qui meatloaf ea tongue non dolore et pork belly andouille ribeye spare ribs enim. Enim exercitation elit, brisket nisi ex swine in jerky consequat pastrami dolore sed ad. In drumstick cow, salami swine fatback short ribs ham ut in shankle consequat corned beef id. Deserunt prosciutto beef speck. Sirloin incididunt kielbasa excepteur irure.</p> 
    <p>Do beef ribs dolore swine chicken shankle, venison officia qui magna ea anim. Jerky shank shankle, tongue in pork loin commodo boudin elit cupidatat turducken id capicola meatball. Strip steak ham hock tenderloin, id chicken drumstick sint jerky. Dolore veniam cillum minim, pariatur est beef. Sunt fatback tri-tip ex chuck.</p><br /> 
    <br /> 
    <strong>Note</strong>: This is a basic template has a menu view embedded 
</script> 

<script type="text/x-handlebars" data-template-name="community"> 
    <h1>Ember Community</h1> 
    <p> 
     Get in touch with the community 
    </p> 
    <p>Featured contact info:</p> 
    {{#each item in content}} 
     <a {{bindAttr href="item.linkUrl" }} target="_blank"> 
      <img height="32" width="32" {{bindAttr src="item.imageUrl" title="item.displayName" alt="item.displayName"}} /><br /> 
      {{item.displayName}} 
     </a><br /> 
    {{/each}} 
    <br /> 
    Check more information about ember community at <a href="http://emberjs.com/community/" target="_blank">emberjs.com</a> 
    <br /> 
    <br /> 
    <strong>Note</strong>: This is a template with a <i>foreach</i> type of loop 
</script>​ 

JavaScript:

App = Em.Application.create(); 

App.ApplicationController = Em.Controller.extend(); 
App.ApplicationView = Em.View.extend({ 
    templateName: 'application' 
}); 

App.HomeController = Em.Controller.extend(); 
App.HomeView = Em.View.extend({ 
    templateName: 'home' 
}); 

App.NavbarController = Em.Controller.extend(); 
App.NavbarView = Em.View.extend({ 
    templateName: 'navbar' 
}); 

App.StartingController = Em.Controller.extend(); 
App.StartingView = Em.View.extend({ 
    templateName: 'starting' 
}); 


App.StartingMenuController = Em.Controller.extend(); 
App.StartingMenuView = Em.View.extend({ 
    templateName: 'getting-started-menu' 
}); 

App.AboutMVCController = Em.Controller.extend(); 
App.AboutMVCView = Em.View.extend({ 
    templateName: 'about-mvc' 
}); 

App.AboutEmberController = Em.Controller.extend(); 
App.AboutEmberView = Em.View.extend({ 
    templateName: 'about-ember' 
}); 

App.CommunityModel = Em.Object.extend({ 
    displayName: null, 
    linkUrl: null, 
    imageUrl: null 
}); 

App.CommunityController = Em.ArrayController.extend({ 
    content: [], 
    init: function() { 
     this._super(); 
     this.pushObject(
     App.CommunityModel.create({ 
      displayName: 'Twitter', 
      linkUrl: 'https://twitter.com/#!/emberjs', 
      imageUrl: 'http://icons.iconarchive.com/icons/iconshots/social-media-network/32/twitter-icon.png' 
     })); 
     this.pushObject(
     App.CommunityModel.create({ 
      displayName: 'GitHub', 
      linkUrl: 'https://github.com/emberjs/ember.js', 
      imageUrl: 'http://www.workinprogress.ca/wp-content/uploads/github.png' 
     })); 
    } 
}); 

App.CommunityView = Em.View.extend({ 
    templateName: 'community', 
    contentBinding: 'App.CommunityController.content' 
}); 

App.Router = Em.Router.extend({ 
    enableLogging: true, 
    location: 'hash', 

    root: Em.Route.extend({ 
     // EVENTS 
     gotoHome: Ember.Route.transitionTo('home'), 
     gotoStarting: Ember.Route.transitionTo('starting.index'), 
     gotoCommunity: Ember.Route.transitionTo('community.index'), 

     // STATES 
     home: Em.Route.extend({ 
      route: '/', 
      connectOutlets: function(router, context) { 
       router.get('applicationController').connectOutlet('home'); 
      } 
     }), 
     starting: Em.Route.extend({ 
      // SETUP 
      route: '/starting', 
      connectOutlets: function(router, context) { 
       router.get('applicationController').connectOutlet('starting'); 
      }, 
      // EVENTS 
      gotoMVC: Ember.Route.transitionTo('mvc'), 
      gotoEmber: Ember.Route.transitionTo('ember'), 
      gotoIndex: Ember.Route.transitionTo('index'), 

      // STATES 
      index: Em.Route.extend({ 
       route: '/', 
       connectOutlets: function(router, context) { 
        router.get('applicationController').connectOutlet('starting'); 
       } 
      }), 
      mvc: Em.Route.extend({ 
       route: '/mvc', 
       connectOutlets: function(router, context) { 
        router.get('applicationController').connectOutlet('aboutMVC'); 
       } 
      }), 
      ember: Em.Route.extend({ 
       route: '/ember', 
       connectOutlets: function(router, context) { 
        router.get('applicationController').connectOutlet('aboutEmber'); 
       } 
      }) 
     }), 
     community: Em.Route.extend({ 
      // SETUP 
      route: '/community', 
      connectOutlets: function(router, context) { 
       router.get('applicationController').connectOutlet('community'); 
      }, 
      // EVENTS 
      // STATES 
      index: Em.Route.extend({ 
       route: '/', 
       connectOutlets: function(router, context) { 
        router.get('applicationController').connectOutlet('community'); 
       } 
      }) 
     }) 
    }) 
}); 
App.initialize();​ 
+6

Wielki, znacznie bardziej szybciej niż ja. IMHO ten przykład powinien być częścią przykładów przykładów witryn ember. –

+1

Napisałem próbkę, więc już miałem kilka szablonów. Mógłbym zmodyfikować skrzypce później, aby adresować część klasy CSS tho – MilkyWayJoe

+4

Cudownie, dziękuję! Zgadzam się, że powinno to być na stronie Ember. Zauważyłem, że dokumentacja Ember jest całkiem uboga - zajęło to trochę czasu, aby to wszystko połączyć. Dokumentacja na stronie pozostawiła mi wiele pytań, głównie o tym, jak połączyć wszystko dla rzeczywistej aplikacji, a nie tylko jednego widoku. Podczas gdy Rails, którego nauczyłem się w ciągu 1 dnia, screencasty były WIELKIM punktem wyjścia. Chciałbym, żeby Ember miał coś takiego. – user1499207

8

mi się nie podoba odpowiedź MilkyWayJoe ponieważ jeśli prędzej czy później chcą zmienić nazewnictwo swoich stanów czy cokolwiek musicie przejść przez kod I widok, także dodając funkcję do przejścia. Każda trasa wydaje się niepożądana. Moje podejście jest nieco bardziej programowy i modularny:

# Parent View-Tamplate, holding the navbar DOM elements 
App.NavView = Ember.View.extend( 
    controller: App.NavArrayController 
    templateName: "ember-nav" 
) 
# We push NavItems into this array 
App.NavArrayController = Ember.ArrayController.create(
    content: Ember.A([]) 
) 
# NavItem has two settable properties and 
# an programmatic active state depending on the router 
App.NavItem = Ember.Object.extend(
    title: '' 
    goto: null # <=this is the name of the state we want to go to! 
    active: (-> 
    if App.router.currentState.name == @.get "goto" 
     true 
    else 
     false 
).property('App.router.currentState.name').cacheable() 
) 
# the actual NavElement which gets the class="active" if the 
# property "active" is true, plus a on-click binding to 
# make the Router transition to this state 
App.NavItemView = Ember.View.extend(
tagName: "li" 
    classNameBindings: ["active"] 
    click: -> 
    App.router.transitionTo(@get('goto')) 
    false 
) 

nav-view.hbs (dla navs twitter-bootstrap stylu)

<div class="nav-collapse collapse"> 
    <ul class="nav"> 
    {{#each App.NavArrayController}} 
     {{#view App.NavItemView classBinding="active" gotoBinding="goto"}} 
     <a href="#" {{bindAttr data-goto="goto"}}> {{title}}</a> 
     {{/view}} 
    {{/each}} 
    </ul> 
</div> 

ten sposób, mogę tylko tworzyć i poeksperymentować z moje trasy w routerze, i utrzymać Nav-Definicje side-by-side:

# put this somewhere close to the Router 
App.NavArrayController.pushObjects(
    [ 
    App.NavItem.create(
     title: 'Home' 
     goto: 'home' 
    ), 
    App.NavItem.create(
     title: 'Chat' 
     goto: 'chat' 
    ), 
    App.NavItem.create(
     title: 'Test' 
     goto: 'test' 
    ) 
    ] 
) 
+0

Plus ma tę zaletę, że linki są w rzeczywistości linkami, a nie działaniami - więc mają działanie href i przeglądarki, takie jak "Otwórz w nowej karcie" itp., Będą działały. – Ginty

+1

tylko jeśli ustawisz 'a href =" # "' na 'href ="/#/{{uncbound goto}} "' – Thomas

+1

Zgadzam się z Wami. Próbowałem rozwiązać ten problem w zaktualizowanej wersji kodu, ale nie do końca tam, gdzie chciałem. Teraz, gdy nowy router się uruchomi, zaktualizuję (w pewnym momencie) to, aby lepiej dostosować twoje podejście do tej implementacji. Moją wymówką jest to, że piszę to tak, jak się uczyłem, więc było to doświadczenie odkrywania: P – MilkyWayJoe

Powiązane problemy