hjalmers / angular-generic-table

A generic table for Angular 2+. Generic table uses standard markup for tables ie. table, tr and td elements etc. and has support for expanding rows, global search, filters, sorting, pagination, export to CSV, column clicks, custom column rendering, custom export values.
https://hjalmers.github.io/angular-generic-table/
MIT License
104 stars 55 forks source link

SystemJS integration #56

Open d-damien opened 7 years ago

d-damien commented 7 years ago

How would you include Generic Table in a project using SystemJS ? I can't find the proper map: {} and import instructions. I believe SystemJS is fairly common.

Thanks in advance.

hjalmers commented 7 years ago

When this project started we actually used SystemJS so it should work just fine although I don't have the config need and it has probably changed since we used it. But it would be nice to add it to the docs or maybe move it to a wiki. If and when time permits I might be able to look into it myself but if someone already has implemented it using SystemJs I'de be happy just to update the docs/wiki.

hjalmers commented 7 years ago

For anyone looking at an example based on SystemJS check out this plunker.

gotshoo commented 6 years ago

I checked out the Plunker and tried to setup in my project, but all of the dependencies were coming back as 404. Looks like there is an issue determining the default extension to use.

image

I also tried adding the defaultExtension to my systemjs config.

Any help would be appreciated! Like the simplicity of this data table module.

leonardoheis commented 6 years ago

I have the same problem. Any clue to how to resolve it. I used plunker without success.

image

This is part of my systemjs:

`
System.config({ paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { // our app is within the app folder 'app': 'app', .... '@angular-generic-table/core': 'npm:@angular-generic-table/core/core.module.js', '@angular-generic-table/core/components/gt-checkbox/gt-checkbox.component': 'npm:@angular-generic-table/core/components/gt-checkbox/gt-checkbox.component.js', '@angular-generic-table/column-settings': 'npm:@angular-generic-table/column-settings/column-settings.module.js',

        'ng2-dragula': 'npm:ng2-dragula/bundles/ng2-dragula.umd.js'
    packages: {
        app: {
            defaultExtension: 'js',
            meta: {
                './*.js': {
                    loader: 'systemjs-angular-loader.js'
                }
            }
        },
        rxjs: {
            defaultExtension: 'js'
        },
        '@angular-generic-table/core/components/gt-checkbox/gt-checkbox.component': {
            defaultExtension: 'js'
        }
    }
});`
hjalmers commented 6 years ago

Hmm perhaps something has changed with systemJs or some other package if the plunker isn’t working anymore. If a remember correctly, the example I set up uses the latest version of most dependencies which might have caused it to break. I’ll see if can get a chance to look at it during the weekend:)

leonardoheis commented 6 years ago

