mike-north / ember-material-lite

Material Design Lite for Ember.js Apps
http://mike.works/ember-material-lite
MIT License
148 stars 51 forks source link

Passing model for dynamic segment to {{mdl-nav-item}} #62

Open micahjon opened 9 years ago

micahjon commented 9 years ago

I was unable to pass the model for a dynamic segment to the {{mdl-nav-item}} component. This is b/c the mdl-nav template passes a route name to the {{link-to}} but no model parameter, which is essential for dynamic routing (e.g. users/:id).

{{link-to navItem.name navItem.route class='mdl-navigation__link'}}

I thought I could pass a string containing both the route name and the model, but was not able to get that to work:

{{mdl-nav-item name="Announcements by Date" action='announcements.day currentDay'}}

A fix would be wonderful. Thanks again for making all of these changes so fast!

micahjon commented 9 years ago

On second thought, instead of adding additional complexity to {{mdl-nav-item}}, it would be helpful if this component was simply a wrapper (block form) and yielded whatever template was passed to it.

Typically, it would wrap a {{link-to}}: {{mdl-nav-item}}{{link-to ..}}{{/mdl-nav-item}}

but it could also wrap a custom template, such as an image of the current user {{mdl-nav-item}}{{current-user-nav-item image="imageUrl" action="logout"}}{{/mdl-nav-item}}

I'm guessing this would also be more maintainable, as there would be no need for {{mdl-nav-item}} to be refactored every time {{link-to}} is.

kennethkalmer commented 9 years ago

:+1: from my side on the block form, I've just started migrating from ember-paper and immediately hit this wall. Block form would be way more useful since not everything is a route (looking at you ember-simple-auth)...

mike-north commented 9 years ago

the nav stuff is a little tricky, and I want to make sure we end up with the right pattern before too many people start using it.

