<!DOCTYPE html>
<html>
<head>
<base href="." />
<title>angular2 playground</title>
<link rel="stylesheet" href="style.css" />
<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>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/css/bootstrap.min.css" integrity="sha384-2hfp1SzUoho7/TsGGGDaFdsuuDL0LX2hnUp6VkX3CUQ2K4K+xjboZdsXyp4oUHZj" crossorigin="anonymous">
</head>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
/* Styles go here */
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/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',
'@ng-bootstrap/ng-bootstrap': 'npm:@ng-bootstrap/ng-bootstrap',
'rxjs': 'npm:rxjs',
'typescript': 'npm:typescript@2.0.2/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} from '@angular/core'
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser'
import { NgbDropdownModule } from './dropdown.module';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
@Component({
selector: 'my-app',
template: `
<table>
<tr *ngFor="let number of numbers">
<td>{{number}}</td>
<td>
<div ngbDropdown class="d-inline-block">
<button class="btn btn-outline-primary" id="{{number}}" ngbDropdownToggle>...</button>
<div class="dropdown-menu">
<button class="dropdown-item">Action - 1</button>
<button class="dropdown-item">Another Action</button>
<button class="dropdown-item">Something else is here</button>
</div>
</div>
</table>
`
})
export class App {
numbers: Array
constructor(){
this.numbers = Array(1).fill().map((x,i)=>i);
}
}
@NgModule({
imports: [BrowserModule, CommonModule, FormsModule, NgbDropdownModule.forRoot()],
declarations: [App],
bootstrap: [App]
})
export class AppModule {}
import {Directive, Input, Output, EventEmitter, ElementRef, OnDestroy, Renderer} from '@angular/core';
import {NgbDropdownConfig} from './dropdown-config';
/**
* Transforms a node into a dropdown.
*/
@Directive({
selector: '[ngbDropdown]',
exportAs: 'ngbDropdown',
host: {
'[class.dropdown]': '!up',
'[class.dropup]': 'up',
'[class.open]': 'isOpen()',
'(keyup.esc)': 'closeFromOutsideEsc()',
//'(document:click)': 'closeFromOutsideClick($event)'
}
})
export class NgbDropdown implements OnDestroy {
private _toggleElement: any;
// globalListenFunc will hold the function returned by "renderer.listenGlobal"
private outsideClickListener: Function;
/**
* Indicates that the dropdown should open upwards
*/
@Input() up: boolean;
/**
* Indicates that dropdown should be closed when selecting one of dropdown items (click) or pressing ESC.
*/
@Input() autoClose: boolean;
/**
* Defines whether or not the dropdown-menu is open initially.
*/
@Input('open') private _open = false;
/**
* An event fired when the dropdown is opened or closed.
* Event's payload equals whether dropdown is open.
*/
@Output() openChange = new EventEmitter();
constructor(config: NgbDropdownConfig, private renderer: Renderer, private elementRef: ElementRef) {
this.up = config.up;
this.autoClose = config.autoClose;
this.renderer = renderer;
}
ngOnDestroy() {
}
/**
* Checks if the dropdown menu is open or not.
*/
isOpen(): boolean { return this._open; }
/**
* Opens the dropdown menu of a given navbar or tabbed navigation.
*/
open(): void {
if (!this._open) {
this._open = true;
this.openChange.emit(true);
// We cache the function "listenGlobal" returns
this.outsideClickListener = this.renderer.listen(this.elementRef.nativeElement, 'document:click', (event) =>
this.closeFromOutsideClick(event)
);
}
}
/**
* Closes the dropdown menu of a given navbar or tabbed navigation.
*/
close(): void {
if (this._open) {
this._open = false;
this.openChange.emit(false);
console.log('suppression listener');
this.outsideClickListener();
}
}
/**
* Toggles the dropdown menu of a given navbar or tabbed navigation.
*/
toggle(): void {
if (this.isOpen()) {
this.close();
} else {
this.open();
}
}
closeFromOutsideClick($event) {
if (this.autoClose && !this._isEventFromToggle($event)) {
this.close();
}
}
closeFromOutsideEsc() {
if (this.autoClose) {
this.close();
}
}
/**
* @internal
*/
set toggleElement(toggleElement: any) { this._toggleElement = toggleElement; }
private _isEventFromToggle($event) { return !!this._toggleElement && this._toggleElement.contains($event.target); }
}
/**
* Allows the dropdown to be toggled via click. This directive is optional.
*/
@Directive({
selector: '[ngbDropdownToggle]',
host: {
'class': 'dropdown-toggle',
'aria-haspopup': 'true',
'[attr.aria-expanded]': 'dropdown.isOpen()',
'(click)': 'toggleOpen()'
}
})
export class NgbDropdownToggle {
constructor(public dropdown: NgbDropdown, elementRef: ElementRef) {
dropdown.toggleElement = elementRef.nativeElement;
}
toggleOpen() { this.dropdown.toggle(); }
}
export const NGB_DROPDOWN_DIRECTIVES = [NgbDropdownToggle, NgbDropdown];
import {Injectable, TemplateRef} from '@angular/core';
/**
* Configuration service for the NgbDropdown directive.
* You can inject this service, typically in your root component, and customize the values of its properties in
* order to provide default values for all the dropdowns used in the application.
*/
@Injectable()
export class NgbDropdownConfig {
up = false;
autoClose = true;
}
import {NgModule, ModuleWithProviders} from '@angular/core';
import {NGB_DROPDOWN_DIRECTIVES} from './dropdown';
import {NgbDropdownConfig} from './dropdown-config';
export {NgbDropdownConfig} from './dropdown-config';
@NgModule({declarations: NGB_DROPDOWN_DIRECTIVES, exports: NGB_DROPDOWN_DIRECTIVES})
export class NgbDropdownModule {
static forRoot(): ModuleWithProviders { return {ngModule: NgbDropdownModule, providers: [NgbDropdownConfig]}; }
}