Hi, how you doing. Plunker is working, as it, in plunker. These are my systemjs file and the package.json I'm using. Also I'm posting how I using the List (is one of the most complete and versatile list I've seen). I'm trying to use it in a ASP.NET 5 WebApi 2 project.

/**
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
    System.config({
        paths: {
            // paths serve as alias
            'npm:': 'node_modules/'
        },
        // map tells the System loader where to look for things
        map: {
            // our app is within the app folder
            'app': 'app',

            // angular bundles
            '@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/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.js',
            '@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.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/common/http': 'npm:@angular/common/bundles/common-http.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',

            // other libraries
            'rxjs': 'npm:rxjs',
            'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
            'underscore': 'npm:underscore/underscore.js',
            'ng2-avatar': 'npm:ng2-avatar/bundles/ng2-avatar.umd.js',
            'hammerjs': 'npm:hammerjs/hammer.js',
            'tslib': 'npm:tslib/tslib.js',
            'ng2-dragula': 'npm:ng2-dragula/bundles/ng2-dragula.umd.js',
            '@ng-bootstrap/ng-bootstrap': 'npm:@ng-bootstrap/ng-bootstrap/bundles/ng-bootstrap.js',
            '@angular-generic-table/core': 'npm:@angular-generic-table/core/core.module.js'
        },
        // packages tells the System loader how to load when no filename and/or no extension
        packages: {
            app: {
                defaultExtension: 'js',
                meta: {
                    './*.js': {
                        loader: 'systemjs-angular-loader.js'
                    }
                }
            },
            rxjs: {
                defaultExtension: 'js'
            }
        }
    });
})(this);
{
  "name": "mci",
  "version": "1.0.0",
  "description": "MCI package.json from the documentation",
  "scripts": {
    "build": "tsc -p src/",
    "build:watch": "tsc -p src/ -w",
    "build:e2e": "tsc -p e2e/",
    "serve": "lite-server -c=bs-config.json",
    "serve:e2e": "lite-server -c=bs-config.e2e.json",
    "prestart": "npm run build",
    "start": "concurrently \"npm run build:watch\" \"npm run serve\"",
    "pree2e": "npm run build:e2e",
    "e2e": "concurrently \"npm run serve:e2e\" \"npm run protractor\" --kill-others --success first",
    "preprotractor": "webdriver-manager update",
    "protractor": "protractor protractor.config.js",
    "pretest": "npm run build",
    "test": "concurrently \"npm run build:watch\" \"karma start karma.conf.js\"",
    "pretest:once": "npm run build",
    "test:once": "karma start karma.conf.js --single-run",
    "lint": "tslint ./src/**/*.ts -t verbose"
  },
  "keywords": [],
  "author": "MSTech",
  "license": "MIT",
  "dependencies": {
    "@angular/common": "~5.2.2",
    "@angular/compiler": "~5.2.2",
    "@angular/core": "~5.2.2",
    "@angular/forms": "~5.2.2",
    "@angular/http": "~5.2.2",
    "@angular/platform-browser": "~5.2.2",
    "@angular/platform-browser-dynamic": "~5.2.2",
    "@angular/router": "~5.2.2",
    "@angular-generic-table/core": "^4.12.0",
    "@angular-generic-table/column-settings": "^4.12.0",
    "@ng-bootstrap/ng-bootstrap": "^1.0.2",
    "@angular/animations": "6.0.0-beta.8",

    "jquery": "3.3.1",
    "angular-in-memory-web-api": "~0.5.3",
    "systemjs": "~0.20.19",
    "core-js": "^2.5.3",
    "dragula": "^3.7.2",
    "rxjs": "5.5.6",
    "zone.js": "^0.8.20",
    "underscore": "^1.8.3",
    "ng2-avatar": "^2.2.1",
    "hammerjs": "^2.0.8",
    "ng2-table": "^1.3.2",
    "ng2-bootstrap": "^1.6.3",
    "ng2-dragula": "^1.5.0"

  },
  "devDependencies": {
    "concurrently": "^3.5.1",
    "lite-server": "^2.3.0",
    "typescript": "~2.6.2",

    "canonical-path": "0.0.2",
    "tslint": "^5.9.1",
    "lodash": "^4.17.4",
    "jasmine-core": "~2.9.1",
    "karma": "^2.0.0",
    "karma-chrome-launcher": "^2.2.0",
    "karma-cli": "^1.0.1",
    "karma-jasmine": "^1.1.1",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.3.0",
    "rimraf": "^2.6.2",

    "@types/node": "^6.0.46",
    "@types/jasmine": "2.5.36",
    "@types/underscore": "^1.8.8",
    "@types/jquery": "3.3.1",
    "@types/hammerjs": "^2.0.35"
  },
  "repository": {}
}

import { AppComponent } from './app.component'; import { AppRoutingModule } from './app.route'; import { StarterHeaderComponent } from './starter/starter-header/starter-header.component'; import { StarterLeftSideComponent } from './starter/starter-left-side/starter-left-side.component'; import { StarterContentComponent } from './starter/starter-content/starter-content.component'; import { StarterFooterComponent } from './starter/starter-footer/starter-footer.component'; import { StarterControlSidebarComponent } from './starter/starter-control-sidebar/starter-control-sidebar.component'; import { HomeComponent } from "./home/home.component"; import { ContactComponent } from "./contact/contact.component"; import { AboutComponent } from "./about/about.component"; import { ContentHeaderComponent } from "./content-header/content-header.component"; import { PlansListComponent } from "./planslist/planslist.component";

