Compare commits

..

No commits in common. "develop" and "production" have entirely different histories.

31 changed files with 8479 additions and 506 deletions

46
.circleci/config.yml Normal file
View File

@ -0,0 +1,46 @@
version: 2
jobs:
build:
docker:
- image: circleci/node:10.4-browsers
working_directory: ~/repo
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
- v1-dependencies-
- run:
name: Install
command: yarn
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
- run:
name: Build
command: yarn build-datatable
- run:
name: Copy README and LICENSE
command: |
cp LICENSE dist/ng-datatable/
cp README.md dist/ng-datatable/
- store_artifacts:
path: dist/ng-datatable
- deploy:
command: |
echo "${CIRCLE_BRANCH}"
if [ "${CIRCLE_BRANCH}" == "production" ]; then
yarn ci-publish
else
echo "Only the production branch is published"
fi

View File

@ -4,7 +4,7 @@ root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

View File

@ -1,41 +0,0 @@
name: Build
run-name: Build
on:
push:
jobs:
build:
name: Build NPM Project
runs-on: ubuntu-latest
container: node:8
steps:
- name: Clone Repository
uses: ztimson/actions/clone@develop
- name: Install Dependencies
run: npm i
- name: Build Project
run: npm run build
- name: Upload to Registry
uses: ztimson/actions/npm/publish@develop
tag:
name: Tag Version
needs: build
if: ${{github.ref_name}} == develop
runs-on: ubuntu-latest
container: node:8
steps:
- name: Clone Repository
uses: ztimson/actions/clone@develop
- name: Get Version Number
run: echo "VERSION=$(cat package.json | grep version | grep -Eo ':.+' | grep -Eo '[[:alnum:]\.\/\-]+')" >> $GITHUB_ENV
- name: Tag Version
uses: ztimson/actions/tag@develop
with:
tag: ${{env.VERSION}}

102
README.md
View File