It's the only area of MDL that is not currently supported in an ember-ish way (I'm referring to the more complex flavors of multi-row navs here). Either of you guys willing to get on a google hangout and help plan out a sensible solution for the {{mdl-nav-* stuff? Even if you can just describe use cases, that would be helpful

kennethkalmer commented 9 years ago

@mike-north I'd love to, we'd just need to orchestrate timezones (I'm GMT+2).

In the meantime, here is an example from my manually built up markup to support login/logout with ember-simple-auth:

<nav class="mdl-navigation">
  {{#if session.isAuthenticated}}
    <a class="mdl-navigation__link" href="/logout" {{action 'invalidateSession'}}>Logout</a>
  {{else}}
    <a class="mdl-navigation__link" href="/login" {{action 'authenticateSession'}}>Login</a>
    {{#link-to 'register' class='mdl-navigation__link'}}Register{{/link-to}}
  {{/if}}
</nav>

Ideally I would have liked to do something like this:

{{#if session.isAuthenticated}}
  {{mdl-nav-item name='Logout' action='logout'}}
{{else}}
  {{mdl-nav-item name='Login' action='login'}}
  {{mdl-nav-item name='Register' route='register'}}
{{/if}}

I also imagine that the block form could be useful for adding icons or badges to the navigation:

{{#mdl-nav-item}}
  {{#link-to 'inbox'}}
    {{mdl-icon badge=unreadCount icon='inbox'}}
  {{/link-to}}
{{/mdl-nav-item}}

I think the block syntax will also help @pranksinatra's case.

micahjon commented 9 years ago

Great, I'd be happy to talk sometime (eastern time, GMT-5).

Getting navigation right is super important, and I'd err on the side of flexibility in this case. Some key features:

  1. Simple text links with full support for {{link-to}} and {{action}} parameters
  2. Custom components (e.g. search bar, user avatar w/ account options dropdown menu)
  3. Ability to choose whether each of these show up in the desktop menu, the mobile menu, or both (default).

Other potential tweaks:

  1. Allow users to use image (e.g. logo) instead of text for title.
  2. Add component for drop-down menus.

I think the difficulty here is building a component with the flexibility to render up to four custom templates (title, desktop links, mobile links, page content) but also provide simple defaults (as it does currently). I'll give this some more thought.

micahjon commented 9 years ago

I've done some exploring and stumbled across a pattern for named yields: http://stackoverflow.com/questions/20981068/ember-component-block-form-more-than-one-outlet-yield#30107261

Here's a working implementation: application.hbs template

{{#mdl-nav fixedHeader=true as |section|}}

  {{#if (eq section "title")}}
    <img src="mylogo.png" alt="Goshen College">

  {{else if (eq section "mobileTitle")}}
    Goshen College

  {{else if (eq section "headerNavItems")}}
    {{#link-to 'announcements' class='mdl-navigation__link'}}My Announcements{{/link-to}}
    {{#link-to 'announcements.new' class='mdl-navigation__link'}}New Announcement{{/link-to}}
    <a {{action "login"}} class="mdl-navigation__link">Login</a>
    {{input type="search" placeholder="Search..." value=search}}

  {{else if (eq section "drawerNavItems")}}
    {{input type="search" placeholder="Search..." value=search}}
    <a {{action "login"}} class="mdl-navigation__link">Login</a>
    {{#link-to 'announcements' class='mdl-navigation__link'}}My Announcements{{/link-to}}
    {{#link-to 'announcements.mobileonly' class='mdl-navigation__link'}}Custom Link{{/link-to}}

  {{else if (eq section "body")}}
    {{outlet}}

  {{/if}}
{{/mdl-nav}}

Then we'd yield named templates into mdl-nav.hbs, instead of looping through {{mdl-nav-item}} child components:

{{#if includeHeader}}
<header class={{_headerClassString}}>
  <div class="mdl-layout__header-row">
    <span class="mdl-layout-title">
      {{#if title}}{{title}}{{else}}{{yield "title"}}{{/if}}
    </span>
    <div class="mdl-layout-spacer"></div>
    {{#if includeHeaderLinks}}
    <nav class="mdl-navigation mdl-layout--large-screen-only">
      {{yield "headerNavItems"}}
    </nav>
    {{/if}}
  </div>
</header>
{{/if}}
{{#if includeDrawer}}
<div class="mdl-layout__drawer">
  {{#if includeDrawerTitle}}
  <span class="mdl-layout-title">
    {{#if mobileTitle}}{{mobileTitle}}{{else}}{{yield "mobileTitle"}}{{/if}}
  </span>
  {{/if}}
  <nav class="mdl-navigation">
    {{yield "drawerNavItems"}}
  </nav>
</div>
{{/if}}
<main class="mdl-layout__content">
  <div class="page-content">
    {{yield "body"}}
  </div>
</main>

This would provide all the flexibility we'd need with the following drawbacks:

@mike-north, @kennethkalmer what do you think?

leoeuclids commented 9 years ago

I would like to share my use case, since i made a few changes to mdl-nav in order make it work the way i needed.

After creating header, drawer and content components, the dummy app application.hbs looks like this:

{{#mdl-nav fixedDrawer=true fixedHeader=true}}
  {{#mdl-nav-header}}
    <span class="mdl-layout-title">Ember Material Design Lite</span>
    <div class="mdl-layout-spacer"></div>
    <nav class="mdl-navigation mdl-layout--large-screen-only">
      {{link-to "Badges" "badges" class='mdl-navigation__link'}}
      {{link-to "Buttons" "buttons" class='mdl-navigation__link'}}
      <!-- links... -->
      <a class='mdl-navigation__link github-link' href='https://github.com/truenorth/ember-material-lite' target='_blank'>
        <i class="material-icons">code</i>
        GitHub
      </a>
    </nav>
  {{/mdl-nav-header}}

  {{#mdl-nav-drawer}}
    <nav class="mdl-navigation mdl-color--white">
      {{link-to "Badges" "badges" class='mdl-navigation__link'}}
      {{link-to "Buttons" "buttons" class='mdl-navigation__link'}}
      <!-- links... -->
      <a class='mdl-navigation__link github-link drawer' href='https://github.com/truenorth/ember-material-lite' target='_blank'>
        <i class="material-icons">code</i>
        GitHub
      </a>
    </nav>
  {{/mdl-nav-drawer}}

  {{#mdl-nav-content}}
    {{ outlet }}
  {{/mdl-nav-content}}
{{/mdl-nav}}

I'm not really sure about the drawbacks here, but i think they are the same @pranksinatra pointed out.