import { UserService } from "./service/userService"; import { CalendarService } from "./service/calendarService"; import { ReportesService } from "./service/reportesService"; import { PagerService } from './service/pagerService'; import { PlansListService } from "./service/planslistService";

import { AvatarModule } from 'ng2-avatar';

import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; /* Import generic table module / import { GenericTableModule, GenericTableComponent, GtConfig } from '@angular-generic-table/core';

@NgModule({ imports: [ BrowserModule, CommonModule, AppRoutingModule, HttpModule, FormsModule, AvatarModule.forRoot(), NgbModule.forRoot(), GenericTableModule, GenericTableComponent ], declarations: [ AppComponent, StarterHeaderComponent, StarterLeftSideComponent, StarterContentComponent, StarterFooterComponent, StarterControlSidebarComponent, HomeComponent, ContactComponent, AboutComponent, ContentHeaderComponent, PlansListComponent ], providers: [ UserService, CalendarService, ReportesService, PagerService, PlansListService ], bootstrap: [ AppComponent ] }) export class AppModule { }

   * planList.component.ts (where I'm implementing the table)

``` typescript
import { Component, Input, Output, EventEmitter, ViewChild, OnInit } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { GenericTableModule, GenericTableComponent, GtConfig, GtRow, GtOptions } from '@angular-generic-table/core';
import 'rxjs/add/operator/map';

import { PlansListService } from "../service/planslistService";

export interface RowData {
    PlanId: number;
    PlanTitle: string;
    DbTasksCount: string;
    PlannerTasksCount: string;
}

@Component({
    selector: 'planslist-app',
    moduleId: module.id,
    templateUrl: "planslist.component.html",
    styles: []
})
export class PlansListComponent implements OnInit {

    @Output() data = new EventEmitter();
    public configObject: GtConfig<any>;
    @ViewChild(GenericTableComponent)
    private myTable: GenericTableComponent<any, any>;
    public showColumnControls = false;
    public selectedRows = 0;

    constructor(private _planslist: PlansListService,
        private http: HttpClient) {

        this.configObject = {
            settings: [{
                    objectKey: 'checkbox',
                    // sort: 'disable'
            }, {
                    objectKey: 'PlanId',
                    visible: true,
                    sort: 'disable',
                    columnOrder: 0,
                    enabled: true
            }, {
                    objectKey: 'PlanTitle',
                    visible: true,
                    sort: 'enable',
                    sortOrder: 0,
                    columnOrder: 1
            }, {
                    objectKey: 'DbTasksCount',
                    visible: true,
                    enabled: true,
                    sort: 'disable',
                    columnOrder: 2,
                    search: false
            }, {
                    objectKey: 'DbTasksCount',
                    visible: true,
                    enabled: true,
                    sort: 'disable',
                    columnOrder: 3,
                    search: false
            }, {
                    objectKey: 'save',
                    columnOrder: 4,
                    sort: 'disable'
            }],
            fields: [{
                    name: '',
                    objectKey: 'checkbox',
                    columnClass: 'text-right',
                    columnComponent: {
                        type: 'checkbox'
                    },
                    value: (row) => this.myTable.isRowSelected(row)
            }, {
                    name: 'Id en Planner',
                    objectKey: 'PlanId',
                    columnClass: 'sort-numeric'
            }, {
                    name: 'Título',
                    objectKey: 'PlanTitle',
                    columnClass: 'sort-string'
            }, {
                    name: 'Cant. Tareas Db',
                    columnClass: 'sort-string',
                    objectKey: 'DbTasksCount'
            }, {
                    name: 'Cant. Tareas Planner',
                    columnClass: 'sort-string',
                    objectKey: 'PlannerTasksCount'
            }, {
                    objectKey: 'save',
                    name: '',
                    value: () => '',
                    columnClass: 'text-right',
                    render: () => '<button type="button" class="btn btn-primary btn-sm">Detalles</button>'
            }],
            data: []
        };   

    }

    public getData = function () {

        // tell generic table instance that we're loading data
        this.myTable ? this.myTable.loading = true : '';

        this._planslist.loadPlansList()
            .subscribe((res: any) => {
                this.configObject.data = res.data;
            }); 
    };

    /** Apply predefined filter using first_name.
     * */
    public applyFilter = function () {
        this.myTable.gtApplyFilter({
            first_name: ['Victor', 'Joe', 'Carol']
        });
    };

    /** Listen for events
     * */
    public trigger = function ($event: any) {
        console.log($event);
        if ($event.value && $event.value.selectedRows) {
            this.selectedRows = $event.value.selectedRows.length;
        }
    };

    ngOnInit() {
        this.getData();
    } 

}

