<!DOCTYPE html>
<html>
<head>
<base href="." />
<title>angular playground</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<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>
<div class="alert alert-danger" role="alert">
This component is discontinued anymore. It's compatible with both Angular 2 & 4
</div>
<div class="alert alert-warning" role="alert">
But if you are using Angular 4, should switch to my new component: <a href="https://www.npmjs.com/package/ngx-treeview">ngx-treeview</a>
</div>
<leo-app>
loading...
</leo-app>
</body>
</html>
### Angular ng2-dropdown-treeview component demo.
This component is discontinued anymore. It's compatible with both Angular 2 & 4.
If you are using Angular 4, please switch to my new component: https://www.npmjs.com/package/ngx-treeview
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',
'rxjs': 'npm:rxjs',
'typescript': 'npm:typescript@2.2.1/lib/typescript.js',
'lodash' : 'npm:lodash/lodash.min.js',
'ng2-dropdown-treeview' : 'npm:ng2-dropdown-treeview/bundles/ng2-dropdown-treeview.umd.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.module';
platformBrowserDynamic().bootstrapModule(AppModule)
import { Component } from '@angular/core';
import { TreeviewI18n } from 'ng2-dropdown-treeview';
import { I18n } from './i18n';
import { DefaultTreeviewI18n } from './default-treeview-i18n';
@Component({
selector: 'leo-app',
template: `
<div class="container">
<h2>Angular 2 dropdown-treeview component demo</h2>
<hr />
<br />
<div class="row">
<label for="item-category" class="col-3 col-form-label">Language</label>
<div class="col-9">
<select class="form-control" [(ngModel)]="language">
<option value="en">
English
</option>
<option value="vi">
Tiếng Việt
</option>
</select>
</div>
</div>
<hr>
<h4>Example 1: Primary features</h4>
<leo-book></leo-book>
<br />
<h4>Example 2: Performance with 1000 items</h4>
<leo-room></leo-room>
<br />
<h4>Example 3: Using pipe & i18n</h4>
<leo-city></leo-city>
<br />
<h4>Example 4: Tree-view without drop-down & custom TreeviewConfig & custom TreeviewEventParser & custom template</h4>
<leo-product></leo-product>
</div>
`,
providers: [
{ provide: TreeviewI18n, useClass: DefaultTreeviewI18n }
]
})
export class AppComponent {
constructor(
private i18n: I18n
) { }
set language(language: string) {
this.i18n.language = language;
}
get language() {
return this.i18n.language;
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { DropdownTreeviewModule } from 'ng2-dropdown-treeview';
import { AppComponent } from './app.component';
import { BookComponent } from './book/book.component';
import { CityComponent } from './city/city.component';
import { RoomComponent } from './room/room.component';
import { ProductComponent } from './product/product.component';
import { I18n } from './i18n';
import { DisabledOnSelectorDirective } from './disabled-on-selector.directive';
@NgModule({
imports: [
BrowserModule,
FormsModule,
DropdownTreeviewModule.forRoot()
],
declarations: [
BookComponent,
CityComponent,
RoomComponent,
ProductComponent,
AppComponent,
DisabledOnSelectorDirective
],
providers: [
I18n
],
bootstrap: [AppComponent]
})
export class AppModule { }
import { Injectable } from '@angular/core';
@Injectable()
export class I18n {
language = 'en';
}
import { Injectable } from '@angular/core';
import { TreeviewItem, TreeviewI18n } from 'ng2-dropdown-treeview';
import { I18n } from './i18n';
@Injectable()
export class DefaultTreeviewI18n extends TreeviewI18n {
constructor(
protected i18n: I18n
) {
super();
}
getText(checkededItems: TreeviewItem[], isAll: boolean): string {
if (isAll) {
return this.i18n.language === 'en' ? 'All' : 'Tất cả';
}
switch (checkededItems.length) {
case 0:
return this.i18n.language === 'en' ? 'Select options' : 'Chọn mục';
case 1:
return checkededItems[0].text;
default:
return this.i18n.language === 'en'
? `${checkededItems.length} options selected`
: `${checkededItems.length} mục đã được chọn`;
}
}
allCheckboxText(): string {
if (this.i18n.language === 'en') {
return 'All';
} else {
return 'Tất cả';
}
}
filterPlaceholder(): string {
if (this.i18n.language === 'en') {
return 'Filter';
} else {
return 'Lọc';
}
}
filterNoItemsFoundText(): string {
if (this.i18n.language === 'en') {
return 'No items found';
} else {
return 'Không có mục nào được tìm thấy';
}
}
tooltipCollapseExpand(isCollapse: boolean): string {
return isCollapse
? this.i18n.language === 'en' ? 'Expand' : 'Mở rộng'
: this.i18n.language === 'en' ? 'Collapse' : 'Thu lại';
}
}
import { Directive, Input, OnChanges, ElementRef, Renderer } from '@angular/core';
@Directive({
selector: '[leoDisabledOnSelector]'
})
export class DisabledOnSelectorDirective implements OnChanges {
@Input('leoDisabledOnSelector') leoDisabledOnSelector: string;
@Input() disabled: boolean;
private readonly nativeElement: HTMLElement;
constructor(
private el: ElementRef,
private renderer: Renderer) {
this.nativeElement = el.nativeElement;
}
ngOnChanges() {
const elements = this.nativeElement.querySelectorAll(this.leoDisabledOnSelector);
for (let i = 0; i < elements.length; i++) {
this.renderer.setElementProperty(elements[i], 'disabled', this.disabled);
}
}
}
import { Injectable } from '@angular/core';
import { TreeviewItem } from 'ng2-dropdown-treeview';
import { I18n } from '../i18n';
import { DefaultTreeviewI18n } from '../default-treeview-i18n';
@Injectable()
export class CityTreeviewI18n extends DefaultTreeviewI18n {
constructor(
protected i18n: I18n
) {
super(i18n);
}
getText(checkededItems: TreeviewItem[], isAll: boolean): string {
if (isAll) {
return this.i18n.language === 'en' ? 'All cities' : 'Tất cả thành phố';
}
switch (checkededItems.length) {
case 0:
return this.i18n.language === 'en' ? 'Select cities' : 'Chọn thành phố';
case 1:
return checkededItems[0].text;
default:
return this.i18n.language === 'en'
? `${checkededItems.length} cities selected`
: `${checkededItems.length} thành phố đã được chọn`;
}
}
allCheckboxText(): string {
return super.allCheckboxText();
}
filterPlaceholder(): string {
return super.filterPlaceholder();
}
filterNoItemsFoundText(): string {
if (this.i18n.language === 'en') {
return 'No cities found';
} else {
return 'Không có thành phố nào được tìm thấy';
}
}
tooltipCollapseExpand(isCollapse: boolean): string {
return super.tooltipCollapseExpand(isCollapse);
}
}
import { Component, OnInit } from '@angular/core';
import { TreeviewI18n } from 'ng2-dropdown-treeview';
import { City, CityService } from './city.service';
import { CityTreeviewI18n } from './city-treeview-i18n';
@Component({
selector: 'leo-city',
template: `
<div class="row">
<div class="col-12">
<div class="alert alert-success" role="alert">
Selected cities: {{values | json}}
</div>
</div>
<div class="col-12">
<div class="form-group row">
<label for="city-category" class="col-3 col-form-label">City category</label>
<div class="col-9">
<leo-dropdown-treeview [items]="cities | leoTreeview:'name'" (selectedChange)="values = $event">
</leo-dropdown-treeview>
</div>
</div>
</div>
</div>
`, providers: [
CityService,
{ provide: TreeviewI18n, useClass: CityTreeviewI18n }
]
})
export class CityComponent implements OnInit {
cities: City[];
values: City[];
constructor(
private service: CityService
) { }
ngOnInit() {
this.cities = this.service.getCities();
}
}
import { Injectable } from '@angular/core';
export interface City {
id: number;
name: string;
postCode: number;
}
@Injectable()
export class CityService {
getCities(): City[] {
return [
{
id: 1,
name: 'Ho Chi Minh',
postCode: 700000
},
{
id: 2,
name: 'Ha Noi',
postCode: 100000
},
{
id: 3,
name: 'Da Nang',
postCode: 550000
}
];
}
}
import { Component, Injectable, OnInit, ViewChild } from '@angular/core';
import * as _ from 'lodash';
import {
TreeviewI18n, TreeviewItem, TreeviewConfig, TreeviewHelper, TreeviewComponent,
TreeviewEventParser, OrderDownlineTreeviewEventParser, DownlineTreeviewItem
} from 'ng2-dropdown-treeview';
import { ProductService } from './product.service';
@Injectable()
export class ProductTreeviewConfig extends TreeviewConfig {
isShowAllCheckBox = true;
isShowFilter = true;
isShowCollapseExpand = false;
maxHeight = 500;
}
@Component({
selector: 'leo-product',
template: `
<template #tpl let-item="item"
let-toggleCollapseExpand="toggleCollapseExpand"
let-onCheckedChange="onCheckedChange">
<div class="form-check">
<i *ngIf="item.children" (click)="toggleCollapseExpand()" aria-hidden="true"
class="fa" [class.fa-caret-right]="item.collapsed" [class.fa-caret-down]="!item.collapsed"></i>
<label class="form-check-label">
<input type="checkbox" class="form-check-input"
[(ngModel)]="item.checked" (ngModelChange)="onCheckedChange()" [disabled]="item.disabled" />
{{item.text}}
</label>
<label class="form-check-label">
<i class="fa fa-trash" aria-hidden="true" title="Remove" (click)="removeItem(item)"></i>
</label>
</div>
</template>
<div class="row">
<div class="col-6">
<div class="form-group">
<div class="d-inline-block">
<leo-treeview [items]="items" [template]="tpl" (selectedChange)="onSelectedChange($event)">
</leo-treeview>
</div>
</div>
</div>
<div class="col-6">
<div class="alert alert-success" role="alert">
Selected products:
<div *ngFor="let row of rows">{{row}}</div>
</div>
</div>
</div>
`, providers: [
ProductService,
{ provide: TreeviewEventParser, useClass: OrderDownlineTreeviewEventParser },
{ provide: TreeviewConfig, useClass: ProductTreeviewConfig }
]
})
export class ProductComponent implements OnInit {
@ViewChild(TreeviewComponent) treeviewComponent: TreeviewComponent;
items: TreeviewItem[];
rows: string[];
constructor(
private service: ProductService
) { }
ngOnInit() {
this.items = this.service.getProducts();
}
onItemCheckedChange(item: TreeviewItem) {
console.log(item);
}
onSelectedChange(downlineItems: DownlineTreeviewItem[]) {
this.rows = [];
downlineItems.forEach(downlineItem => {
const item = downlineItem.item;
const value = item.value;
const texts = [item.text];
let parent = downlineItem.parent;
while (!_.isNil(parent)) {
texts.push(parent.item.text);
parent = parent.parent;
}
const reverseTexts = _.reverse(texts);
const row = `${reverseTexts.join(' -> ')} : ${value}`;
this.rows.push(row);
});
}
removeItem(item: TreeviewItem) {
TreeviewHelper.removeItem(item, this.items);
this.treeviewComponent.raiseSelectedChange();
}
}
import { Injectable } from '@angular/core';
import { TreeviewItem } from 'ng2-dropdown-treeview';
export class ProductService {
getProducts(): TreeviewItem[] {
const fruitCategory = new TreeviewItem({
text: 'Fruit', value: 1, children: [
{ text: 'Apple', value: 11 },
{ text: 'Mango', value: 12 }
]
});
const vegetableCategory = new TreeviewItem({
text: 'Vegetable', value: 2, children: [
{ text: 'Salad', value: 21 },
{ text: 'Potato', value: 22 }
]
});
vegetableCategory.children.push(new TreeviewItem({ text: 'Mushroom', value: 23, checked: false }));
vegetableCategory.correctChecked(); // need this to make 'Vegetable' node to change checked value from true to false
return [fruitCategory, vegetableCategory];
}
}
import { Component, OnInit } from '@angular/core';
import { TreeviewConfig, TreeviewItem } from 'ng2-dropdown-treeview';
import { RoomService } from './room.service';
@Component({
selector: 'leo-room',
template: `
<div class="row">
<div class="col-12">
<div class="alert alert-success" role="alert">
Selected rooms: {{values}}
</div>
</div>
<div class="col-12">
<div class="form-group row">
<label for="item-category" class="col-3 col-form-label">Item category</label>
<div class="col-9">
<leo-dropdown-treeview [config]="config" [items]="items" (selectedChange)="values = $event">
</leo-dropdown-treeview>
</div>
</div>
</div>
</div>
`, providers: [
RoomService
]
})
export class RoomComponent implements OnInit {
items: TreeviewItem[];
values: any[];
config: TreeviewConfig = {
isShowAllCheckBox: true,
isShowFilter: true,
isShowCollapseExpand: false,
maxHeight: 500
};
constructor(
private service: RoomService
) { }
ngOnInit() {
this.items = this.service.getRooms();
}
}
import { Injectable } from '@angular/core';
import { TreeviewItem } from 'ng2-dropdown-treeview';
@Injectable()
export class RoomService {
getRooms(): TreeviewItem[] {
const items: TreeviewItem[] = [];
for (let i = 0; i < 1000; i++) {
const value: any = i === 0 ? { name: `${i}` } : i;
const checked = i % 100 === 0;
const item = new TreeviewItem({ text: `Room ${i}`, value: value, checked: checked });
items.push(item);
};
return items;
}
}
import { Component, OnInit } from '@angular/core';
import { TreeviewItem, TreeviewConfig } from 'ng2-dropdown-treeview';
import { BookService } from './book.service';
@Component({
selector: 'leo-book',
template: `
<div class="row">
<div class="col-12">
<div class="alert alert-success" role="alert">
Selected books: {{values}}
</div>
</div>
<div class="col-12">
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" [(ngModel)]="enableButton">
Check/uncheck to enable/disable dropdown button
</label>
</div>
<div class="form-group row">
<label for="book-category" class="col-3 col-form-label">Book category</label>
<div class="col-9">
<div class="d-inline-block">
<leo-dropdown-treeview [config]="config" [items]="items" (selectedChange)="values = $event"
[disabled]="!enableButton" [leoDisabledOnSelector]="'button.dropdown-toggle'">
</leo-dropdown-treeview>
</div>
</div>
</div>
</div>
</div>
`, providers: [
BookService
]
})
export class BookComponent implements OnInit {
enableButton = true;
items: TreeviewItem[];
values: number[];
config: TreeviewConfig = {
isShowAllCheckBox: true,
isShowFilter: true,
isShowCollapseExpand: true,
maxHeight: 500
};
constructor(
private service: BookService
) { }
ngOnInit() {
this.items = this.service.getBooks();
}
}
import { Injectable } from '@angular/core';
import { TreeviewItem } from 'ng2-dropdown-treeview';
export class BookService {
getBooks(): TreeviewItem[] {
const childrenCategory = new TreeviewItem({
text: 'Children', value: 1, collapsed: true, children: [
{ text: 'Baby 3-5', value: 11 },
{ text: 'Baby 6-8', value: 12 },
{ text: 'Baby 9-12', value: 13 }
]
});
const itCategory = new TreeviewItem({
text: 'IT', value: 9, children: [
{
text: 'Programming', value: 91, children: [{
text: 'Frontend', value: 911, children: [
{ text: 'Angular 1', value: 9111 },
{ text: 'Angular 2', value: 9112 },
{ text: 'ReactJS', value: 9113 }
]
}, {
text: 'Backend', value: 912, children: [
{ text: 'C#', value: 9121 },
{ text: 'Java', value: 9122 },
{ text: 'Python', value: 9123, checked: false }
]
}]
},
{
text: 'Networking', value: 92, children: [
{ text: 'Internet', value: 921 },
{ text: 'Security', value: 922 }
]
}
]
});
const teenCategory = new TreeviewItem({
text: 'Teen', value: 2, collapsed: true, disabled: true, children: [
{ text: 'Adventure', value: 21 },
{ text: 'Science', value: 22 }
]
});
const othersCategory = new TreeviewItem({ text: 'Others', value: 3, collapsed: true, disabled: true });
return [childrenCategory, itCategory, teenCategory, othersCategory];
}
}