@ -1,52 +1,8 @@
<!-- Header -->
<div id="top" align="center">
<br />
# ng-datatable
<!-- Logo -->
<img src="https://git.zakscode.com/repo-avatars/56e7adede041749f5df1d8b88b334e8c4cac38d7a4a574ccb42a624c52a35624" alt="Logo" width="200" height="200">
<!-- Title -->
### ng-datatable
<!-- Description -->
**Deprecated:** Angular Table Building Library
<!-- Repo badges -->
[![Version](https://img.shields.io/badge/dynamic/json.svg?label=Version&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/ng-datatable/tags&query=$[0].name)](https://git.zakscode.com/ztimson/ng-datatable/tags)
[![Pull Requests](https://img.shields.io/badge/dynamic/json.svg?label=Pull%20Requests&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/ng-datatable&query=open_pr_counter)](https://git.zakscode.com/ztimson/ng-datatable/pulls)
[![Issues](https://img.shields.io/badge/dynamic/json.svg?label=Issues&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/ng-datatable&query=open_issues_count)](https://git.zakscode.com/ztimson/ng-datatable/issues)
<!-- Links -->
---
<div>
<a href="https://git.zakscode.com/ztimson/ng-datatable/releases" target="_blank">Release Notes</a>
<a href="https://git.zakscode.com/ztimson/ng-datatable/issues/new?template=.github%2fissue_template%2fbug.md" target="_blank">Report a Bug</a>
<a href="https://git.zakscode.com/ztimson/ng-datatable/issues/new?template=.github%2fissue_template%2fenhancement.md" target="_blank">Request a Feature</a>
</div>
---
</div>
## Table of Contents
- [ng-datatable](#top)
- [About](#about)
- [Built With](#built-with)
- [Setup](#setup)
- [Production](#production)
- [Development](#development)
- [Documentation](#documentation)
- [NgDatatableComponent](#ngdatatablecomponent)
- [Column](#column)
- [License](#license)
## About
**Deprecated**
A lightweight, feature rich table to display data. It is built with twitter bootstrap in mind so it will be automatically styled if you have the css included but its simple table structure makes it easy to style.
[![CircleCI](https://circleci.com/gh/ztimson/ng-datatable/tree/master.svg?style=svg)](https://circleci.com/gh/ztimson/ng-datatable/tree/master)
A lightweight, feature rich table to display data. It is built with twitter bootstrap in mind but its simple table structor makes it easy to style.
Features:
@ -60,25 +16,13 @@ Features:
- Mobile column hiding
- Checkboxes
[View on NPM](https://www.npmjs.com/package/@ztimson/ng-datatable)
### Built With
[![Angular](https://img.shields.io/badge/Angular-DD0031?style=for-the-badge&logo=angular)](https://angular.io/)
[![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white)](https://typescriptlang.org/)
[View the demo here](https://stackblitz.com/edit/angular-rzq6xm)
## Setup
## Installing
<details>
<summary>
<h3 id="production" style="display: inline">
Production
</h3>
</summary>
#### Prerequisites
- [Node.js](https://nodejs.org/en/download)
#### Instructions
1. Install package `npm install @ztimson/ng-datatable --save`
2. Import into module
@ -100,26 +44,8 @@ export class AppModule { }
```HTML
<ng-datatable [columns]="columns" [data]="data"></ng-datatable>
```
</details>
<details>
<summary>
<h3 id="development" style="display: inline">
Development
</h3>
</summary>
#### Prerequisites
- [Node.js](https://nodejs.org/en/download)
#### Instructions
1. Install the dependencies: `npm install`
2. Start the Angular server: `npm run start`
3. Open [http://localhost:4200](http://localhost:4200)
</details>
## Documentation
## API
### NgDatatableComponent
@ -138,14 +64,12 @@ Selector: `ng-datatable`
| @Input() pageLength: number | Number of rows per page. Default 20 |
| @Input() page: number | Current page |
| @Input() paginate: boolean | Paginate rows or display all at once. Default true |
| @Input() paginateCssClass: string | Class added to the paginator |
| @Input() paginateCssClass: string | Class added to the paginator
| @Input() selectionMode: null/'single'/'multi' | Allow selecting none, single or multiple rows at once |
| @Input() showCheckbox: boolean | Show checkbox' for mass selecting |
| @Input() tableLayout: 'auto'/'fixed' | CSS table layout. Defaults to 'auto' |
| @Output() filterChanged: EventEmitter<(a, b) => 1/0/-1[]> | Applied filters |
| @Output() finished: EventEmitter<any[]> | Emits when finished processing data |
| @Output() pageChanged: EventEmitter<number> | New page |
| @Output() processing: EventEmitter<any[]> | Emits when processing begins |
| @Output() selectionChanged: EventEmitter<any[]> | Selected rows |
| pagedData: any[] | Array of rows on current page after sorting and filtering |
| processedData: any[] | Array of remaining rows after sorting and filtering |
@ -181,10 +105,6 @@ Clear filters being applied to. Update can be set to false to prevent instant fi
Clear all selected rows.
#### refresh()
Refreshes the grid
##### selectAll()
Select all rows. Ignores pagination but not filtering.
@ -224,9 +144,3 @@ Exported As: `Column`
| sortFn: (a, b) => 1/0/-1 | Custom function to sort rows by |
| template: TemplateRef<any> | Template to render row with |
| width: number/string | CSS width property |
## License
Copyright © 2023 Zakary Timson | Available under the Apache 2.0 License
See the [license](./LICENSE) for more information.

View File

@ -17,8 +17,9 @@
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.json",
"tsConfig": "src/tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
@ -56,6 +57,63 @@
"browserTarget": "Sandbox:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "Sandbox:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js",
"styles": [
"styles.css"
],
"scripts": [],
"assets": [
"src/favicon.ico",
"src/assets"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"Sandbox-e2e": {
"root": "e2e/",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "Sandbox:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": "e2e/tsconfig.e2e.json",
"exclude": [
"**/node_modules/**"
]
}
}
}
},
@ -76,6 +134,26 @@
"project": "projects/ng-datatable/ng-package.prod.json"
}
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/ng-datatable/src/test.ts",
"tsConfig": "projects/ng-datatable/tsconfig.spec.json",
"karmaConfig": "projects/ng-datatable/karma.conf.js"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/ng-datatable/tsconfig.lib.json",
"projects/ng-datatable/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}

28
e2e/protractor.conf.js Normal file
View File

@ -0,0 +1,28 @@
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.e2e.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};

14
e2e/src/app.e2e-spec.ts Normal file
View File

@ -0,0 +1,14 @@
import { AppPage } from './app.po';
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Welcome to app!');
});
});

11
e2e/src/app.po.ts Normal file
View File

@ -0,0 +1,11 @@
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get('/');
}
getParagraphText() {
return element(by.css('app-root h1')).getText();
}
}

13
e2e/tsconfig.e2e.json Normal file
View File

@ -0,0 +1,13 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}

View File

@ -1,11 +1,17 @@
{
"name": "ng-datatable",
"version": "1.0.0",
"name": "sandbox",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build ng-datatable --prod"
"build": "ng build",
"build-datatable": "ng build ng-datatable --prod",
"ci-publish": "cd dist/ng-datatable && ci-publish",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^6.0.0",
"@angular/common": "^6.0.0",

View File

@ -1,6 +1,6 @@
{
"name": "@ztimson/ng-datatable",
"version": "1.11.7",
"version": "1.5.2",
"homepage": "https://github.com/ztimson/ng-datatable",
"license": "Apache-2.0",
"author": {

View File

@ -1,9 +1,7 @@
import {TemplateRef} from "@angular/core";
export interface Column {
aggregate?: (rows: any[]) => any;
cssClass?: string; // CSS to add to column
canSelect?: boolean;
hide?: boolean; // Hide column
hideMobile?: boolean; // Hide column on mobile
initialSort?: 'asc' | 'desc'; // Sort this column initially

View File

@ -1,4 +1,4 @@
<table [class]="cssClass + ' ngdt'" [style.table-layout]="tableLayout">
<table [class]="cssClass" [style.table-layout]="tableLayout">
<colgroup>
<col *ngIf="showCheckbox && selectionMode !== null" width="30px">
<col *ngIf="expandedTemplate" width="30px">
@ -6,15 +6,15 @@
<col *ngIf="c.hide !== true && !(c.hideMobile === true && width < mobileBreakpoint)" span="1" [width]="_convertWidth(c.width)">
</ng-container>
</colgroup>
<thead class="ngdt-header">
<thead>
<tr>
<th *ngIf="showCheckbox && selectionMode !== null" class="ngdt-checkall">
<th *ngIf="showCheckbox && selectionMode !== null">
<input *ngIf="selectionMode == 'multi'" type="checkbox" [checked]="processedData.length == selectedRows.size"
(change)="$event.target.checked ? selectAll() : clearSelected()"/>
</th>
<th *ngIf="expandedTemplate"></th>
<ng-container *ngFor="let c of columns; let i = index">
<th *ngIf="c.hide !== true && !(c.hideMobile === true && width < mobileBreakpoint)" [class]="c.cssClass + ' ngdt-column'"
<th *ngIf="c.hide !== true && !(c.hideMobile === true && width < mobileBreakpoint)" [class]="c.cssClass"
style="cursor: pointer" (click)="sort(i)">
<span *ngIf="sortedColumn == i && !sortedDesc">&uarr;</span>
<span *ngIf="sortedColumn == i && sortedDesc">&darr;</span>
@ -23,54 +23,35 @@
</ng-container>
</tr>
</thead>
<tbody class="ngdt-body">
<tbody>
<ng-container *ngFor="let row of pagedData; let i = index">
<tr class="ngdt-row" [ngClass]="{'active': selectedRows.has(i)}">
<td *ngIf="showCheckbox && selectionMode !== null" class="ngdt-checkbox" (click)="updateSelected(i)">
<input type="checkbox" [checked]="selectedRows.has(i)"/>
</td>
<td *ngIf="expandedTemplate" class="ngdt-expand" (click)="updateSelected(i)">
<span *ngIf="!selectedRows.has(i)">&#9658;</span>
<tr [ngClass]="{'active': selectedRows.has(i)}" (click)="updateSelected(i)">
<td *ngIf="showCheckbox && selectionMode !== null"><input type="checkbox" [checked]="selectedRows.has(i)"/></td>
<td *ngIf="expandedTemplate">
<span *ngIf="!selectedRows.has(i)">&#9698;</span>
<span *ngIf="selectedRows.has(i)">&#9660;</span>
</td>
<ng-container *ngFor="let c of columns">
<td *ngIf="c.hide !== true && !(c.hideMobile === true && width < mobileBreakpoint)" class="ngdt-cell" (click)="updateSelected(i, c)">
<td *ngIf="c.hide !== true && !(c.hideMobile === true && width < mobileBreakpoint)">
<ng-template #defaultTemplate let-value="value">{{value}}</ng-template>
<ng-template [ngTemplateOutlet]="c.template || defaultTemplate"
[ngTemplateOutletContext]="{object: row, key: c.property, value: _dotNotation(row, c.property)}">
[ngTemplateOutletContext]="{object: row, value: _dotNotation(row, c.property)}">
</ng-template>
</td>
</ng-container>
</tr>
<tr *ngIf="expandedTemplate && selectedRows.has(i)" class="ngdt-detail">
<tr *ngIf="expandedTemplate && selectedRows.has(i)">
<td [attr.colspan]="columns.length + (showCheckbox ? 1 : 0) + (expandedTemplate ? 1 : 0)">
<ng-template [ngTemplateOutlet]="expandedTemplate" [ngTemplateOutletContext]="{object: row}"></ng-template>
</td>
</tr>
</ng-container>
<tr class="ngdt-total">
<td *ngIf="showCheckbox && selectionMode !== null" class="ngdt-checkbox"></td>
<td *ngIf="expandedTemplate" class="ngdt-expand"></td>
<ng-container *ngFor="let c of columns">
<td class="ngdt-cell">{{aggregate(c)}}</td>
</ng-container>
</tr>
</tbody>
</table>
<nav *ngIf="paginate" [class]="paginateCssClass + 'ngdt-paginator'" aria-label="Page navigation">
<nav *ngIf="paginate" [class]="paginateCssClass" aria-label="Page navigation">
<ul class="pagination">
<li class="page-item ngdt-first" [ngClass]="{'disabled': page <= 1}" (click)="changePage(1)"><a class="page-link">First</a></li>
<li class="page-item ngdt-next" [ngClass]="{'disabled': page <= 1}" (click)="changePage(page - 1)"><a class="page-link">Previous</a></li>
<ng-container *ngFor="let i of pages;">
<li *ngIf="i > page - 3 && i < page + 3" class="page-item ngdt-page" [ngClass]="{'active': page == i}">
<a class="page-link" (click)="changePage(i)">
<span *ngIf="i == page - 2 && i > 1">...</span>
{{i}}
<span *ngIf="i == page + 2 && i != pages.length">...</span>
</a>
</li>
</ng-container>
<li class="page-item ngdt-previous" [ngClass]="{'disabled': page >= pages.length}" (click)="changePage(page + 1)"><a class="page-link">Next</a></li>
<li class="page-item ngdt-last" [ngClass]="{'disabled': page == pages.length}" (click)="changePage(pages.length)"><a class="page-link">Last</a></li>
<li class="page-item" [ngClass]="{'disabled': page <= 1}" (click)="changePage(page - 1)"><a class="page-link">Previous</a></li>
<li *ngFor="let i of pages" class="page-item" [ngClass]="{'active': page == i}"><a class="page-link" (click)="changePage(i)">{{i}}</a></li>
<li class="page-item" [ngClass]="{'disabled': page >= pages.length}" (click)="changePage(page + 1)"><a class="page-link">Next</a></li>
</ul>
</nav>

View File

@ -3,8 +3,7 @@ import {Column} from './column';
@Component({
selector: 'ng-datatable',
templateUrl: 'ng-datatable.component.html',
styles: ['.ngdt-expand {font-family: sans-serif;}']
templateUrl: 'ng-datatable.component.html'
})
export class NgDatatableComponent implements OnInit {
// Inputs ============================================================================================================
@ -22,37 +21,30 @@ export class NgDatatableComponent implements OnInit {
// Outputs ===========================================================================================================
@Output() filterChanged = new EventEmitter<any[]>(); // Output when filters change
@Output() finished = new EventEmitter<any[]>(); // Fired after processing is finished
@Output() pageChanged = new EventEmitter<number>(); // Output when page is changed
@Output() processing = new EventEmitter<any[]>(); // Fires when grid begins to process
@Output() selectionChanged = new EventEmitter<any[]>(); // Output when selected rows changes
// Properties ========================================================================================================
filters: ((el?: any, i?: number, arr?: any[]) => boolean)[] = []; // Array of process functions to apply to data
pages: number[] = []; // Array of possible pages
pagedData: any[] = []; // The data for the current
processedData: any[] = []; // rows left after filtering
processedData: any[]; // rows left after filtering
selectedRows = new Set<number>(); // Keep track of selected rows
sortedColumn: number; // Column currently being sorted
sortedDesc = false; // Is the sorted column being sorted in ascending or descending order
width = window.innerWidth; // Width of the screen. Used for hiding mobile columns
// Fields ============================================================================================================
get count(): number {
return this.processedData ? this.processedData.length : 0;
} // Number of rows after filtering
get count(): number { return this.processedData.length; } // Number of rows after filtering
private _data: any[] = []; // Original data entered into table
get data(): any[] {
return this.processedData;
} // Return the processed data
get data(): any[] { return this.processedData; } // Return the processed data
@Input() set data(data: any[]) {
this._data = data;
this.refresh();
this._process();
}
// ===================================================================================================================
constructor() {
}
constructor() { }
ngOnInit() {
// Look through columns for an initial sort
@ -65,6 +57,31 @@ export class NgDatatableComponent implements OnInit {
}
// Helpers ===========================================================================================================
private _process() {
this.clearSelected();
this.processedData = this._data;
this.filters.forEach(f => this.processedData = this.processedData.filter(f));
if(this.sortedColumn != null) {
if (this.columns[this.sortedColumn].sortFn) {
this.processedData = this.processedData.sort(this.columns[this.sortedColumn].sortFn);
} else {
this.processedData = this.processedData.sort((a: any, b: any) => {
if (a[this.columns[this.sortedColumn].property] > b[this.columns[this.sortedColumn].property]) return 1;
if (a[this.columns[this.sortedColumn].property] < b[this.columns[this.sortedColumn].property]) return -1;
return 0;
});
}
if (this.sortedDesc) this.processedData = this.processedData.reverse();
}
if(this.paginate) {
this.pages = Array(Math.ceil(this.processedData.length / this.pageLength)).fill(0).map((ignore, i) => i + 1);
this.pagedData = this.processedData.filter((ignore, i) => i >= (this.page - 1) * this.pageLength && i < this.page * this.pageLength);
} else {
this.pagedData = this.processedData;
}
}
_convertWidth(width) {
if(typeof width == 'number') return `${width}px`;
return width;
@ -76,25 +93,20 @@ export class NgDatatableComponent implements OnInit {
addFilter(...filters: ((row?: any, index?: number, arr?: any[]) => boolean)[]) {
this.filters = this.filters.concat(filters);
this.refresh();
this._process();
this.filterChanged.emit(this.filters);
}
aggregate(col: Column) {
if (!col.aggregate) return '';
return col.aggregate(this.processedData.map(row => this._dotNotation(row, col.property)));
}
changePage(page: number) {
if(!this.paginate || page < 1 || page > this.pages.length) return;
this.page = page;
this.refresh();
this._process();
this.pageChanged.emit(this.page);
}
clearFilters(update=true) {
this.filters = [];
if (update) this.refresh();
if(update) this._process();
this.filterChanged.emit(this.filters);
}
@ -105,38 +117,7 @@ export class NgDatatableComponent implements OnInit {
}
@HostListener('window:resize', ['$event'])
onResize(event) {
this.width = event.target.innerWidth;
}
refresh() {
this.processing.emit(this.processedData);
this.clearSelected();
this.processedData = this._data;
this.filters.forEach(f => this.processedData = this.processedData.filter(f));
if (this.sortedColumn != null && this.processedData) {
if (this.columns[this.sortedColumn].sortFn) {
this.processedData = this.processedData.sort(this.columns[this.sortedColumn].sortFn);
} else {
this.processedData = this.processedData.sort((a: any, b: any) => {
if (this._dotNotation(a, this.columns[this.sortedColumn].property) > this._dotNotation(b, this.columns[this.sortedColumn].property)) return 1;
if (this._dotNotation(a, this.columns[this.sortedColumn].property) < this._dotNotation(b, this.columns[this.sortedColumn].property)) return -1;
return 0;
});
}
if (this.sortedDesc) this.processedData = this.processedData.reverse();
}
if (this.paginate && this.processedData) {
this.pages = Array(Math.ceil(this.processedData.length / this.pageLength)).fill(0).map((ignore, i) => i + 1);
if (!this.page) this.page = 1;
if (this.page > this.pages.length) this.page = this.pages.length;
this.pagedData = this.processedData.filter((ignore, i) => i >= (this.page - 1) * this.pageLength && i < this.page * this.pageLength);
} else {
this.pagedData = this.processedData;
}
this.finished.emit(this.processedData);
}
onResize(event) { this.width = event.target.innerWidth; }
selectAll() {
this.processedData.forEach((ignore, i) => this.selectedRows.add(i));
@ -156,12 +137,11 @@ export class NgDatatableComponent implements OnInit {
this.sortedDesc = desc;
// Preform sort
this.refresh();
this._process();
}
updateSelected(index: number, column?: Column) {
updateSelected(index: number) {
if (this.selectionMode == null) return;
if (column && column.canSelect === false) return;
if (this.selectionMode == 'single') {
let alreadySelected = this.selectedRows.has(index);

View File

@ -25,5 +25,8 @@
"strictInjectionParameters": true,
"flatModuleId": "AUTOGENERATED",
"flatModuleOutFile": "AUTOGENERATED"
}
},
"exclude": [
"**/*.spec.ts"
]
}

View File

View File

@ -13,7 +13,7 @@ Checkbox
<input placeholder="Search" (keyup)="search.next($event.target.value)">
<br> Selected: {{table.selectedRows.size}}/{{table.processedData.length}}
<ng-datatable #table [cssClass]="tableCSS" [columns]="columns" [data]="data" [expandedTemplate]="expandable ? expanded : null"
[showCheckbox]="checkbox" [paginate]="true" [selectionMode]="selectionMode == 'None' ? null : selectionMode" (rowSelected)="log($event)">
[showCheckbox]="checkbox" [paginate]="false" [selectionMode]="selectionMode == 'None' ? null : selectionMode" (rowSelected)="log($event)">
<ng-template #expanded let-object="object">
Hello {{object.firstName}} {{object.lastName}}, How are you today?
<span *ngIf="object.age < 18">I can see that you are under age.</span>

View File

@ -0,0 +1,27 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
}));
});

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,9 @@
import {NgModule} from '@angular/core';
import {FormsModule} from "@angular/forms";
import { BrowserModule } from '@angular/platform-browser';
import {NgDatatableModule} from "../../projects/ng-datatable/src/lib/ng-datatable.module";
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import {FormsModule} from "@angular/forms";
import {NgDatatableModule} from "../../projects/ng-datatable/src/lib/ng-datatable.module";
@NgModule({
declarations: [

0
src/assets/.gitkeep Normal file
View File

View File

@ -1,3 +1,15 @@
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.
export const environment = {
production: false
};
/*
* In development mode, to ignore zone related error stack frames such as
* `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can
* import the following file, but please comment it out in production mode
* because it will have performance impact when throw error
*/
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.

BIN
src/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

31
src/karma.conf.js Normal file
View File

@ -0,0 +1,31 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, '../coverage'),
reports: ['html', 'lcovonly'],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};

20
src/test.ts Normal file
View File

@ -0,0 +1,20 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: any;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

12
src/tsconfig.app.json Normal file
View File

@ -0,0 +1,12 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "es2015",
"types": []
},
"exclude": [
"src/test.ts",
"**/*.spec.ts"
]
}

19
src/tsconfig.spec.json Normal file
View File

@ -0,0 +1,19 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/spec",
"module": "commonjs",
"types": [
"jasmine",
"node"
]
},
"files": [
"test.ts",
"polyfills.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

17
src/tslint.json Normal file
View File

@ -0,0 +1,17 @@
{
"extends": "../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"app",
"camelCase"
],
"component-selector": [
true,
"element",
"app",
"kebab-case"
]
}
}

View File

@ -2,8 +2,7 @@
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "../out-tsc/app",
"module": "es2015",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",

130
tslint.json Normal file
View File

@ -0,0 +1,130 @@
{
"rulesDirectory": [
"node_modules/codelyzer"
],
"rules": {
"arrow-return-shorthand": true,
"callable-types": true,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"deprecation": {
"severity": "warn"
},
"eofline": true,
"forin": true,
"import-blacklist": [
true,
"rxjs/Rx"
],
"import-spacing": true,
"indent": [
true,
"spaces"
],
"interface-over-type-literal": true,
"label-position": true,
"max-line-length": [
true,
140
],
"member-access": false,
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-arg": true,
"no-bitwise": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-super": true,
"no-empty": false,
"no-empty-interface": true,
"no-eval": true,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-misused-new": true,
"no-non-null-assertion": true,
"no-shadowed-variable": true,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unnecessary-initializer": true,
"no-unused-expression": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"prefer-const": true,
"quotemark": [
true,
"single"
],
"radix": true,
"semicolon": [
true,
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"unified-signatures": true,
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],
"no-output-on-prefix": true,
"use-input-property-decorator": true,
"use-output-property-decorator": true,
"use-host-property-decorator": true,
"no-input-rename": true,
"no-output-rename": true,
"use-life-cycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
"directive-class-suffix": true
}
}

7689
yarn.lock Normal file

File diff suppressed because it is too large Load Diff