and the html

<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper" style="min-height: 1126px;">
    <!-- Content Header (Page header) -->
    <app-content-header></app-content-header>
    <!-- Main content -->
    <section class="content container-fluid">
        <!-- .row -->
        <div class="row">
            <!-- .col -->
            <div class="col-xs-12">
                <!-- .box -->
                <div class="box">
                    <!-- .box-header -->
                    <div class="box-header">
                        <h3 class="box-title">Lista de Planes en DB</h3>
                    </div>
                    <!-- /.box-header -->
                    <!-- .box-body -->
                    <div class="box-body">
                        <div class="card mb-5">
                            <div class="card-header">Lista de Planes en DB</div>
                            <div class="card-body">
                                <form class="form form-inline mb-4">
                                    <label for="rows" class="form-control-label mr-sm-2">Filas</label>
                                    <select id="rows" class="form-control form-control-sm mr-sm-2 mb-3 mb-sm-0" #rowLength (change)="myTable.changeRowLength(rowLength.value)">
                                        <option value=10>10</option>
                                        <option value=25>25</option>
                                        <option value=50>50</option>
                                        <option value=100>100</option>
                                        <option value=all>Todas</option>
                                    </select>
                                    <input class="form-control form-control-sm mr-sm-2 mb-3 mb-sm-0" #search (keyup)="myTable.gtSearch(search.value)" placeholder="Buscar" />
                                    <div *ngIf="showColumnControls" class="col-12 row mt-xl-2">
                                        <label class="form-control-label mr-sm-2">Visible columns:</label>
                                        <div class="form-check form-check-inline ml-0 ml-sm-2" *ngFor="let column of configObject.settings">
                                            <label class="form-check-label">
                                                <input type="checkbox" name="{{column.objectKey}}" class="form-check-input" [(ngModel)]="column.visible" (change)="myTable.redraw()">
                                                {{configObject.fields | gtProperty:column.objectKey:'name'}}
                                            </label>
                                        </div>
                                    </div>
                                </form>
                                <generic-table [gtClasses]="'table-hover'" #myTable [gtSettings]="configObject.settings" [gtFields]="configObject.fields" [gtData]="configObject.data" [gtTexts]="{loading:'Cargando...', tableInfo: 'Visualizando #recordFrom de #recordTo de un total de #recordsAfterSearch registros.'}"></generic-table> <!--table-sm-->
                                <gt-pagination [gtClasses]="'justify-content-left'" [genericTable]="myTable"></gt-pagination> <!--pagination-sm -->
                            </div>
                            <div class="card-footer" #basicExample>
                                <div class="text-center">
                                    <small><gt-table-info class="form-text text-muted mb-2" [genericTable]="myTable"></gt-table-info></small>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!-- /.box-body -->
                </div>
                <!-- /.box -->
            </div>
            <!-- /.col -->
        </div>
        <!-- /.row -->
    </section>
    <!-- /.content -->
</div>

With this implementation I'm getting the error I showed before. If you need something else in order to simulate the problem, pls let me know.

EDIT: This is the error I'm facing with this configuration:

image

Thanks!!!!

hjalmers commented 6 years ago

Thanks for the code @leonardoheis, I haven't had time to look it through thoroughly yet but did you get it working using some other config or nothing has worked? Have you used a starter template for your project?

hjalmers commented 6 years ago

@leonardoheis I've published a new version (v4.13.0) using ng-packagr which hopefully should have solved this issue, feel free to give it a try and let me know if it works so that I can update the docs and close this issue:)