Reputation: 734
I have this problem, the level two not appear in the dropdown
index. html
<!DOCTYPE html>
<html>
<head>
<title>angular2 playground</title>
<link rel="stylesheet" href="style.css" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.17/angular2-polyfills.js"></script>
<script src="https://code.angularjs.org/tools/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
$(function(){
$(".dropdown-menu > li > a.trigger").on("click",function(e){
var current=$(this).next();
var grandparent=$(this).parent().parent();
if($(this).hasClass('left-caret')||$(this).hasClass('right-caret'))
$(this).toggleClass('right-caret left-caret');
grandparent.find('.left-caret').not(this).toggleClass('right-caret left-caret');
grandparent.find(".sub-menu:visible").not(current).hide();
current.toggle();
e.stopPropagation();
});
$(".dropdown-menu > li > a:not(.trigger)").on("click",function(){
var root=$(this).closest('.dropdown');
root.find('.left-caret').toggleClass('right-caret left-caret');
root.find('.sub-menu:visible').hide();
});
});
</script>
</head>
<body>
<my-app>
</my-app>
</body>
</html>
---------------------------------------------------------------------
app.ts
//our root app component
import {Component} from '@angular/core'
@Component({
selector: 'my-app',
providers: [],
template: `
<div class="dropdown" style="position:relative">
<a href="#" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">Click Here <span class="caret"></span></a>
<ul class="dropdown-menu">
<li>
<a class="trigger right-caret">Level 1 the other level dont enter</a>
<ul class="dropdown-menu sub-menu">
<li><a href="#">Level 2</a></li>
<li>
<a class="trigger right-caret">Level 2</a>
<ul class="dropdown-menu sub-menu">
<li><a href="#">Level 3</a></li>
<li><a href="#">Level 3</a></li>
<li>
<a class="trigger right-caret">Level 3</a>
<ul class="dropdown-menu sub-menu">
<li><a href="#">Level 4</a></li>
<li><a href="#">Level 4</a></li>
<li><a href="#">Level 4</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">Level 2</a></li>
</ul>
</li>
<li><a href="#">Level 1</a></li>
<li><a href="#">Level 1</a></li>
</ul>
</div>
`,
directives: []
})
export class App {
constructor() {
this.name = 'Angular2 (Release Candidate!)'
}
}
main.ts
//main entry point
import {bootstrap} from '@angular/platform-browser-dynamic';
import {App} from './app';
bootstrap(App, [])
.catch(err => console.error(err));
https://plnkr.co/edit/9LVuek8bQ7mNgoqaC5Y6?p=preview
the dropdown work fine, but if I add the code to a component of angular in a template when the html is rendering and you navigate for the dropdown don't show the level 2.
Upvotes: 1
Views: 4904
Reputation: 878
Why don't you just plug in smartmenu(http://www.smartmenus.org), very simply, after everything finished
ngAfterViewChecked() {
$('#main-menu').smartmenus();
}
It is mobile/tablet/ipad friendly and cope with most browser
http://plnkr.co/edit/wLqLUoBQYgcDwOgSoRfF?p=preview
Check my code here: https://github.com/Longfld/DynamicaLoadMultiLevelDropDownMenu
Upvotes: 1
Reputation: 214195
I see several way to do that:
1) Use event delegation:
$(document).on("click", ".dropdown-menu > li > a.trigger", function(e){
See plunker example here https://plnkr.co/edit/O6pfV7mrLWiGZ2KHwqh8?p=preview
2) Init event handlers after angular2 view has been rendered
export class App {
ngAfterViewInit() {
this.initMenu();
}
initMenu() {
$(".dropdown-menu > li > a.trigger").on("click",function(e){
var current=$(this).next();
...
See plunker example here https://plnkr.co/edit/2DRVOGhcIMkTgQHTM57d?p=preview
3) Use angular2 approach instead jQuery manipulation:
root component
import {Component} from '@angular/core'
import {MenuItem} from './menu-item.component';
@Component({
selector: 'my-app',
template: `
<div class="dropdown" style="position:relative">
<a href="#" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">Click Here <span class="caret"></span></a>
<ul class="dropdown-menu">
<li class="menu-item" *ngFor="let menuItem of menu" [data]="menuItem"></li>
</ul>
</div>
`,
directives: [MenuItem]
})
export class App {
menu = [
{
title: 'Level 1 the other level dont enter'
items: [
{
title: 'Level 2'
},
{
title: 'Level 2',
items: [
{
title: 'Level 3'
},
{
title: 'Level 3'
},
{
title: 'Level 3',
items: [
{
title: 'Level 4'
},
{
title: 'Level 4'
},
{
title: 'Level 4'
}
]
}
]
},
{
title: 'Level 2'
}
]
},
{
title: 'Level 1'
},
{
title: 'Level 1'
}
];
}
menu-item component
import {Component, Input, forwardRef, ViewChildren} from '@angular/core'
interface MenuItem {
title: string;
items: Array<MenuItem>
}
@Component({
selector: 'li.menu-item',
styles: [`
.block {
display: block;
}
`],
template: `
<a [ngClass]="{'right-caret': !!data.items && !opened, 'left-caret': !!data.items && opened}" (click)="onClick($event)">{{data.title}}</a>
<template [ngIf]="!!data.items">
<ul class="dropdown-menu sub-menu" [ngClass]="{'block': opened}">
<li class="menu-item" *ngFor="let menuItem of data.items" [data]="menuItem">
</li>
</ul>
</template>
`,
directives: [forwardRef(()=> MenuItem)]
})
export class MenuItem {
@Input() data: MenuItem;
@ViewChildren(MenuItem) children:QueryList<MenuItem>;
private _opened: boolean = false;
get opened() {
return this._opened;
};
set opened(val) {
this._opened = val;
if(!val) {
this.children.toArray().forEach(x => x.opened = false)
}
}
onClick(e){
this.opened = !this.opened;
if(this.data.items) {
e.stopPropagation();
}
}
}
Here is the link to working example plunker code
Upvotes: 4