<!DOCTYPE html>
<html>

  <head>
    <base href="." />
    <title>angular playground</title>
    <link rel="stylesheet" href="style.css" />
    <link href="https://unpkg.com/@angular/material/prebuilt-themes/indigo-pink.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <style>body { font-family: Roboto, Arial, sans-serif; }</style>
    <script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script>
    <script src="https://unpkg.com/zone.js/dist/zone.js"></script>
    <script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script>
    <script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
    <script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
    <script src="config.js"></script>
    <script>
    System.import('app')
      .catch(console.error.bind(console));
  </script>
  </head>

  <body>
    <my-app>
    loading...
  </my-app>
  </body>

</html>
/* Styles go here */

body {
  background: #f1f1f1;
  margin: 0;
}

.title {
  color: #fff;
  margin-right: 15px;
}
.toolbar.mat-toolbar.mat-primary {
  background: #334658;
  box-shadow: 0 2px 5px 0 rgba(0,0,0,0.24);
}

.toolbar .mat-button-focus-overlay {
  background: rgba(255,255,255,.12);
}
.example-card {
  margin: 20px 20%;
}

.example-card .mat-card-content {
  font-size: 16px;
}
/* Menu styles */

.sub-menu {
  margin-top: -48px;
}

.sub-menu.mat-menu-panel.mat-menu-before.mat-menu-below {
  transform-origin: left top !important;
}

.custom-menu.mat-menu-panel {
  min-width: 180px;
}
top-menu [md-button] {
  z-index: 1001;
  line-height: 64px;
  color: #fff;
}


[md-menu-item].mat-menu-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
[md-menu-item].mat-menu-item span:first-child {
  margin-right: 15px;
}
[md-menu-item].mat-menu-item .mat-icon {
  margin-right: 0;
}

.mat-divider {
  border-top: 1px solid rgba(0,0,0,.12);
  margin: 0;
}


.cdk-overlay-backdrop {
  display: block;
}

.cdk-overlay-backdrop ~ .cdk-overlay-backdrop {
  display: none;
}

/* End Menu styles */
### Angular Starter Plunker - Typescript
var materialVersion = '@2.0.0-beta.11';

System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  paths: {
    'npm:': 'https://unpkg.com/'
  },
  //map tells the System loader where to look for things
  map: {
    
    'app': './src',
    
    '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
    '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
    '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
    '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
    '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
    '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
    '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
    '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
    '@angular/animations': 'npm:@angular/animations/bundles/animations.umd.js',
    '@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.js',
    '@angular/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.js',
    
    '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
    '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
    '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
    '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
    '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
    '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
    
    '@angular/cdk': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk.umd.js',
    '@angular/cdk/a11y': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-a11y.umd.js',
    '@angular/cdk/bidi': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-bidi.umd.js',
    '@angular/cdk/coercion': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-coercion.umd.js',
    '@angular/cdk/collections': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-collections.umd.js',
    '@angular/cdk/keycodes': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-keycodes.umd.js',
    '@angular/cdk/observers': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-observers.umd.js',
    '@angular/cdk/overlay': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-overlay.umd.js',
    '@angular/cdk/platform': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-platform.umd.js',
    '@angular/cdk/portal': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-portal.umd.js',
    '@angular/cdk/rxjs': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-rxjs.umd.js',
    '@angular/cdk/scrolling': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-scrolling.umd.js',
    '@angular/cdk/table': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-table.umd.js',
    '@angular/material': 'npm:@angular/material@2.0.0-beta.11/bundles/material.umd.js',
    '@angular/cdk/stepper': 'https://unpkg.com/@angular/cdk' + materialVersion + '/bundles/cdk-stepper.umd.js',
    'rxjs': 'npm:rxjs',
    'typescript': 'npm:typescript@2.2.1/lib/typescript.js'
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    },
    rxjs: {
      defaultExtension: 'js'
    }
  }
});
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app';

platformBrowserDynamic().bootstrapModule(AppModule)
//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

import { MdButtonModule, MdCardModule, MdIconModule, MdMenuModule, MdToolbarModule } from '@angular/material';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { TopMenuComponent } from './top-menu.component';

