+<div class="eg-grid-row eg-grid-body-row"
+ [ngClass]="{'eg-grid-row-selected': selector[idx]}"
+ *ngFor="let row of currentPage(); let idx = index">
+
+ <div class="eg-grid-cell eg-grid-checkbox-cell">
+ <input type='checkbox' [(ngModel)]="selector[idx]">
+ </div>
+ <div class="eg-grid-cell eg-grid-body-cell" [ngStyle]="{flex:col.flex}"
+ *ngFor="let col of columnSet.displayColumns()">
+ {{col.displayValue(row)}}
+ </div>
+
+<div>
import {Component, Input, OnInit, Host, TemplateRef} from '@angular/core';
-import {EgGridColumn} from './grid-column';
+import {EgGridColumn, EgGridColumnSet} from './grid-column';
import {EgGridDataSource} from './grid-data-source';
+import {Pager} from '@eg/share/util/pager';
@Component({
selector: 'eg-grid-body',
export class EgGridBodyComponent implements OnInit {
@Input() dataSource: EgGridDataSource;
- @Input() columns: EgGridColumn[];
+ @Input() columnSet: EgGridColumnSet;
+ @Input() pager: Pager;
+ @Input() selector: {[idx:number] : boolean};
ngOnInit() {
}
+
+ currentPage(): any[] {
+ if (!this.dataSource.data) return [];
+ return this.dataSource.data.slice(this.pager.offset, this.pager.limit);
+ }
}
@Input() name: string;
@Input() path: string;
@Input() label: string;
- @Input() flex: number = 1;
- @Input() visible: boolean = false;
+ @Input() flex: number;
+ @Input() hidden: boolean = false;
@Input() cellTemplate: TemplateRef<any>;
- @Input() grid: EgGridComponent;
+
+ // get a reference to our container grid.
+ constructor(@Host() private grid: EgGridComponent) {}
ngOnInit() {
let col = new EgGridColumn();
col.name = this.name;
col.path = this.path;
- col.label = this.label;
- col.flex = this.flex;
- col.visible = this.visible;
+ col.label = this.label || this.name;
+ col.flex = this.flex || 2;
+ col.hidden = this.hidden;
col.cellTemplate = this.cellTemplate;
- this.grid.columns.push(col);
+ this.grid.columnSet.add(col);
}
}
import {TemplateRef} from '@angular/core';
+import {EgIdlService} from '@eg/core/idl.service';
export class EgGridColumn {
name: string;
path: string;
label: string;
- flex: number = 1;
- visible: boolean = false;
+ flex: number;
+ hidden: boolean;
cellTemplate: TemplateRef<any>;
displayValue(row: any): string {
if (row[this.name] === undefined || row[this.name] === null)
return '';
- if (typeof row[this.name] == 'function')
- return row[this.name]()+'';
+ if (typeof row[this.name] == 'function') {
+ let val = row[this.name]();
+ if (val === undefined || val === null) return '';
+ return val+'';
+ }
return row[this.name]+'';
}
+}
+
+export class EgGridColumnSet {
+
+ columns: EgGridColumn[];
+
+ constructor() {
+ this.columns = [];
+ }
+ add(col: EgGridColumn) {
+ this.columns.push(col);
+ }
+
+ displayColumns(): EgGridColumn[] {
+ return this.columns.filter(c => !c.hidden);
+ }
}
+
+export class EgGridIdlColumnSet extends EgGridColumnSet {
+ idl: EgIdlService;
+ idlClass: string;
+
+ constructor(idl: EgIdlService, idlClass: string) {
+ super();
+ this.idl = idl;
+ this.idlClass = idlClass;
+ this.generateColumns();
+ }
+
+ generateColumns() {
+ this.idl.classes[this.idlClass].fields.forEach(field => {
+ if (field.virtual) return;
+ let col = new EgGridColumn();
+ col.name = field.name;
+ col.label = field.label || field.name;
+ this.add(col);
+ });
+ }
+}
+
+
-
+//import {Observable} from 'rxjs/Rx';
export class EgGridDataSource {
data: any[] = [];
+ sortSpec: any[] = [];
+
// Do we know how many items we have in total?
indeterminate: boolean
+ applySort() {
+ }
}
<div class="eg-grid-row eg-grid-header-row">
- <div *ngFor="let col of columns">{{col.label}}</div>
+ <div class="eg-grid-cell eg-grid-header-cell eg-grid-checkbox-cell">
+ <input type='checkbox'> <!-- add click handlers ; shared selector mod -->
+ </div>
+
+ <div *ngFor="let col of columnSet.displayColumns()"
+ class="eg-grid-cell eg-grid-header-cell" [ngStyle]="{flex:col.flex}">
+ {{col.label}}
+ </div>
</div>
import {Component, Input, OnInit} from '@angular/core';
-import {EgGridColumn} from './grid-column';
+import {EgGridColumn, EgGridColumnSet} from './grid-column';
@Component({
selector: 'eg-grid-header',
export class EgGridHeaderComponent implements OnInit {
- @Input() columns: EgGridColumn[];
+ @Input() columnSet: EgGridColumnSet;
+ @Input() selected: {[idx:number] : boolean};
constructor() {}
+.eg-grid {
+ width: 100%;
+ color: rgba(0,0,0,.87);
+}
+
.eg-grid-row {
display: flex;
+ border-bottom: 1px solid rgba(0,0,0,.12);
+ padding-left: 10px;
+ padding-right: 10px;
}
.eg-grid-header-row {
}
+.eg-grid-body-row {
+}
+
.eg-grid-header-cell {
font-weight: bold;
}
.eg-grid-cell {
+ flex: 1; /* applied per column */
+ padding: 6px;
}
+.eg-grid-body-cell {
+}
+
+
<div class="eg-grid">
<!--
- <eg-grid-toolbar [columns]="columns"></eg-grid-toolbar>
- -->
- <eg-grid-header [columns]="columns"></eg-grid-header>
- <!--
- <eg-grid-body [columns]="columns" [dataSource]="dataSource"></eg-grid-body>
+ <eg-grid-toolbar [columnSet]="columnSet"></eg-grid-toolbar>
-->
+ <eg-grid-header [columnSet]="columnSet"></eg-grid-header>
+ <eg-grid-body
+ [columnSet]="columnSet"
+ [dataSource]="dataSource"
+ [pager]="pager"
+ [selector]="selector">
+ </eg-grid-body>
</div>
-import {Component, Input, OnInit} from '@angular/core';
+import {Component, Input, OnInit, ViewEncapsulation} from '@angular/core';
import {EgGridDataSource} from './grid-data-source';
-import {EgGridColumn} from './grid-column';
+import {EgGridColumn, EgGridColumnSet, EgGridIdlColumnSet} from './grid-column';
+import {EgIdlService} from '@eg/core/idl.service';
+import {Pager} from '@eg/share/util/pager';
@Component({
selector: 'eg-grid',
templateUrl: './grid.component.html',
- styleUrls: ['./grid.component.css']
+ styleUrls: ['grid.component.css'],
+ // share grid css globally once imported.
+ encapsulation: ViewEncapsulation.None
})
export class EgGridComponent implements OnInit {
@Input() dataSource: EgGridDataSource;
- columns: EgGridColumn[];
+ @Input() idlClass: string;
+
+ pager: Pager;
+ columnSet: EgGridColumnSet;
+ selector: {[idx:number] : boolean};
- constructor() {
- this.columns = [];
+ constructor(private idl: EgIdlService) {
+ this.pager = new Pager();
+ this.pager.limit = 10; // TODO
+ this.selector = {};
}
ngOnInit() {
+ if (this.idlClass) {
+ this.columnSet = new EgGridIdlColumnSet(this.idl, this.idlClass);
+ } else {
+ this.columnSet = new EgGridColumnSet();
+ }
}
}
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
+import {FormsModule} from '@angular/forms';
import {EgGridComponent} from './grid.component';
import {EgGridColumnComponent} from './grid-column.component';
import {EgGridHeaderComponent} from './grid-header.component';
EgGridBodyComponent
],
imports: [
- CommonModule
+ CommonModule,
+ FormsModule
],
exports: [
// public components
<!-- grid stuff -->
-<eg-grid #testGrid [dataSource]="gridDataSource"></eg-grid>
-<eg-grid-column [grid]="testGrid" name="name" label="Name" i18n-label></eg-grid-column>
+
+<eg-grid #cbtGrid idlClass="cbt" [dataSource]="billingTypes">
+</eg-grid>
+
+<!--
+<eg-grid #testGrid [dataSource]="gridDataSource">
+ <eg-grid-column name="name" label="Name" i18n-label></eg-grid-column>
+ <eg-grid-column name="state" label="State" i18n-label></eg-grid-column>
+</eg-grid>
+-->
+
+
+
+
+
import {EgStringService} from '@eg/share/string/string.service';
import {Observable} from 'rxjs/Rx';
import {EgGridDataSource} from '@eg/share/grid/grid-data-source';
+import {EgIdlService, EgIdlObject} from '@eg/core/idl.service';
@Component({
templateUrl: 'sandbox.component.html'
gridDataSource: EgGridDataSource = new EgGridDataSource();
+ billingTypes: EgGridDataSource = new EgGridDataSource();
+
testStr: string;
@Input() set testString(str: string) {
name: string = 'Jane';
constructor(
+ private idl: EgIdlService,
private strings: EgStringService,
private toast: EgToastService
) {}
ngOnInit() {
this.gridDataSource.data = [
- {name: 'Jane'},
- {name: 'Al'},
- {name: 'The Tick'}
+ {name: 'Jane', state: 'AZ'},
+ {name: 'Al', state: 'CA'},
+ {name: 'The Tick', state: 'TX'}
];
+
+ let bt1 = this.idl.create('cbt');
+ let bt2 = this.idl.create('cbt');
+ bt1.id = 12;
+ bt1.name = 'BT1';
+ bt2.id = 47;
+ bt1.name = 'BT2';
+ this.billingTypes.data = [bt1, bt2];
}
showProgress() {
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- link to bootstrap manually for the time being. With
ng-bootstrap, we only need the CSS, not the JS -->
+ <!--
<link rel="stylesheet" crossorigin="anonymous"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm">
+ -->
+ <!-- lnk to local copy for dev on the go -->
+ <link rel="stylesheet" crossorigin="anonymous"
+ href="/css/bootstrap.min.css"
</head>
<body>
<eg-root></eg-root>