<!DOCTYPE html>
<html>
<head>
<base href="." />
<title>angular2 playground</title>
<link rel="stylesheet" href="style.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>
<my-app>
loading...
</my-app>
</body>
</html>
h1{text-align:center}
.centered{text-align:center;margin:0 auto}
smart-table{position:relative}
.smart-table-wrap{
border-right: 1px solid #aaa;
border-bottom: 1px solid #aaa;
box-sizing: border-box;
margin: 0 auto;
max-width: 100%;
overflow-x: auto;
position: relative
}
.smart-table-wrap table{margin:0 auto}
.smart-table-wrap table th{
background-color:#777;
color:#fff;
cursor:default;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
.smart-table-wrap table td{
border:1px solid #bbb;
padding:5px;
white-space: nowrap;
background-color:#fff
}
.smart-table-wrap table tr.odd td{
background-color:#eee;
min-width:50px;
}
.smart-table-wrap .locked-table{border-right: 1px solid #aaa;position:fixed;z-index:2}
.smart-table-wrap .unlocked-table{margin-left:160px}
.smart-table-wrap table th {
background-image: url(https://raw.githubusercontent.com/msalehisedeh/SmartTable/master/app/blue-bar.png);
background-repeat: no-repeat;
height: 30px;
position: relative;
text-shadow: #012b4d 2px 2px 2px;
text-align: center;
}
.smart-table-wrap table td img{
height: 15px;
}
.smart-table-wrap table th.locked .lock{
background-image: url(https://raw.githubusercontent.com/msalehisedeh/SmartTable/master/app/indicators.png);
background-position: 0 0;
background-repeat: no-repeat;
cursor:pointer;
height:12px;
position: absolute;
right: 2px;
top: 2px;
width:12px;
}
.smart-table-wrap table th.unlocked .lock{
background-image: url(https://raw.githubusercontent.com/msalehisedeh/SmartTable/master/app/indicators.png);
background-repeat: no-repeat;
background-position: -12px 0;
cursor:pointer;
height:12px;
position: absolute;
right: 2px;
top: 2px;
width:12px;
}
.smart-table-wrap th.asc .sort{
background-image: url(https://raw.githubusercontent.com/msalehisedeh/SmartTable/master/app/indicators.png);
background-repeat: no-repeat;
width:12px;
height:12px;
background-position: -24px 0;
position: absolute;
bottom: 2px;
right: 2px;
}
.smart-table-wrap th.des .sort{
background-image: url(https://raw.githubusercontent.com/msalehisedeh/SmartTable/master/app/indicators.png);
background-repeat: no-repeat;
width:12px;
height:12px;
background-position: -36px 0;
position: absolute;
bottom: 2px;
right: 2px;
}
.smart-table-wrap th.not .sort{display:none}
.smart-table-wrap td.currency{text-align:right}
.smart-table-wrap th.attention,.smart-table-wrap td.attention{color:#f00}
pagination {
display: block;
clear: both;
min-height: 28px;
margin: 1px 0;
}
pagination .wrapper {
box-sizing: border-box;
font-size: 1em;
position: relative;
max-width: 100%;
margin: 0 auto;
}
pagination .wrapper .next,
pagination .wrapper .prev,
pagination .wrapper .last,
pagination .wrapper .first {
background-image: url(https://raw.githubusercontent.com/msalehisedeh/SmartTable/master/app/blue-bar.png);
background-repeat: no-repeat;
border: 1px solid #ddd;
border-radius: 3px;
color:#fff;
cursor:pointer;
float:right;
min-width:24px;
padding: 5px;
text-shadow: #012b4d 2px 2px 2px;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
pagination .wrapper .current,
pagination .wrapper .reset-size {
background-image: url(https://raw.githubusercontent.com/msalehisedeh/SmartTable/master/app/blue-bar.png);
background-repeat: no-repeat;
border: 1px solid #ddd;
border-radius: 3px;
color:#fff;
min-width:100px;
float:right;
padding: 5px;
text-shadow: #012b4d 2px 2px 2px;
text-align: center;
}
pagination .wrapper .current input,
pagination .wrapper .reset-size input {
padding: 0 3px;
width: 50px;
height: 14px;
}
pagination .wrapper .disabled{
color: #dbdbdb !important;
opacity: 0.7;
}
### Angular Starter Plunker - Typescript
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',
'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)
import {
Component,
ViewChild,
ViewContainerRef,
ElementRef,
ComponentFactoryResolver,
NgModule} from "@angular/core";
import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
import {BrowserModule} from "@angular/platform-browser";
import {HttpModule} from "@angular/http";
import {Observable} from "rxjs/Observable";
import 'rxjs/add/operator/map'
import {FormatPipe} from './format.pipe';
import {ContentManagementPipe,ContentManagementLangSetup} from './i18n.pipe';
import {SmartTable,SmartTableData,ORDER_BY} from './smart-table.component';
import {Pagination,PaginationInfo} from './pagination.component';
@Component({
selector:'my-app',
template: `<div lang="{{pl|isDefaultLanguage}}">
<h1>{{"sample.home.title" | i18n:pl}}</h1>
<p class="centered">{{"sample.home.description" | i18n:pl}}</p>
<p class="centered">{{"sample.home.click.lock" | i18n:pl}}</p>
<p class="centered">{{"sample.home.click.drag" | i18n:pl}}</p>
<smart-table [content]="tableData" (onbefrepagesizechange)="beforePageSizeChange(input)" #theTable></smart-table>
<br/>
<div class="centered">
<input id="input" type="checkbox" #input (click)="sctivateReactComparison($event.target.checked)" /><label for="input">{{"sample.checkbox.compare" | i18n:pl}}</label>
</div>
</div>
`
})
export class SmartTableApp {
@ViewChild('theTable') private theTable: SmartTable;
private pl = "en_US";
private tableData:SmartTableData = {};
private intervals:number[] = [];
constructor(private resolver:ComponentFactoryResolver){
let data = [
[24434,'Joe Black',54000.00,'not listed','cancer','additional information needed|https://www.google.com','lost contact|https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png','place holder','place holder','place holder','place holder','place holder'],
[24333,'Jeniffer Holand',154000.00,'listed','TB','information supplied|https://www.google.com','contact verified|https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png','place holder','place holder','place holder','place holder','place holder'],
[24411,'Fred Hampton',114000.00,'in transition','brain tumor','information forwarded|https://www.google.com','midding contact info|https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png','place holder','place holder','place holder','place holder','place holder'],
[24411,'Joe Apaya',104000.00,'listed','legament tumor','information forwarded|https://www.google.com','midding contact info|https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png','place holder','place holder','place holder','place holder','place holder'],
[24411,'Margaret Hays',164000.00,'in transition','malice','information forwarded|https://www.google.com','midding contact info|https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png','place holder','place holder','place holder','place holder','place holder'],
[24411,'Olav palyov',414000.00,'listed','delugional','information forwarded|https://www.google.com','midding contact info|https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png','place holder','place holder','place holder','place holder','place holder'],
[24411,'Mo Thacher',14000.00,'in transition','drunkeness','information forwarded|https://www.google.com','midding contact info|https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png','place holder','place holder','place holder','place holder','place holder'],
[24411,'Bob Blake',316000.00,'listed','bladder stone','information forwarded|https://www.google.com','midding contact info|https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png','place holder','place holder','place holder','place holder','place holder'],
[24545,'Morali Shaban',94000.00,'listed','kidney stone','additional data needed|https://www.google.com','contact verified|https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png','place holder','place holder','place holder','place holder','place holder']
];
this.tableData={
id: "mySmartTable1",
dragColumns:true,
showEvenRows:true,
headers:[
{id:"col1",name:"id",format:"NUMB:0",lockable:true,sortable:true},
{id:"col2",name:"name",format:"TEXT:50",lockable:true,sortable:true},
{id:"col3",name:"income",format:"CURR:$",class:'currency',lockable:true,sortable:true},
{id:"col4",name:"housing",format:"TEXT:50",class:'attention',sortable:true},
{id:"col5",name:"illness",format:"TEXT:50",sortable:true},
{id:"col6",name:"text 1",format:"LINK:_top"},
{id:"col7",name:"text 2",format:"IMAG:50"},
{id:"col8",name:"text 3",format:"TEXT:50"},
{id:"col9",name:"text 4",format:"TEXT:50"},
{id:"col10",name:"text 5",format:"TEXT:50"},
{id:"col11",name:"text 6",format:"TEXT:50"},
{id:"col12",name:"text 7",format:"TEXT:50"}
],
rows:data,
pagination:{pageSize:8,contentSize:data.length,resetSize:true}
};
}
beforePageSizeChange(input:Element){
if(this.intervals.length){
//this.sctivateReactComparison(false);
}
}
sctivateReactComparison(checked:boolean){
// see the perfomance of angular2 is just as good as ReactJS.
if(checked){
this.intervals.push(setInterval(()=>this.tableData.rows[0][0]=Math.floor(Math.random()*4000),500));
this.intervals.push(setInterval(()=>this.tableData.rows[2][0]=Math.floor(Math.random()*5000),600));
this.intervals.push(setInterval(()=>this.tableData.rows[4][0]=Math.floor(Math.random()*1000),700));
this.intervals.push(setInterval(()=>this.tableData.rows[6][0]=Math.floor(Math.random()*6000),800));
this.intervals.push(setInterval(()=>this.tableData.rows[7][0]=Math.floor(Math.random()*6000),800));
this.intervals.push(setInterval(()=>this.tableData.rows[1][2]=Math.floor(Math.random()*40000),500));
this.intervals.push(setInterval(()=>this.tableData.rows[3][2]=Math.floor(Math.random()*50000),600));
this.intervals.push(setInterval(()=>this.tableData.rows[5][2]=Math.floor(Math.random()*10000),700));
this.intervals.push(setInterval(()=>this.tableData.rows[6][2]=Math.floor(Math.random()*60000),800));
this.intervals.push(setInterval(()=>this.tableData.rows[7][2]=Math.floor(Math.random()*60000),800));
this.intervals.push(setInterval(()=>{
this.tableData.rows[1][3]=Math.floor(Math.random()*10)>5 ? "in transit":"listed";
this.tableData.rows[3][3]=Math.floor(Math.random()*10)>5 ? "in transit":"listed";
this.tableData.rows[5][3]=Math.floor(Math.random()*10)>5 ? "in transit":"listed";
this.tableData.rows[6][3]=Math.floor(Math.random()*10)>5 ? "in transit":"listed";
this.tableData.rows[7][3]=Math.floor(Math.random()*10)>5 ? "in transit":"listed";
this.theTable.resetBoundaries();
},800));
}else {
for(let i:number=0;i<this.intervals.length;i++){
clearInterval(this.intervals[i])
}
this.intervals=[];
}
}
}
@NgModule({
declarations: [
SmartTable,
SmartTableApp,
FormatPipe,
Pagination,
ContentManagementPipe,
ContentManagementLangSetup
],
imports: [BrowserModule,HttpModule],
bootstrap: [SmartTableApp]
})
export default class AppModule {
}
platformBrowserDynamic().bootstrapModule(AppModule);
import {
Component,
ComponentFactory,
ReflectiveInjector,
ViewContainerRef,
Input,
Output,
HostListener,
EventEmitter,
ViewChild,
ElementRef} from "@angular/core";
import {Pagination,PaginationInfo} from './pagination.component';
export enum ORDER_BY {NOT,ASC,DES}
export interface SmartTableHeader {
id?:string
name:string,
class?:string,
format:string,
lockable?:boolean,
locked?:boolean,
sortable?:boolean,
sortorder?:ORDER_BY
}
export interface SmartTableData {
id?:string
pagination?:PaginationInfo,
defaultSortIndex?:number,
headers?:SmartTableHeader[],
dragColumns?:boolean,
showEvenRows?:boolean,
rows?:any[]
}
export interface Pagination {
from?:number
to?:number,
pageSize?:number,
currentPage?:number
}
@Component({
selector:'smart-table',
template: `
<pagination [info]="this.content.pagination"
(onready)="readyPagination($event)" (onchange)="updatePagination($event)" #pagination></pagination>
<div class="smart-table-wrap">
<table id="content.id" cellpadding="0" cellspacing="0" class="locked-table" #lockedTable>
<tbody>
<tr>
<template ngFor let-header [ngForOf]="content.headers">
<th *ngIf="header.locked" id="{{header.id}}" class="{{header.class}}"
(click)="sort(header.id)"
[class.asc]="header.sortable && header.sortorder==orderASC"
[class.des]="header.sortable && header.sortorder==orderDES"
[class.not]="header.sortable && header.sortorder==orderNOT"
[class.locked]="header.lockable">
{{header.name}}
<a class="lock" (click)="lock(header.id,false)"></a>
<span class="sort"></span>
</th>
</template>
</tr>
<template ngFor let-row [ngForOf]="content.rows" let-j="index">
<tr *ngIf="!content.pagination || (j>=content.pagination.from && j<=content.pagination.to)" [class.odd]="content.showEvenRows && j%2">
<template ngFor let-col [ngForOf]="row" let-i="index">
<td class="{{content.headers[i].class}}" *ngIf="content.headers[i].locked"><span [outerHTML]="col | format:content.headers[i].format"></span></td>
</template>
</tr>
</template>
</tbody>
</table>
<table id="content.id" cellpadding="0" cellspacing="0" class="unlocked-table" #unlockedTable>
<tbody>
<tr>
<template ngFor let-header [ngForOf]="content.headers">
<th *ngIf="!header.locked" id="{{header.id}}" class="{{header.class}}"
(click)="sort(header.id)"
[class.asc]="header.sortable && header.sortorder==orderASC"
[class.des]="header.sortable && header.sortorder==orderDES"
[class.not]="header.sortable && header.sortorder==orderNOT"
[class.unlocked]="header.lockable">
{{header.name}}
<a class="lock" (click)="lock(header.id,true)"></a>
<span class="sort"></span>
</th>
</template>
</tr>
<template ngFor let-row [ngForOf]="content.rows" let-j="index">
<tr *ngIf="!content.pagination || (j>=content.pagination.from && j<=content.pagination.to)" [class.odd]="content.showEvenRows && j%2">
<template ngFor let-col [ngForOf]="row" let-i="index">
<td class="{{content.headers[i].class}}" *ngIf="!content.headers[i].locked"><span [outerHTML]="col | format:content.headers[i].format"></span></td>
</template>
</tr>
</template>
</tbody>
</table>
</div>`
})
export class SmartTable {
@ViewChild('lockedTable', {read: ViewContainerRef}) private lockedTable: ViewContainerRef;
@ViewChild('unlockedTable', {read: ViewContainerRef}) private unlockedTable: ViewContainerRef;
@ViewChild('pagination') private pagination: Pagination;
@Input("content")
public content:SmartTableData ={};
@Output('onbefrepagesizechange')
private befrepagesizechange = new EventEmitter();
private el:HTMLElement;
private orderNOT:ORDER_BY = ORDER_BY.NOT;
private orderASC:ORDER_BY = ORDER_BY.ASC;
private orderDES:ORDER_BY = ORDER_BY.DES;
constructor(el: ElementRef) {
this.el = el.nativeElement;
}
@HostListener("window:scroll", [])
onWindowScroll() {
let lt = this.lockedTable.element.nativeElement;
let ut = this.unlockedTable.element.nativeElement;
let rect = ut.parentNode.getBoundingClientRect();
lt.style.top = rect.top+"px";
lt.style.left = (rect.left+2)+"px";
}
ngOnChanges(changes:any) {
if(!this.content.defaultSortIndex){
for(let i=0;i<this.content.headers.length;i++){
let h = this.content.headers[i];
if(h.sortable){
this.content.defaultSortIndex = i;
this.sort(h.id);
break;
}
}
}else {
this.sort(this.content.headers[this.content.defaultSortIndex].id);
}
setTimeout(()=>this.calculateBoundaries(),20);
if(this.content.dragColumns){
setTimeout(()=>this.enableDragging(),40);
}
}
enableDragging(){
let list = this.unlockedTable.element.nativeElement.children[0].children[0].children;
for(let i=0;i<list.length;i++){
this.registerDargEvents(list[i]);
}
}
findColumnWithID(id:string){
let list = this.unlockedTable.element.nativeElement.children[0].children[0].children;
let column = null;
for(let i=0;i<list.length;i++){
if(list[i].getAttribute("id")==id){
column = list[id];
break;
}
}
return column;
}
registerDargEvents(column:any){
column.draggable = 'true';
column.addEventListener('dragstart', this.dragStart);
column.addEventListener('dragover', this.dragOver);
column.parentNode.addEventListener('dragover', this.dragOver);
column.addEventListener('dragend', this.dragEnd);
column.addEventListener('drop', this.dragDropped.bind(this));
}
unRegisterDargEvents(column:any){
column.removeEventListener('dragstart', this.dragStart);
column.removeEventListener('dragover', this.dragOver);
column.parentNode.removeEventListener('dragover', this.dragOver);
column.removeEventListener('dragend', this.dragEnd);
column.removeEventListener('drop', this.dragDropped);
}
dragStart(e:any){
e.dataTransfer.setData('id', e.target.getAttribute("id"));
e.dataTransfer.effectAllowed = 'move';
return false;
}
dragOver(e:any){
if (e.preventDefault) e.preventDefault();
return false;
}
dragEnd(e:any){
e.preventDefault();
}
dragDropped(e:any){
if (e.stopPropagation) {
e.stopPropagation(); // Stops some browsers from redirecting.
}
let sourceID = e.dataTransfer.getData('id');
let destinationID = e.target.getAttribute("id");
this.swapColumns(sourceID, destinationID);
return false;
}
swapColumns(sourceID:string, destinationID:string){
let srcIndex = this.getColumnIndex(sourceID);
let desIndex = this.getColumnIndex(destinationID);
let sobj = this.content.headers[srcIndex];
this.content.headers[srcIndex] = this.content.headers[desIndex];
this.content.headers[desIndex] = sobj;
for(let i = 0;i<this.content.rows.length;i++){
let row = this.content.rows[i];
let sobj = row[srcIndex];
row[srcIndex] = row[desIndex];
row[desIndex] = sobj;
}
}
getColumnIndex(id:string){
let index = -1;
for(let i = 0;i<this.content.headers.length;i++){
if(this.content.headers[i].id==id){
index = i;
break;
}
}
return index;
}
calculateBoundaries(){
let lt = this.lockedTable.element.nativeElement;
let ut = this.unlockedTable.element.nativeElement;
let wrapper = ut.parentNode;
let lrect = lt.getBoundingClientRect();
let urect = ut.getBoundingClientRect();
ut.style.marginLeft = (lrect.width-1)+"px";
wrapper.style.width = ( urect.width+(lrect.width>10 ? lrect.width-7: lrect.width))+"px";
}
lock(id:string, flag:boolean){
for(let i=0;i<this.content.headers.length;i++){
let h = this.content.headers[i];
if(h.id == id){
if(flag){
this.unRegisterDargEvents(this.findColumnWithID(id));
}
h.locked=flag;
setTimeout(()=>{
this.calculateBoundaries()
if(!flag){
this.registerDargEvents(this.findColumnWithID(id));
}
},20);
}
}
setTimeout(()=>this.resetBoundaries(),2);
}
public resetBoundaries(){
this.calculateBoundaries();
this.readyPagination("");
}
sort(id:string){
for(let i=0;i<this.content.headers.length;i++){
let h = this.content.headers[i];
if(h.id == id && h.sortable){
if(h.sortorder===ORDER_BY.NOT || h.sortorder===ORDER_BY.ASC){
h.sortorder=ORDER_BY.DES;
}else {
h.sortorder=ORDER_BY.ASC;
}
this.content.rows.sort((a,b)=>{
if(h.sortorder==ORDER_BY.ASC){
return a[i]>b[i] ? 1:-1;
}
return a[i]<b[i] ? 1:-1;
});
this.content.defaultSortIndex = i;
}else {
h.sortorder=ORDER_BY.NOT;
}
}
setTimeout(()=>{
this.calculateBoundaries();
this.readyPagination("");
},2);
}
readyPagination($event:any){
let lt = this.lockedTable.element.nativeElement;
let ut = this.unlockedTable.element.nativeElement;
let wrapper = ut.parentNode;
let lrect = lt.getBoundingClientRect();
let urect = ut.getBoundingClientRect();
this.pagination.setWidth( urect.width+(lrect.width>10 ? lrect.width-7: lrect.width));
}
updatePagination($event:any){
setTimeout(()=>{
this.befrepagesizechange.emit();
this.resetBoundaries();
},10);
}
}
import {
Component,
ComponentFactory,
ReflectiveInjector,
ViewContainerRef,
Input,
Output,
HostListener,
EventEmitter,
ViewChild,
ElementRef} from "@angular/core";
export interface PaginationInfo {
contentSize:number,
pageSize:number,
maxWidth?:string,
pages?:number,
from?:number,
to?:number,
currentPage?:number,
resetSize?:boolean
}
@Component({
selector:'pagination',
template: `
<div *ngIf="canDisplayPagination" [style.width]="info.maxWidth" class="wrapper" #paginationWrapper>
<div class="reset-size" *ngIf="info.resetSize">Page size: <input [value]="info.pageSize" (keydown.Enter)="changeSize(sizer)" #sizer/></div>
<div class="last" (click)="selectLast()" [class.disabled]="info.currentPage==info.pages">Last</div>
<div class="next" (click)="selectNext()" [class.disabled]="info.currentPage==info.pages">Next</div>
<div class="current">page <input [value]="info.currentPage" (keydown.Enter)="changeCurrent(ranger)" #ranger/> of {{info.pages}}</div>
<div class="prev" (click)="selectPrev()" [class.disabled]="info.currentPage==1">Previous</div>
<div class="first" (click)="selectFirst()" [class.disabled]="info.currentPage==1">First</div>
</div>`
})
export class Pagination {
@ViewChild('paginationWrapper') private pager: Pagination;
@ViewChild('paginationWrapper', {read: ViewContainerRef}) private root: ViewContainerRef;
private canDisplayPagination:boolean = false;
@Input("info")
private info:PaginationInfo ={contentSize:0,pageSize:0,maxWidth:"0"};
@Output('onchange')
private change = new EventEmitter();
@Output('onready')
private ready = new EventEmitter();
private el:HTMLElement;
constructor(el: ElementRef) {
this.el = el.nativeElement;
}
ngOnChanges(changes:any) {
if(this.info && this.info.contentSize && this.info.pageSize){
this.info.pages = Math.ceil(this.info.contentSize/this.info.pageSize);
if(this.info.pages>1){
this.canDisplayPagination = true;
}
this.info.from = 0;
this.info.to = this.info.pageSize-1;
this.info.currentPage = 1;
setTimeout(()=>this.onready(),20);
}
}
public setWidth(width:number){
this.info.maxWidth=width+"px";
}
onready(){this.ready.emit(this);this.change.emit(this.info);}
selectFirst(){
if(this.info.currentPage>1){
this.info.from = 0;
this.info.to = this.info.from+this.info.pageSize-1;
this.info.currentPage = 1;
this.change.emit(this.info);
}
}
selectNext(){
if(this.info.currentPage<this.info.pages){
this.info.from = this.info.to+1;
this.info.to = this.info.from+this.info.pageSize-1;
this.info.currentPage++;
this.change.emit(this.info);
}
}
selectPrev(){
if(this.info.currentPage>1){
this.info.from -= this.info.pageSize;
this.info.to = this.info.from+this.info.pageSize-1;
this.info.currentPage--;
this.change.emit(this.info);
}
}
selectLast(){
if(this.info.currentPage<this.info.pages){
this.info.from = this.info.pageSize*(this.info.pages-1);
this.info.to = this.info.from+this.info.pageSize-1;
this.info.currentPage = this.info.pages;
this.change.emit(this.info);
}
}
changeCurrent(ranger:any){
let v = parseInt(ranger.value);
if(this.info.currentPage<v && v>0 && v<this.info.pages){
this.info.from = v*(this.info.pageSize-1);
this.info.to = this.info.from+this.info.pageSize-1;
this.info.currentPage = v;
this.change.emit(this.info);
}else {
ranger.value = this.info.currentPage;
}
}
changeSize(sizer:any){
let v = parseInt(sizer.value);
if(this.info.contentSize>=v && v>1){
this.info.pageSize = v;
this.info.pages = Math.ceil(this.info.contentSize/v);
this.info.from = 0;
this.info.to = this.info.pageSize-1;
this.info.currentPage = 1;
this.change.emit(this.info);
}else {
sizer.value = this.info.pageSize;
}
}
}
import { Pipe, PipeTransform } from '@angular/core';
var preferredLanguage="en_US";
const keys = {
"en_US": {
"sample.home.title": "Smart Table!!",
"sample.home.description": "Angular 2 fully configurable Smart Table with pagination.",
"sample.home.click.lock": "Click on lock icons to unlock/lock columns",
"sample.home.click.drag": "Drag unlocked columns to re-order them",
"sample.checkbox.compare": "Activate table updater and see Angular2 is as fast as React"
}
};
// need to make the calls everytime language is changed.
// setting pure to false will create a performance problem.
// the best way is to pass in the preffered language.
@Pipe({name:'i18n'})
export class ContentManagementPipe implements PipeTransform{
transform(messageKey: string,args?:any[],lang?:string): any {
return ContentManagementPipe.i18n(messageKey,args,lang);
}
static i18n(messageKey: string,args?:any[],lang?:string): any {
let m = keys[lang ? lang:preferredLanguage][messageKey];
if(m && args && args.length){
for(let i=0;i<args.length;i++){m = m.replace("\{"+i+"\}",args[i])}
}
return (m ? m : messageKey);
}
}
@Pipe({name:'isDefaultLanguage'})
export class ContentManagementLangSetup implements PipeTransform{
transform(langKey: string): any {
if(langKey && langKey.length==5 && langKey.indexOf("_")==2){
preferredLanguage = langKey;
}
return preferredLanguage;
}
}
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name:'format'})
export class FormatPipe implements PipeTransform{
transform(message:any,type:string): any {
let list = type.split(":");
switch(list[0]){
case "CURR" : return this.toCurrency(message,list);
case "NUMB" : return this.toNumber(message,list);
case "DATE" : return this.toDate(message,list);
case "LINK" : return this.toLink(message,list);
case "IMAG" : return this.toImage(message,list);
default: return message;
}
}
toImage(message:any,list:string[]){
let text = message.split("|");
let src = text.length>1 ? text[1]:text[0];
let alt = text.length>1 ? text[0]:"";
return "<img src='"+src+"' alt='"+alt+"' />";
}
toLink(message:any,list:string[]){
let target = list.length && list[1].length ? list[1] : "";
let text = message.split("|");
let src = text.length>1 ? text[1]:text[0];
let title = text.length>1 ? text[0]:"";
return "<a href='"+src+"' target='"+target+"'>"+title+"</a>";
}
toDate(message:any,list:string[]){
let format = list.length && list[1].length ? list[1] : "MM/dd/YYYY";
let date = new Date(message);
return message;//moment().format(format);
}
toNumber(message:any,list:string[]){
let pre = list.length && list[1].length ? parseInt(list[1]) : 0;
return message.toFixed(pre).replace(/./g, function(c:any, i:any, a:any) {
return i && c !== "." && ((a.length - i) % 3 === 0) ? ',' + c : c;
});
}
toCurrency(message:any,list:string[]){
return list[1]+message.toFixed(2).replace(/./g, function(c:any, i:any, a:any) {
return i && c !== "." && ((a.length - i) % 3 === 0) ? ',' + c : c;
});
}
}