@Component({
  selector: 'my-app',
  templateUrl: 'src/app.html',
})
export class App {
    menuItems = [
    {
      text: 'File',
      items: [
        {
          text: 'Share'
        },
        {
          text: 'New',
          icon: 'arrow_right',
          items: [
            {
              text: 'Document'
            },
            {
              text: 'New',
              icon: 'arrow_right',
              items: [
                {
                  text: 'New',
                  icon: 'arrow_right',
                  items: [
                    {
                      text: 'Document'
                    },
                    {
                      text: 'Spreadsheet'
                    }
                  ]
                },
                {
                  text: 'Document',
                  icon: 'arrow_right',
                  items: [
                    {
                      text: 'Document 1'
                    },
                    {
                      text: 'Document 2'
                    }
                  ]
                }
              ]
            },
            {
              text: 'Spreadsheet'
            },
            {
              text: 'Presentation',
              icon: 'arrow_right',
              items: [
                {
                  text: 'New',
                  icon: 'arrow_right',
                  items: [
                    {
                      text: 'Document'
                    },
                    {
                      text: 'Spreadsheet'
                    }
                  ]
                }
              ]
            },
            {
              text: 'Form'
            }
          ]
        },
        {
          divider: true
        },
        {
          text: 'Open',
          extraText: 'Ctrl+O'
        },
        {
          text: 'Rename',
          disabled: true
        },
        {
          divider: true
        },
        {
          text: 'Print',
          extraText: 'Ctrl+P'
        }
      ]
    },
    {
      text: 'Edit',
      items: [
        {
          text: 'Undo',
          extraText: 'Ctrl+Z'
        },
        {
          text: 'Redo',
          extraText: 'Ctrl+Y'
        },
        {
          divider: true
        },
        {
          text: 'Cut',
          extraText: 'Ctrl+X'
        },
        {
          text: 'Copy',
          extraText: 'Ctrl+C'
        },
        {
          text: 'Paste',
          extraText: 'Ctrl+P'
        },
        {
          divider: true
        },
        {
          text: 'Find and replace...',
          extraText: 'Ctrl+Shift+H'
        }
      ]
    },
    {
      text: 'View',
      items: [
        {
          text: 'Print layout'
        },
        {
          text: 'Mode',
          icon: 'arrow_right',
          items: [
            {
              text: 'Presentation'
            },
            {
              text: 'Edit'
            },
            {
              text: 'Modifiable'
            }
          ]
        },
        {
          divider: true
        },
        {
          text: 'Show ruler'
        },
        {
          text: 'Show equation toolbar'
        },
        {
          text: 'Show spelling suggestions'
        },
        {
          divider: true
        },
        {
          text: 'Compact controls'
        },
        {
          text: 'Full screen'
        },
      ]
    },
    {
      text: 'Format',
      items: [
        {
          text: 'Bold',
          extraText: 'Ctrl+B'
        },
        {
          text: 'Italic',
          extraText: 'Ctrl+I'
        },
        {
          text: 'Underline',
          extraText: 'Ctrl+U'
        },
        {
          text: 'Strikethrough',
          extraText: 'Alt+Shift+5'
        },
        {
          text: 'Superscript',
          extraText: 'Ctrl+.'
        },
        {
          text: 'Subscript',
          extraText: 'Ctrl+,'
        },
        {
          divider: true
        },
        {
          text: 'Clear Formatting'
        },
      ]
    }
  ];
}

@NgModule({
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    MdToolbarModule,
    MdMenuModule,
    MdButtonModule,
    MdIconModule,
    MdCardModule
  ],
  declarations: [ App, TopMenuComponent],
  bootstrap:    [ App ]
})
export class AppModule { }
import { Component, Input, QueryList, ViewChildren } from '@angular/core';
import { ConnectedPositionStrategy, MdMenuTrigger } from '@angular/material';

let originWithFallbackPosition = ConnectedPositionStrategy.prototype.withFallbackPosition;
ConnectedPositionStrategy.prototype.withFallbackPosition = function (originPos, overlayPos) {
  overlayPos.overlayX = 'start';
  if(this._preferredPositions.length) {
    return this;
  }
  return originWithFallbackPosition.apply(this, arguments);
};

@Component({
    selector: 'top-menu',
    templateUrl: 'src/top-menu.component.html'
})
export class TopMenuComponent {
  @Input() items: any[];

  @ViewChildren(MdMenuTrigger) triggers: QueryList<MdMenuTrigger>;

  openMenu(trigger: MdMenuTrigger, level: number) {
    this.triggers
      .filter((x: any) => x._element.nativeElement.dataset.level >= level && x !== trigger)
      .forEach(x => x.closeMenu());
    trigger.openMenu();
  }

  closeMenu() {
    this.triggers.forEach(x => x.closeMenu());
  }
}
<ng-container *ngFor="let item of items">
  <button md-button [mdMenuTriggerFor]="menu" #trigger="mdMenuTrigger" [attr.data-level]="1" (mouseenter)="openMenu(trigger, 1)">
    {{item.text}}
  </button>
  <md-menu class="custom-menu" #menu="mdMenu" [overlapTrigger]="false" (close)="closeMenu()" xPosition="after">
    <ng-container *ngTemplateOutlet="subMenu; context: { $implicit: item.items, level: 2 }"></ng-container>
  </md-menu>
</ng-container>

<ng-template #subMenu let-items let-level="level">
  <ng-container *ngFor="let item of items">
    <ng-container *ngIf="item.items && item.items.length else simpleTmpl">
      <button *ngIf="!item.divider" md-menu-item [disabled]="item.disabled"
              [mdMenuTriggerFor]="menu"
              #trigger="mdMenuTrigger"
              [attr.data-level]="level"
              (mouseenter)="openMenu(trigger, level);" (click)="$event.stopPropagation()">
        <span>{{item.text}}</span>
        <span *ngIf="item.extraText">{{item.extraText}}</span>
        <md-icon *ngIf="item.icon">{{item.icon}}</md-icon>
      </button>
      <md-menu class="sub-menu" #menu="mdMenu" [overlapTrigger]="false" xPosition="before" >
        <ng-container *ngTemplateOutlet="subMenu; context: { $implicit: item.items || [], level: level + 1 }"></ng-container>
      </md-menu>
      <md-divider *ngIf="item.divider" class="mat-divider"></md-divider>
    </ng-container>
    <ng-template #simpleTmpl>
      <button *ngIf="!item.divider" md-menu-item [disabled]="item.disabled" (click)="closeMenu()">
        <span>{{item.text}}</span>
        <span *ngIf="item.extraText">{{item.extraText}}</span>
      </button>
      <md-divider *ngIf="item.divider" class="mat-divider"></md-divider>
    </ng-template>
  </ng-container>
</ng-template>


<md-toolbar color="primary" class="toolbar">
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="80" viewBox="0, 0, 500, 500">
      <g>
        <path d="M250.696,82 L91,138.2 L116.235,347.426 L250.864,421.421 L386.186,346.424 L411.413,137.205 L250.696,82" fill="#FFFFFF"/>
        <path d="M395.484,149.298 L250.323,99.795 L250.323,403.742 L371.974,336.416 L395.484,149.298" fill="#CA403A"/>
        <path d="M108.92,150.189 L130.544,337.309 L250.32,403.742 L250.32,99.789 L108.92,150.189" fill="#E15855"/>
        <path d="M286.417,252.193 L250.587,181.26 L221.196,250.973 L250.32,250.973 L286.417,252.193 M290.28,261.601 L250.323,280.287 L208.207,280.287 L188.41,329.804 L151.585,330.486 L250.323,110.832 L290.28,261.601 z" fill="#FFFFFF"/>
        <path d="M250.32,110.832 L250.585,181.26 L283.934,251.027 L250.395,251.027 L250.32,280.243 L296.695,280.287 L318.372,330.492 L353.603,331.146 L250.32,110.832" fill="#FFFFFF"/>
      </g>
  </svg>
  <h3 class="title">Ng2 Menu</h3>

  <top-menu [items]="menuItems"></top-menu>
  <span class="fill-remaining-space"></span>
</md-toolbar>

<md-card class="example-card">
  <md-card-content>
    <h2>What is an example of a material design angular2/4 menu with nested dropdown options like angular1?</h2>
    <p>
      I really want to incorporate angular2 material, noticed the following menu example:
    </p>
    <p>
      https://material.angularjs.org/1.1.4/demo/menuBar
    </p>
    <p>This is a beauty: http://codepen.io/anon/pen/zrdQwP</p>
    <p>I like how you can have nested menus, but for the Angular 2/4 demo, all you see is this:</p>
    <p>https://material.angular.io/components/component/menu</p>
    <p>
      There is no example with nested menus! Is this possible with Angular2 + Material?
      If so, can someone demonstrate how to use this? Or is this just not possible?
      Seems fishy if Angular 2/4 can't support this while Angular 1.x can...
    </p>
  </md-card-content>
</md-card>