├── .gitignore
├── .travis.yml
├── README.md
├── angular.json
├── package.json
├── src
├── app
│ ├── app-routing.module.ts
│ ├── app.component.css
│ ├── app.component.html
│ ├── app.component.ts
│ ├── app.module.ts
│ ├── common
│ │ ├── side-menu
│ │ │ ├── side-menu.component.css
│ │ │ ├── side-menu.component.html
│ │ │ └── side-menu.component.ts
│ │ ├── toggle-button
│ │ │ ├── toggle-button.component.css
│ │ │ ├── toggle-button.component.html
│ │ │ └── toggle-button.component.ts
│ │ ├── toggle-switch
│ │ │ ├── toggle-switch.component.css
│ │ │ ├── toggle-switch.component.html
│ │ │ └── toggle-switch.component.ts
│ │ └── top-menu
│ │ │ ├── top-menu.component.css
│ │ │ ├── top-menu.component.html
│ │ │ └── top-menu.component.ts
│ └── examples
│ │ ├── customizing-grid
│ │ ├── customizing-grid.component.css
│ │ ├── customizing-grid.component.html
│ │ └── customizing-grid.component.ts
│ │ ├── customizing-toolbar
│ │ ├── customizing-toolbar.component.css
│ │ ├── customizing-toolbar.component.html
│ │ └── customizing-toolbar.component.ts
│ │ ├── handling-events
│ │ ├── handling-events.component.css
│ │ ├── handling-events.component.html
│ │ └── handling-events.component.ts
│ │ ├── pivot-table-demo
│ │ ├── pivot-table-demo.component.css
│ │ ├── pivot-table-demo.component.html
│ │ └── pivot-table-demo.component.ts
│ │ ├── updating-data
│ │ ├── updating-data.component.css
│ │ ├── updating-data.component.html
│ │ └── updating-data.component.ts
│ │ ├── using-api-calls
│ │ ├── using-api-calls.component.css
│ │ ├── using-api-calls.component.html
│ │ └── using-api-calls.component.ts
│ │ ├── with-amcharts
│ │ ├── with-amcharts.component.css
│ │ ├── with-amcharts.component.html
│ │ └── with-amcharts.component.ts
│ │ ├── with-amcharts4
│ │ ├── with-amcharts4.component.css
│ │ ├── with-amcharts4.component.html
│ │ └── with-amcharts4.component.ts
│ │ └── with-highcharts
│ │ ├── with-highcharts.component.css
│ │ ├── with-highcharts.component.html
│ │ └── with-highcharts.component.ts
├── assets
│ └── .gitkeep
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── favicon.ico
├── index.html
├── main.ts
├── polyfills.ts
└── styles.css
├── testsServer
└── server.js
├── tsconfig.app.json
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /dist-server
6 | /tmp
7 | /out-tsc
8 |
9 | # dependencies
10 | /node_modules
11 |
12 | # IDEs and editors
13 | /.idea
14 | .project
15 | .classpath
16 | .c9/
17 | *.launch
18 | .settings/
19 | *.sublime-workspace
20 |
21 | # IDE - VSCode
22 | .vscode/*
23 | !.vscode/settings.json
24 | !.vscode/tasks.json
25 | !.vscode/launch.json
26 | !.vscode/extensions.json
27 |
28 | # misc
29 | /.angular/cache
30 | /.sass-cache
31 | /connect.lock
32 | /coverage
33 | /libpeerconnection.log
34 | npm-debug.log
35 | yarn-error.log
36 | testem.log
37 | /typings
38 |
39 | # e2e
40 | /e2e/*.js
41 | /e2e/*.map
42 |
43 | # System Files
44 | .DS_Store
45 | Thumbs.db
46 | /.editorconfig
47 | package-lock.json
48 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | os:
2 | - linux
3 | language: node_js
4 | node_js:
5 | - '20'
6 | cache:
7 | npm: false
8 | services:
9 | - xvfb
10 | dist: jammy
11 | addons:
12 | chrome: stable
13 | before_install:
14 | - google-chrome-stable --port=9515 --headless --disable-gpu --remote-debugging-port=9222
15 | http://localhost &
16 | beforescript:
17 | - git clone https://github.com/flexmonster/framework-integration-testing.git
18 | - chmod +x ./framework-integration-testing/launchScripts/angular/angular.sh
19 | - chmod +x ./framework-integration-testing/launchScripts/angular/angularTestLaunch.sh
20 | - chmod +x ./framework-integration-testing/launchScripts/angular/angularKillPorts.sh
21 | script:
22 | - bash ./framework-integration-testing/launchScripts/angular/angular.sh
23 | - bash ./framework-integration-testing/launchScripts/angular/angularTestLaunch.sh
24 | - bash ./framework-integration-testing/launchScripts/angular/angularKillPorts.sh
25 | notifications:
26 | slack:
27 | rooms:
28 | if: branch = master
29 | secure: kvARUhEAMnvD8CxiO4G20auQ9hX7Hpgu/NdwX2uJ28z4KYptRvlPI2kPc49KcZepsrxcgwjCffOr5EU6wCVwnOebFWcASEnemz5EhyDtVyLdN8cihhIufpk2+qyekH4zceI4bb7hRqzll55cewVIlSVclZQ19qztEXO5zq47080JJZ1QW2PkEB+0WscIOm5Z2tppUfooLlt++bdmJllcW4NtW4VA+w1TT2KLvj0WYvs9xATBtvGulvKgjGdkuaA17x/FXVVz9YRPIPWcsn63TTNKNIp/syW/leV78tPn68zBqkFRJIwu2jkHjywl2TuvxWlqVIw8mTh9vQ1Illp0c4c1sUBP9p2afRy6aWFlfVD5YMCtdCM01v+YlknzvioKKjRpDV9KHVnJ/U4EYzL2Xa1q7TVWKUlFoleNsMoes8CgoOah5C2wtSfLMc4v11+VdkTs/XSMiMpbgN6Ypjv6qmOfKnM0SJ5X+i8RDgnM7TmojpDpU8J+oWSgydhiqgqvX1CPVnWAT6yKplzA8pZeIAmZ3fpQXMyFPH+G0MBHRPFJLvMS3E1kA1pxZmoSfJ6otBcEo4bpGUZUK9ppcI3nNdQYecDdnJ9Rh4nvqRKmK4paaQzb1uLCHwbz5PdkOdeCCXL1sSqUJlVzqxwwFbZIG8mXiyUmOr8vKCc8/xH4sgc=
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Angular pivot table | Flexmonster Pivot Table & Charts sample project with Angular
2 | [](https://www.flexmonster.com?r=sample_ngx)
3 | Website: [flexmonster.com](https://www.flexmonster.com?r=sample_ngx)
4 |
5 | [](https://github.com/flexmonster) [](https://twitter.com/Flexmonster)
6 |
7 | ## Flexmonster Pivot Table & Charts
8 | Flexmonster Pivot Table & Charts is a powerful and fully customizable JavaScript component for web reporting. It is packed with all core features for data analysis and can easily become a part of your Angular data visualization project. The tool supports popular frameworks like Angular, React, Vue, Blazor, and [more](https://www.flexmonster.com/doc/available-tutorials-integration?r=sample_ngx). Also, Flexmonster connects to any data source, including SQL and NoSQL databases, JSON and CSV files, OLAP cubes, and Elasticsearch.
9 |
10 | This repository contains a sample [Angular](https://angular.io/) project for Flexmonster Pivot Table & Charts.
11 |
12 | **Note:** This version of the project uses the [ngx-flexmonster](https://github.com/flexmonster/ngx-flexmonster) wrapper, which is Ivy-compatible. Switch to the [ng-flexmonster](https://github.com/flexmonster/pivot-angular/tree/ng-flexmonster) branch for the project with the legacy `ng-flexmonster` wrapper.
13 |
14 | Table of contents:
15 |
16 | * [Prerequisites](#prerequisites)
17 | * [Installation](#installation)
18 | * [What is inside the project](#what-is-inside-the-project)
19 | * [Related Flexmonster docs](#related-flexmonster-docs)
20 | * [Support and feedback](#support-and-feedback)
21 | * [Flexmonster licensing](#flexmonster-licensing)
22 | * [Social media](#social-media)
23 |
24 | ## Prerequisites
25 |
26 | - [Node.js 18 through 22](https://nodejs.org/en/)
27 |
28 | ## Installation
29 |
30 | 1. Download a `.zip` archive with the sample project or clone it from GitHub with the following command:
31 |
32 | ```bash
33 | git clone https://github.com/flexmonster/pivot-angular.git && cd pivot-angular
34 | ```
35 |
36 | 2. Install the npm dependencies described in `package.json`:
37 |
38 | ```bash
39 | npm install
40 | ```
41 |
42 | 3. Run the sample project:
43 |
44 | ```bash
45 | ng serve
46 | ```
47 |
48 | To see the result, open `http://localhost:4200/` in your browser.
49 |
50 | ## What is inside the project
51 |
52 | Angular sample project contains several examples of Flexmonster Pivot usage and customization:
53 |
54 | - **Pivot table demo** shows how to define the `report`, `toolbar`, `height`, `beforetoolbarcreated`, and `shareReportConnection` initialization parameters in the pivot grid for Angular.
55 | - **Handling events** demonstrates how to subscribe to events and unsubscribe from them.
56 | - **Using API calls** illustrates how to use Flexmonster's methods.
57 | - **Updating data** is an example of using the `updateData()` method.
58 | - **Customizing the Toolbar** illustrates how to customize the Toolbar.
59 | - **Customizing the grid** shows how to customize the pivot table using the `customizeCell()` API call.
60 | - **Integration with Highcharts** demonstrates how to integrate with the Highcharts charting library.
61 | - **Integration with amCharts** is an example of integration with the amCharts charting library.
62 |
63 | You can try all of these examples right from the project’s starting page.
64 |
65 | ## Related Flexmonster docs
66 |
67 | - [Integration with Angular](https://www.flexmonster.com/doc/integration-with-angular/?r=sample_ngx) — learn how to integrate Flexmonster into an Angular project.
68 | - [Usage examples in Angular](https://www.flexmonster.com/doc/usage-examples-angular/?r=sample_ngx) — see details on Flexmonster usage.
69 |
70 | ## Support and feedback
71 |
72 | In case of any issues, visit our [troubleshooting section](https://www.flexmonster.com/doc/typical-errors?r=sample_ngx). You can also search among the [resolved cases](https://www.flexmonster.com/technical-support?r=sample_ngx) for a solution to your problem.
73 |
74 | To share your feedback or ask questions, contact our Tech team by raising a ticket on [Flexmonster Help Center](https://www.flexmonster.com/help-center?r=sample_ngx). You can also find a list of samples, technical specifications, and a user interface guide there.
75 |
76 | ## Flexmonster licensing
77 |
78 | This sample project uses [Flexmonster Angular wrapper](https://github.com/flexmonster/ngx-flexmonster), which is released as an MIT-licensed (free and open-source) add-on to Flexmonster Pivot.
79 |
80 | To learn about Flexmonster Pivot licenses, visit the [Flexmonster licensing page](https://www.flexmonster.com/pivot-table-editions-and-pricing?r=sample_ngx).
81 | If you want to test our product, we provide a 30-day free trial.
82 |
83 | If you need any help with your license — fill out our [Contact form](https://www.flexmonster.com/contact-our-team?r=sample_ngx), and we will get in touch with you.
84 |
85 | ## Social media
86 |
87 | Follow us on social media and stay updated on our development process!
88 |
89 | [](https://linkedin.com/company/flexmonster) [](https://youtube.com/user/FlexMonsterPivot) [](https://twitter.com/flexmonster)
90 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "pivot-angular": {
7 | "projectType": "application",
8 | "schematics": {
9 | "@schematics/angular:application": {
10 | "strict": true
11 | }
12 | },
13 | "root": "",
14 | "sourceRoot": "src",
15 | "prefix": "app",
16 | "architect": {
17 | "build": {
18 | "builder": "@angular/build:application",
19 | "options": {
20 | "allowedCommonJsDependencies": [
21 | "core-js",
22 | "raf",
23 | "xlsx",
24 | "@babel/runtime",
25 | "pdfmake"
26 | ],
27 | "outputPath": {
28 | "base": "dist/pivot-angular"
29 | },
30 | "index": "src/index.html",
31 | "polyfills": [
32 | "src/polyfills.ts"
33 | ],
34 | "tsConfig": "tsconfig.app.json",
35 | "assets": [
36 | "src/favicon.ico",
37 | "src/assets"
38 | ],
39 | "styles": [
40 | "src/styles.css"
41 | ],
42 | "scripts": [],
43 | "browser": "src/main.ts"
44 | },
45 | "configurations": {
46 | "production": {
47 | "budgets": [
48 | {
49 | "type": "initial",
50 | "maximumWarning": "5mb",
51 | "maximumError": "5mb"
52 | },
53 | {
54 | "type": "anyComponentStyle",
55 | "maximumWarning": "2kb",
56 | "maximumError": "4kb"
57 | }
58 | ],
59 | "fileReplacements": [
60 | {
61 | "replace": "src/environments/environment.ts",
62 | "with": "src/environments/environment.prod.ts"
63 | }
64 | ],
65 | "outputHashing": "all"
66 | },
67 | "development": {
68 | "optimization": false,
69 | "extractLicenses": false,
70 | "sourceMap": true,
71 | "namedChunks": true
72 | }
73 | },
74 | "defaultConfiguration": "production"
75 | },
76 | "serve": {
77 | "builder": "@angular/build:dev-server",
78 | "configurations": {
79 | "production": {
80 | "buildTarget": "pivot-angular:build:production"
81 | },
82 | "development": {
83 | "buildTarget": "pivot-angular:build:development"
84 | }
85 | },
86 | "defaultConfiguration": "development"
87 | },
88 | "extract-i18n": {
89 | "builder": "@angular/build:extract-i18n",
90 | "options": {
91 | "buildTarget": "pivot-angular:build:production,development"
92 | }
93 | }
94 | }
95 | }
96 | },
97 | "cli": {
98 | "analytics": false
99 | }
100 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pivot-angular",
3 | "version": "1.0.0",
4 | "license": "MIT",
5 | "scripts": {
6 | "ng": "ng",
7 | "start": "ng serve --open",
8 | "build": "ng build",
9 | "watch": "ng build --watch --configuration development"
10 | },
11 | "private": true,
12 | "dependencies": {
13 | "@amcharts/amcharts4": "^4.10.22",
14 | "@amcharts/amcharts5": "^5.3.3",
15 | "@angular/animations": "^19.1.2",
16 | "@angular/common": "^19.1.2",
17 | "@angular/compiler": "^19.1.2",
18 | "@angular/core": "^19.1.2",
19 | "@angular/forms": "^19.1.2",
20 | "@angular/platform-browser": "^19.1.2",
21 | "@angular/platform-browser-dynamic": "^19.1.2",
22 | "@angular/router": "^19.1.2",
23 | "express": "^4.18.2",
24 | "highcharts": "^11.4.3",
25 | "ngx-flexmonster": "latest",
26 | "path": "^0.12.7",
27 | "rxjs": "^7.4.0",
28 | "tslib": "^2.3.0",
29 | "zone.js": "~0.15.0"
30 | },
31 | "devDependencies": {
32 | "@angular/build": "^19.1.3",
33 | "@angular/cli": "^19.1.3",
34 | "@angular/compiler-cli": "^19.1.2",
35 | "@types/node": "^20.14.2",
36 | "karma-chrome-launcher": "~3.1.0",
37 | "karma-coverage": "~2.0.3",
38 | "typescript": "^5.5.4"
39 | }
40 | }
--------------------------------------------------------------------------------
/src/app/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { HandlingEventsComponent } from './examples/handling-events/handling-events.component';
4 | import { CustomizingGridComponent } from './examples/customizing-grid/customizing-grid.component';
5 | import { CustomizingToolbarComponent } from './examples/customizing-toolbar/customizing-toolbar.component';
6 | import { PivotTableDemoComponent } from './examples/pivot-table-demo/pivot-table-demo.component';
7 | import { UpdatingDataComponent } from './examples/updating-data/updating-data.component';
8 | import { UsingApiCallsComponent } from './examples/using-api-calls/using-api-calls.component';
9 | import { WithAmcharts4Component } from './examples/with-amcharts4/with-amcharts4.component';
10 | import { WithAmchartsComponent } from './examples/with-amcharts/with-amcharts.component';
11 | import { WithHighchartsComponent } from './examples/with-highcharts/with-highcharts.component';
12 |
13 | const routes: Routes = [
14 | { path: 'pivot-table-demo', component: PivotTableDemoComponent },
15 | { path: 'handling-events', component: HandlingEventsComponent },
16 | { path: 'using-api-calls', component: UsingApiCallsComponent },
17 | { path: 'updating-data', component: UpdatingDataComponent },
18 | { path: 'customizing-toolbar', component: CustomizingToolbarComponent },
19 | { path: 'customizing-grid', component: CustomizingGridComponent },
20 | { path: 'with-highcharts', component: WithHighchartsComponent },
21 | { path: 'with-amcharts4', component: WithAmcharts4Component },
22 | { path: 'with-amcharts', component: WithAmchartsComponent },
23 | { path: '**', redirectTo: 'pivot-table-demo' }
24 | ];
25 |
26 | @NgModule({
27 | imports: [RouterModule.forRoot(routes)],
28 | exports: [RouterModule]
29 | })
30 | export class AppRoutingModule { }
31 |
--------------------------------------------------------------------------------
/src/app/app.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/app.component.css
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-root',
5 | templateUrl: './app.component.html',
6 | styleUrls: ['./app.component.css'],
7 | standalone: false
8 | })
9 | export class AppComponent {
10 | title = 'pivot-angular';
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { BrowserModule } from '@angular/platform-browser';
3 |
4 | import { AppRoutingModule } from './app-routing.module';
5 | import { AppComponent } from './app.component';
6 | import { FlexmonsterPivotModule } from 'ngx-flexmonster';
7 | import { SideMenuComponent } from './common/side-menu/side-menu.component';
8 | import { ToggleButtonComponent } from './common/toggle-button/toggle-button.component';
9 | import { ToggleSwitchComponent } from './common/toggle-switch/toggle-switch.component';
10 | import { TopMenuComponent } from './common/top-menu/top-menu.component';
11 | import { HandlingEventsComponent } from './examples/handling-events/handling-events.component';
12 | import { CustomizingGridComponent } from './examples/customizing-grid/customizing-grid.component';
13 | import { CustomizingToolbarComponent } from './examples/customizing-toolbar/customizing-toolbar.component';
14 | import { UpdatingDataComponent } from './examples/updating-data/updating-data.component';
15 | import { UsingApiCallsComponent } from './examples/using-api-calls/using-api-calls.component';
16 | import { WithAmcharts4Component } from './examples/with-amcharts4/with-amcharts4.component';
17 | import { WithAmchartsComponent } from './examples/with-amcharts/with-amcharts.component';
18 | import { WithHighchartsComponent } from './examples/with-highcharts/with-highcharts.component';
19 | import { FormsModule } from '@angular/forms';
20 |
21 | @NgModule({
22 | declarations: [
23 | AppComponent,
24 | TopMenuComponent,
25 | SideMenuComponent,
26 | HandlingEventsComponent,
27 | UsingApiCallsComponent,
28 | UpdatingDataComponent,
29 | CustomizingToolbarComponent,
30 | CustomizingGridComponent,
31 | WithHighchartsComponent,
32 | WithAmcharts4Component,
33 | WithAmchartsComponent,
34 | ToggleButtonComponent,
35 | ToggleSwitchComponent
36 | ],
37 | imports: [
38 | BrowserModule,
39 | AppRoutingModule,
40 | FlexmonsterPivotModule,
41 | FormsModule
42 | ],
43 | providers: [],
44 | bootstrap: [AppComponent]
45 | })
46 | export class AppModule { }
47 |
--------------------------------------------------------------------------------
/src/app/common/side-menu/side-menu.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/common/side-menu/side-menu.component.css
--------------------------------------------------------------------------------
/src/app/common/side-menu/side-menu.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/common/side-menu/side-menu.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-side-menu',
5 | templateUrl: './side-menu.component.html',
6 | styleUrls: ['./side-menu.component.css'],
7 | standalone: false
8 | })
9 | export class SideMenuComponent implements OnInit {
10 |
11 | constructor() { }
12 |
13 | ngOnInit(): void {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/common/toggle-button/toggle-button.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/common/toggle-button/toggle-button.component.css
--------------------------------------------------------------------------------
/src/app/common/toggle-button/toggle-button.component.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | {{ checked ? labelOn : labelOff }}
6 |
7 |
--------------------------------------------------------------------------------
/src/app/common/toggle-button/toggle-button.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-toggle-button',
5 | templateUrl: './toggle-button.component.html',
6 | styleUrls: ['./toggle-button.component.css'],
7 | standalone: false
8 | })
9 | export class ToggleButtonComponent implements OnInit {
10 | @Input() public _id!: string;
11 | @Input() public labelOn!: string;
12 | @Input() public labelOff!: string;
13 |
14 | @Output() public clicked: EventEmitter = new EventEmitter();
15 |
16 | public checked: boolean = true;
17 |
18 | constructor() { }
19 |
20 | ngOnInit(): void {
21 | }
22 |
23 | onChange() {
24 | this.clicked.emit(this.checked);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/app/common/toggle-switch/toggle-switch.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/common/toggle-switch/toggle-switch.component.css
--------------------------------------------------------------------------------
/src/app/common/toggle-switch/toggle-switch.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ checked ? labelOn : labelOff }}
5 |
6 |
--------------------------------------------------------------------------------
/src/app/common/toggle-switch/toggle-switch.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, EventEmitter, Input, OnInit, Output, SimpleChanges } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-toggle-switch',
5 | templateUrl: './toggle-switch.component.html',
6 | styleUrls: ['./toggle-switch.component.css'],
7 | standalone: false
8 | })
9 | export class ToggleSwitchComponent implements OnInit {
10 | @Input() public _id!: string;
11 | @Input() public labelOn!: string;
12 | @Input() public labelOff!: string;
13 |
14 | @Output() public clicked: EventEmitter = new EventEmitter();
15 |
16 | public checked: boolean = true;
17 |
18 | constructor() { }
19 |
20 | ngOnInit(): void {
21 | }
22 |
23 | onChange() {
24 | this.clicked.emit(this.checked);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/app/common/top-menu/top-menu.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/common/top-menu/top-menu.component.css
--------------------------------------------------------------------------------
/src/app/common/top-menu/top-menu.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/common/top-menu/top-menu.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-top-menu',
5 | templateUrl: './top-menu.component.html',
6 | styleUrls: ['./top-menu.component.css'],
7 | standalone: false
8 | })
9 | export class TopMenuComponent implements OnInit {
10 |
11 | constructor() { }
12 |
13 | ngOnInit(): void {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/examples/customizing-grid/customizing-grid.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/examples/customizing-grid/customizing-grid.component.css
--------------------------------------------------------------------------------
/src/app/examples/customizing-grid/customizing-grid.component.html:
--------------------------------------------------------------------------------
1 | Customizing the grid
2 |
3 |
4 |
Style the grid by adding links, applying custom CSS, or formatting the cells. Check our docs for details:
5 | Customizing the grid .
6 |
7 |
In this demo, the Price measure is customized.
8 |
9 |
10 |
14 |
15 |
16 |
19 |
--------------------------------------------------------------------------------
/src/app/examples/customizing-grid/customizing-grid.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild } from '@angular/core';
2 | import { FlexmonsterPivot } from 'ngx-flexmonster';
3 |
4 | @Component({
5 | selector: 'app-customizing-grid',
6 | templateUrl: './customizing-grid.component.html',
7 | styleUrls: ['./customizing-grid.component.css'],
8 | standalone: false
9 | })
10 | export class CustomizingGridComponent implements OnInit {
11 |
12 | @ViewChild('pivot') pivot!: FlexmonsterPivot;
13 |
14 | constructor() { }
15 |
16 | ngOnInit(): void {
17 | }
18 |
19 | customizeToolbar(toolbar: Flexmonster.Toolbar) {
20 | toolbar.showShareReportTab = true;
21 | }
22 |
23 | customizeCellFunction(cell: Flexmonster.CellBuilder, data: Flexmonster.CellData) {
24 | if (data.measure && data.measure.uniqueName == "Price") {
25 | let backgroundColor = "#00A45A";
26 | let textShadowColor = "#095231";
27 | let borderColor = "#009552";
28 | cell.style = {
29 | ...cell.style,
30 | "background-color": backgroundColor,
31 | "color": "white",
32 | "font-weight": "bold",
33 | "text-shadow": `0px 2px 3px ${textShadowColor}`,
34 | "border-bottom": `1px solid ${borderColor}`,
35 | "border-right": `1px solid ${borderColor}`
36 | };
37 | }
38 | }
39 |
40 | removeCustomization() {
41 | this.pivot.flexmonster.customizeCell(() => null);
42 | }
43 |
44 | applyCustomization() {
45 | this.pivot.flexmonster.customizeCell(this.customizeCellFunction);
46 | }
47 |
48 | toggleCustomization(checked: boolean) {
49 | if (checked) {
50 | this.applyCustomization();
51 | } else {
52 | this.removeCustomization();
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/app/examples/customizing-toolbar/customizing-toolbar.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/examples/customizing-toolbar/customizing-toolbar.component.css
--------------------------------------------------------------------------------
/src/app/examples/customizing-toolbar/customizing-toolbar.component.html:
--------------------------------------------------------------------------------
1 | Customizing the Toolbar
2 |
3 |
4 |
You can add, remove, and update the Toolbar tabs.
5 |
In this demo, we’ve removed all the tabs and added a custom New Tab .
6 | See our docs to learn more about the Toolbar and its customization:
7 | Customizing the Toolbar .
8 |
9 |
10 |
11 |
12 |
14 |
--------------------------------------------------------------------------------
/src/app/examples/customizing-toolbar/customizing-toolbar.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild } from '@angular/core';
2 | import { FlexmonsterPivot } from 'ngx-flexmonster';
3 |
4 | @Component({
5 | selector: 'app-customizing-toolbar',
6 | templateUrl: './customizing-toolbar.component.html',
7 | styleUrls: ['./customizing-toolbar.component.css'],
8 | standalone: false
9 | })
10 | export class CustomizingToolbarComponent implements OnInit {
11 |
12 | @ViewChild('pivot') pivot!: FlexmonsterPivot;
13 |
14 | constructor() { }
15 |
16 | ngOnInit(): void {
17 | }
18 |
19 | showInfo() {
20 | this.pivot.flexmonster.alert({
21 | title: "Customizing Flexmonster",
22 | message:
23 | "How to customize the Toolbar: https://www.flexmonster.com/doc/customizing-toolbar/ ",
24 | type: "info",
25 | blocking: false,
26 | });
27 | }
28 |
29 | customizeToolbar(toolbar: Flexmonster.Toolbar) {
30 | let tabs = toolbar.getTabs();
31 | toolbar.getTabs = () => {
32 | tabs = [];
33 | // add new tab
34 | tabs.push({
35 | id: "fm-tab-newtab",
36 | title: "New Tab",
37 | handler: () => this.showInfo(),
38 | icon: toolbar.icons.open,
39 | });
40 | return tabs;
41 | };
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/app/examples/handling-events/handling-events.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/examples/handling-events/handling-events.component.css
--------------------------------------------------------------------------------
/src/app/examples/handling-events/handling-events.component.html:
--------------------------------------------------------------------------------
1 | Handling Flexmonster events
2 |
3 |
4 |
5 | Perform an action (for example, click on a grid cell) to trigger a
6 | Flexmonster
7 | event .
8 | Scroll down to the log output to see which events get triggered.
9 |
10 |
11 |
12 |
16 |
17 |
18 |
21 |
22 |
23 |
24 |
25 |
Log Output
26 |
27 |
28 |
29 |
[ Event ] {{ log.date | date:'mediumTime' }}:
30 | {{ log.event }} [
see details ]
32 |
33 |
34 |
35 |
36 | Clear Log Output
37 |
38 |
--------------------------------------------------------------------------------
/src/app/examples/handling-events/handling-events.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
2 | import { FlexmonsterPivot } from 'ngx-flexmonster';
3 |
4 | @Component({
5 | selector: 'app-handling-events',
6 | templateUrl: './handling-events.component.html',
7 | styleUrls: ['./handling-events.component.css'],
8 | standalone: false
9 | })
10 | export class HandlingEventsComponent implements OnInit {
11 |
12 | @ViewChild('pivot') pivot!: FlexmonsterPivot;
13 | @ViewChild('logsContainer')
14 | logsContainer!: ElementRef;
15 |
16 | public logs: {
17 | date: Date,
18 | event: string
19 | }[] = [];
20 |
21 | public eventList = [
22 | "afterchartdraw",
23 | "aftergriddraw",
24 | "beforegriddraw",
25 | "beforetoolbarcreated",
26 | "cellclick",
27 | "celldoubleclick",
28 | "chartclick",
29 | "datachanged",
30 | "dataerror",
31 | "datafilecancelled",
32 | "dataloaded",
33 | "drillthroughclose",
34 | "drillthroughopen",
35 | "exportcomplete",
36 | "exportstart",
37 | "fieldslistclose",
38 | "fieldslistopen",
39 | "filterclose",
40 | "filteropen",
41 | "loadingdata",
42 | "loadinglocalization",
43 | "loadingolapstructure",
44 | "loadingreportfile",
45 | "localizationerror",
46 | "localizationloaded",
47 | "olapstructureerror",
48 | "olapstructureloaded",
49 | "openingreportfile",
50 | "printcomplete",
51 | "printstart",
52 | "querycomplete",
53 | "queryerror",
54 | "ready",
55 | "reportchange",
56 | "reportcomplete",
57 | "reportfilecancelled",
58 | "reportfileerror",
59 | "runningquery",
60 | "update",
61 | ];
62 |
63 | constructor() { }
64 |
65 | ngOnInit(): void {
66 | }
67 |
68 | customizeToolbar(toolbar: Flexmonster.Toolbar) {
69 | toolbar.showShareReportTab = true;
70 | }
71 |
72 | printLog(log: string) {
73 | this.logs.push({
74 | date: new Date(),
75 | event: log
76 | });
77 | requestAnimationFrame(() => {
78 | this.logsContainer.nativeElement.scrollTop = this.logsContainer.nativeElement.scrollHeight;
79 | });
80 | }
81 |
82 | toggleEvents(checked: boolean) {
83 | if (checked) {
84 | this.signOnAllEvents();
85 | } else {
86 | this.signOffAllEvents();
87 | }
88 | }
89 |
90 | signOffAllEvents() {
91 | for (const eventName of this.eventList) {
92 | // remove all handlers for specified event
93 | this.pivot.flexmonster.off(eventName);
94 | }
95 | }
96 |
97 | signOnAllEvents() {
98 | for (const eventName of this.eventList) {
99 | // add handler for specified event
100 | this.pivot.flexmonster.on(eventName, () => {
101 | this.printLog(eventName);
102 | });
103 | }
104 | }
105 |
106 | clearLogs() {
107 | this.logs.length = 0;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/app/examples/pivot-table-demo/pivot-table-demo.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/examples/pivot-table-demo/pivot-table-demo.component.css
--------------------------------------------------------------------------------
/src/app/examples/pivot-table-demo/pivot-table-demo.component.html:
--------------------------------------------------------------------------------
1 | Pivot Table Demo
2 |
3 |
Flexmonster is a fast and powerful JavaScript pivot grid for data visualization and reporting.
4 |
With Flexmonster, you can create reports based on many data sources, including JSON, CSV, MongoDB, and SQL
5 | databases.
6 | Our component is easy to customize and configure, so it can be seamlessly integrated into any project.
7 |
8 |
Visit our documentation for step-by-step guidance on
9 | Flexmonster.
10 |
11 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/src/app/examples/pivot-table-demo/pivot-table-demo.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { FlexmonsterPivotModule } from 'ngx-flexmonster';
3 |
4 | @Component({
5 | selector: 'app-pivot-table-demo',
6 | templateUrl: './pivot-table-demo.component.html',
7 | styleUrls: ['./pivot-table-demo.component.css'],
8 | imports: [FlexmonsterPivotModule],
9 | standalone: true
10 | })
11 | export class PivotTableDemoComponent implements OnInit {
12 |
13 | constructor() { }
14 |
15 | ngOnInit(): void {
16 | }
17 |
18 | customizeToolbar(toolbar: Flexmonster.Toolbar) {
19 | toolbar.showShareReportTab = true;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/app/examples/updating-data/updating-data.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/examples/updating-data/updating-data.component.css
--------------------------------------------------------------------------------
/src/app/examples/updating-data/updating-data.component.html:
--------------------------------------------------------------------------------
1 | Updating the data in Flexmonster
2 |
3 |
4 |
5 | This demo shows how to refresh the data at runtime and keep the slice, options, and formatting the same.
6 |
7 |
Try it yourself: configure the component as you wish and click the UPDATE DATA button.
8 |
Learn more about updating the data
9 | in our documentation .
10 |
11 |
12 |
13 | Update data
14 |
15 |
16 |
18 |
--------------------------------------------------------------------------------
/src/app/examples/updating-data/updating-data.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild } from '@angular/core';
2 | import { FlexmonsterPivot } from 'ngx-flexmonster';
3 |
4 | @Component({
5 | selector: 'app-updating-data',
6 | templateUrl: './updating-data.component.html',
7 | styleUrls: ['./updating-data.component.css'],
8 | standalone: false
9 | })
10 | export class UpdatingDataComponent implements OnInit {
11 |
12 | @ViewChild('pivot') pivot!: FlexmonsterPivot;
13 |
14 | public data: Object[] = [
15 | {
16 | Category: "Accessories",
17 | Size: "262 oz",
18 | Color: "red",
19 | Destination: "Australia",
20 | "Business Type": "Specialty Bike Shop",
21 | Country: "Australia",
22 | Price: 100,
23 | Quantity: 225,
24 | Discount: 23,
25 | },
26 | {
27 | Category: "Components",
28 | Size: "235 oz",
29 | Color: "green",
30 | Destination: "Australia",
31 | "Business Type": "Warehouse",
32 | Country: "Australia",
33 | Price: 200,
34 | Quantity: 1950,
35 | Discount: 51,
36 | },
37 | ];
38 |
39 | constructor() { }
40 |
41 | ngOnInit(): void {
42 | }
43 |
44 | customizeToolbar(toolbar: Flexmonster.Toolbar) {
45 | toolbar.showShareReportTab = true;
46 | }
47 |
48 | onReady() {
49 | // Connect Flexmonster to the data
50 | this.pivot.flexmonster.connectTo({ data: this.data });
51 | }
52 |
53 | updateTheData() {
54 | // If the data got updated, for example:
55 | this.data = [
56 | {
57 | Category: "Accessories",
58 | Size: "262 oz",
59 | Color: "red",
60 | Destination: "Australia",
61 | "Business Type": "Specialty Bike Shop",
62 | Country: "Australia",
63 | Price: Math.floor(Math.random() * Math.floor(1000)),
64 | Quantity: 225,
65 | Discount: 23,
66 | },
67 | {
68 | Category: "Components",
69 | Size: "307 oz",
70 | Color: "white",
71 | Destination: "United Kingdom",
72 | "Business Type": "Warehouse",
73 | Country: "Canada",
74 | Price: Math.floor(Math.random() * Math.floor(1000)),
75 | Quantity: 8212,
76 | Discount: 55,
77 | },
78 | ];
79 | // then the data needs to be updated in Flexmonster as well
80 | // this can be done via Flexmonster's updateData() API call:
81 | this.pivot.flexmonster.updateData({ data: this.data });
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/app/examples/using-api-calls/using-api-calls.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/examples/using-api-calls/using-api-calls.component.css
--------------------------------------------------------------------------------
/src/app/examples/using-api-calls/using-api-calls.component.html:
--------------------------------------------------------------------------------
1 | Using Flexmonster API calls
2 |
3 |
4 |
5 | Flexmonster provides API calls
6 | for interacting with the component.
7 | As an example, we've added the toggle buttons below. Use them to switch between the views or make Flexmonster read-only.
8 |
9 |
10 |
11 |
19 |
20 |
21 |
24 |
--------------------------------------------------------------------------------
/src/app/examples/using-api-calls/using-api-calls.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild } from '@angular/core';
2 | import { FlexmonsterPivot } from 'ngx-flexmonster';
3 |
4 | @Component({
5 | selector: 'app-using-api-calls',
6 | templateUrl: './using-api-calls.component.html',
7 | styleUrls: ['./using-api-calls.component.css'],
8 | standalone: false
9 | })
10 | export class UsingApiCallsComponent implements OnInit {
11 |
12 | @ViewChild('pivot')
13 | pivot!: FlexmonsterPivot;
14 |
15 | constructor() { }
16 |
17 | ngOnInit(): void {
18 | }
19 |
20 | customizeToolbar(toolbar: Flexmonster.Toolbar) {
21 | toolbar.showShareReportTab = true;
22 | }
23 |
24 | toggleView(checked: boolean) {
25 | if (checked) {
26 | this.showGrid();
27 | } else {
28 | this.showChart();
29 | }
30 | }
31 |
32 | toggleMode(checked: boolean) {
33 | if (checked) {
34 | this.interactive();
35 | } else {
36 | this.readOnly();
37 | }
38 | }
39 |
40 | showChart() {
41 | this.pivot.flexmonster.showCharts("column");
42 | }
43 |
44 | showGrid() {
45 | this.pivot.flexmonster.showGrid();
46 | }
47 |
48 | readOnly() {
49 | this.pivot.flexmonster.setOptions({
50 | readOnly: true
51 | });
52 | this.pivot.flexmonster.refresh();
53 | }
54 |
55 | interactive() {
56 | this.pivot.flexmonster.setOptions({
57 | readOnly: false
58 | });
59 | this.pivot.flexmonster.refresh();
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/app/examples/with-amcharts/with-amcharts.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/examples/with-amcharts/with-amcharts.component.css
--------------------------------------------------------------------------------
/src/app/examples/with-amcharts/with-amcharts.component.html:
--------------------------------------------------------------------------------
1 | Integrating with amCharts
2 |
3 |
4 |
Extend Flexmonster’s visualization functionality by integrating with the amCharts library:
5 | Integration with amCharts .
6 |
7 |
8 |
9 |
10 |
18 |
19 |
20 |
21 |
24 |
--------------------------------------------------------------------------------
/src/app/examples/with-amcharts/with-amcharts.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, ViewChild, OnInit } from '@angular/core';
2 | import { FlexmonsterPivot } from 'ngx-flexmonster';
3 |
4 | // amCharts imports
5 | import * as am5 from "@amcharts/amcharts5";
6 | import * as am5xy from "@amcharts/amcharts5/xy";
7 | import am5themes_Animated from "@amcharts/amcharts5/themes/Animated";
8 |
9 | // Importing Flexmonster Connector for amCharts
10 | import "flexmonster/lib/flexmonster.amcharts.js";
11 |
12 | @Component({
13 | selector: 'app-with-amcharts',
14 | templateUrl: './with-amcharts.component.html',
15 | styleUrls: ['./with-amcharts.component.css'],
16 | standalone: false
17 | })
18 | export class WithAmchartsComponent implements OnInit {
19 | @ViewChild('pivot') pivot!: FlexmonsterPivot;
20 |
21 | private flexmonster!: Flexmonster.Pivot;
22 | private root!: am5.Root;
23 |
24 | public report: Flexmonster.Report = {
25 | dataSource: {
26 | filename: 'https://cdn.flexmonster.com/data/data.csv'
27 | },
28 | slice: {
29 | rows: [{
30 | uniqueName: 'Country'
31 | }],
32 | columns: [{
33 | uniqueName: '[Measures]'
34 | }],
35 | measures: [{
36 | uniqueName: 'Price',
37 | aggregation: 'sum'
38 | }]
39 | }
40 | };
41 |
42 | constructor() { }
43 |
44 | ngOnInit(): void {
45 | }
46 |
47 | customizeToolbar(toolbar: Flexmonster.Toolbar) {
48 | toolbar.showShareReportTab = true;
49 | }
50 |
51 | drawChart() {
52 | this.pivot.flexmonster.amcharts?.getData(
53 | {},
54 | this.createChart.bind(this),
55 | this.updateChart.bind(this)
56 | );
57 | }
58 |
59 | onReportComplete() {
60 | this.pivot.flexmonster.off("reportcomplete");
61 | this.drawChart();
62 | }
63 |
64 | createChart = (chartData: Flexmonster.GetDataValueObject, rawData: Flexmonster.GetDataValueObject) => {
65 |
66 | /* Create root element and chart instance */
67 | this.root = am5.Root.new("amcharts-container");
68 | let chart = this.root.container.children.push(am5xy.XYChart.new(this.root, {
69 | }));
70 |
71 | /* Apply amCharts theme */
72 | this.root.setThemes([
73 | am5themes_Animated.new(this.root),
74 | ]);
75 |
76 | /* Apply number format from Flexmonster */
77 | this.root.numberFormatter.set("numberFormat", this.pivot.flexmonster.amcharts?.getNumberFormatPattern((rawData.meta as any).formats[0]));
78 |
79 | /* Create and configure Y axis */
80 | let yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(this.root, {
81 | categoryField: this.pivot.flexmonster.amcharts?.getCategoryName(rawData)!,
82 | renderer: am5xy.AxisRendererY.new(this.root, {
83 | cellStartLocation: 0.1,
84 | cellEndLocation: 0.9
85 | })
86 | }));
87 |
88 | /* Create and configure X axis */
89 | let xAxis = chart.xAxes.push(am5xy.ValueAxis.new(this.root, {
90 | renderer: am5xy.AxisRendererX.new(this.root, {}),
91 | }));
92 |
93 | xAxis.set("numberFormatter", am5.NumberFormatter.new(this.root, {
94 | "numberFormat": "#a"
95 | }));
96 |
97 | /* Create and configure series for a bar chart */
98 | let series = chart.series.push(am5xy.ColumnSeries.new(this.root, {
99 | name: this.pivot.flexmonster.amcharts?.getMeasureNameByIndex(rawData, 0),
100 | xAxis: xAxis,
101 | yAxis: yAxis as any,
102 | sequencedInterpolation: true,
103 | valueXField: this.pivot.flexmonster.amcharts?.getMeasureNameByIndex(rawData, 0),
104 | categoryYField: this.pivot.flexmonster.amcharts?.getCategoryName(rawData),
105 | tooltip: am5.Tooltip.new(this.root, {
106 | labelText: '{name}: [bold]{valueX}[/]'
107 | })
108 | }));
109 |
110 | chart.set("cursor", am5xy.XYCursor.new(this.root, {
111 | behavior: "none",
112 | xAxis: xAxis,
113 | yAxis: yAxis
114 | }));
115 |
116 | /* Add data processed by Flexmonster to the chart */
117 | yAxis.data.setAll(chartData.data);
118 | series.data.setAll(chartData.data);
119 |
120 | /* Create initial animation */
121 | series.appear(1000);
122 | chart.appear(1000, 100);
123 | }
124 |
125 | updateChart(chartData: Flexmonster.GetDataValueObject, rawData: Flexmonster.GetDataValueObject) {
126 | this.root.dispose();
127 | this.createChart(chartData, rawData)
128 | }
129 |
130 | ngOnDestroy() {
131 | // Clean up this.chart when the component is removed
132 | if (this.root) {
133 | this.root.dispose();
134 | }
135 | }
136 |
137 | }
138 |
--------------------------------------------------------------------------------
/src/app/examples/with-amcharts4/with-amcharts4.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/examples/with-amcharts4/with-amcharts4.component.css
--------------------------------------------------------------------------------
/src/app/examples/with-amcharts4/with-amcharts4.component.html:
--------------------------------------------------------------------------------
1 | Integrating with amCharts
2 |
3 |
4 |
Extend Flexmonster’s visualization functionality by integrating with the amCharts library:
5 | Integration with amCharts .
6 |
7 |
8 |
9 |
10 |
18 |
19 |
20 |
21 |
24 |
--------------------------------------------------------------------------------
/src/app/examples/with-amcharts4/with-amcharts4.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, ViewChild, OnInit } from '@angular/core';
2 | import { FlexmonsterPivot } from 'ngx-flexmonster';
3 |
4 | // Importing amCharts
5 | import * as am4core from '@amcharts/amcharts4/core';
6 | import * as am4charts from '@amcharts/amcharts4/charts';
7 | import am4themes_animated from '@amcharts/amcharts4/themes/animated';
8 |
9 | // Importing Flexmonster Connector for amCharts
10 | import "flexmonster/lib/flexmonster.amcharts.js";
11 |
12 | @Component({
13 | selector: 'app-with-amcharts4',
14 | templateUrl: './with-amcharts4.component.html',
15 | styleUrls: ['./with-amcharts4.component.css'],
16 | standalone: false
17 | })
18 | export class WithAmcharts4Component implements OnInit {
19 | @ViewChild('pivot') pivot!: FlexmonsterPivot;
20 |
21 | chart!: am4charts.PieChart;
22 |
23 | public report: Flexmonster.Report = {
24 | dataSource: {
25 | filename: 'https://cdn.flexmonster.com/data/data.csv'
26 | },
27 | slice: {
28 | rows: [{
29 | uniqueName: 'Country'
30 | }],
31 | columns: [{
32 | uniqueName: '[Measures]'
33 | }],
34 | measures: [{
35 | uniqueName: 'Price',
36 | aggregation: 'sum'
37 | }]
38 | }
39 | };
40 |
41 | constructor() { }
42 |
43 | ngOnInit(): void {
44 | }
45 |
46 | customizeToolbar(toolbar: Flexmonster.Toolbar) {
47 | toolbar.showShareReportTab = true;
48 | }
49 |
50 | drawChart() {
51 | this.pivot.flexmonster.amcharts?.getData(
52 | {},
53 | this.createChart.bind(this),
54 | this.updateChart.bind(this)
55 | );
56 | }
57 |
58 | onReportComplete() {
59 | this.pivot.flexmonster.off("reportcomplete");
60 | this.drawChart();
61 | }
62 |
63 | createChart(chartData: Flexmonster.GetDataValueObject, rawData: Flexmonster.GetDataValueObject) {
64 |
65 | /* Apply amCharts theme */
66 | am4core.useTheme(am4themes_animated);
67 |
68 | /* Create chart instance */
69 | let chart = am4core.create("amcharts-container", am4charts.PieChart);
70 |
71 | /* Add data processed by Flexmonster to the chart */
72 | chart.data = chartData.data;
73 |
74 | /* Set an inner radius to transform a pie chart into a donut chart */
75 | chart.innerRadius = am4core.percent(50);
76 |
77 | /* Create and configure series for a pie chart */
78 | var pieSeries = chart.series.push(new am4charts.PieSeries());
79 | pieSeries.dataFields.category = this.pivot.flexmonster.amcharts?.getCategoryName(rawData);
80 | pieSeries.dataFields.value = this.pivot.flexmonster.amcharts?.getMeasureNameByIndex(rawData, 0);
81 | pieSeries.slices.template.stroke = am4core.color("#fff");
82 | pieSeries.slices.template.strokeWidth = 2;
83 | pieSeries.slices.template.strokeOpacity = 1;
84 |
85 | /* Create initial animation */
86 | pieSeries.hiddenState.properties.opacity = 1;
87 | pieSeries.hiddenState.properties.endAngle = -90;
88 | pieSeries.hiddenState.properties.startAngle = -90;
89 |
90 | this.chart = chart;
91 | }
92 |
93 | updateChart(chartData: Flexmonster.GetDataValueObject, rawData: Flexmonster.GetDataValueObject) {
94 | this.chart.dispose();
95 | this.createChart(chartData, rawData)
96 | }
97 |
98 | ngOnDestroy() {
99 | // Clean up this.chart when the component is removed
100 | if (this.chart) {
101 | this.chart.dispose();
102 | }
103 | }
104 |
105 | }
106 |
--------------------------------------------------------------------------------
/src/app/examples/with-highcharts/with-highcharts.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/app/examples/with-highcharts/with-highcharts.component.css
--------------------------------------------------------------------------------
/src/app/examples/with-highcharts/with-highcharts.component.html:
--------------------------------------------------------------------------------
1 | Integrating with Highcharts
2 |
3 |
9 |
10 |
11 |
19 |
20 |
21 |
22 |
25 |
--------------------------------------------------------------------------------
/src/app/examples/with-highcharts/with-highcharts.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild } from '@angular/core';
2 | import { FlexmonsterPivot } from 'ngx-flexmonster';
3 | // Importing Highcharts
4 | import * as Highcharts from 'highcharts';
5 | // Importing Flexmonster Connector for Highcharts
6 | import "flexmonster/lib/flexmonster.highcharts.js";
7 |
8 | @Component({
9 | selector: 'app-with-highcharts',
10 | templateUrl: './with-highcharts.component.html',
11 | styleUrls: ['./with-highcharts.component.css'],
12 | standalone: false
13 | })
14 | export class WithHighchartsComponent implements OnInit {
15 |
16 | @ViewChild('pivot') pivot!: FlexmonsterPivot;
17 |
18 | constructor() { }
19 |
20 | ngOnInit(): void {
21 | }
22 |
23 | customizeToolbar(toolbar: Flexmonster.Toolbar) {
24 | toolbar.showShareReportTab = true;
25 | }
26 |
27 | drawChart() {
28 | this.pivot.flexmonster.highcharts?.getData(
29 | {
30 | type: "spline"
31 | },
32 | (data: Flexmonster.GetDataValueObject) => {
33 | Highcharts.chart('highcharts-container', data);
34 | },
35 | (data: Flexmonster.GetDataValueObject) => {
36 | Highcharts.chart('highcharts-container', data);
37 | }
38 | );
39 | }
40 |
41 | onReportComplete() {
42 | this.pivot.flexmonster.off("reportcomplete");
43 | this.drawChart();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/assets/.gitkeep
--------------------------------------------------------------------------------
/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flexmonster/pivot-angular/11a21cb3df58cc26e8f52f3d0bd387ab50be2200/src/favicon.ico
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PivotAngular
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | platformBrowserDynamic().bootstrapModule(AppModule)
12 | .catch(err => console.error(err));
13 |
--------------------------------------------------------------------------------
/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /**
22 | * By default, zone.js will patch all possible macroTask and DomEvents
23 | * user can disable parts of macroTask/DomEvents patch by setting following flags
24 | * because those flags need to be set before `zone.js` being loaded, and webpack
25 | * will put import in the top of bundle, so user need to create a separate file
26 | * in this directory (for example: zone-flags.ts), and put the following flags
27 | * into that file, and then add the following code before importing zone.js.
28 | * import './zone-flags';
29 | *
30 | * The flags allowed in zone-flags.ts are listed here.
31 | *
32 | * The following flags will work for all browsers.
33 | *
34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
37 | *
38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
40 | *
41 | * (window as any).__Zone_enable_cross_context_check = true;
42 | *
43 | */
44 |
45 | /***************************************************************************************************
46 | * Zone JS is required by default for Angular itself.
47 | */
48 | import 'zone.js'; // Included with Angular CLI.
49 |
50 |
51 | /***************************************************************************************************
52 | * APPLICATION IMPORTS
53 | */
54 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | @import "flexmonster/flexmonster.min.css";
2 |
3 | body {
4 | margin: 0;
5 | }
6 |
7 | #app {
8 | padding: 120px 0 60px;
9 | font-family: "Open Sans", "Arial", sans-serif, serif;
10 | color: #555;
11 | line-height: 1;
12 | margin: 14px 0;
13 | font-size: 15px;
14 | -webkit-font-smoothing: antialiased !important;
15 | text-rendering: optimizeLegibility !important;
16 | }
17 |
18 | .wrap {
19 | margin: 0 auto;
20 | padding-left: 80px;
21 | padding-right: 80px;
22 | background: #fff;
23 | position: relative;
24 | display: flex;
25 | }
26 |
27 | .pivot-example-container {
28 | float: left;
29 | width: 100%;
30 | padding: 30px 40px;
31 | background: #fff;
32 | padding-top: 0;
33 | }
34 |
35 | .chart-container {
36 | margin-top: 70px;
37 | }
38 |
39 | .first-description-block {
40 | margin-top: 30px;
41 | }
42 |
43 | .description-blocks {
44 | margin: 30px 0 30px 0;
45 | max-width: 800px;
46 | }
47 |
48 | .section {
49 | margin-top: 45px;
50 | position: relative;
51 | }
52 |
53 | .section--button {
54 | display: -webkit-box;
55 | display: -webkit-flex;
56 | display: -ms-flexbox;
57 | display: flex;
58 | -webkit-box-orient: horizontal;
59 | -webkit-box-direction: normal;
60 | -webkit-flex-flow: row wrap;
61 | -ms-flex-flow: row wrap;
62 | flex-flow: row wrap;
63 | margin-bottom: 5px;
64 | }
65 |
66 | /* Button */
67 | .button-red,
68 | .button-red:focus {
69 | cursor: pointer;
70 | border: 2px solid #df3800;
71 | border-radius: 4px;
72 | color: #df3800;
73 | background: transparent;
74 | font-weight: normal;
75 | font-size: 14px;
76 | text-align: center;
77 | text-transform: uppercase;
78 | line-height: 1.35714;
79 | padding: 12px 19px;
80 | margin: 5px 5px 5px 0;
81 | position: relative;
82 | width: auto;
83 | -webkit-appearance: none;
84 | -moz-appearance: none;
85 | -webkit-box-sizing: border-box;
86 | box-sizing: border-box;
87 | -webkit-transition: all 0.3s;
88 | -o-transition: all 0.3s;
89 | transition: all 0.3s;
90 | display: -webkit-inline-box;
91 | display: -webkit-inline-flex;
92 | display: -ms-inline-flexbox;
93 | display: inline-flex;
94 | -webkit-box-pack: center;
95 | -webkit-justify-content: center;
96 | -ms-flex-pack: center;
97 | justify-content: center;
98 | -webkit-box-align: center;
99 | -webkit-align-items: center;
100 | -ms-flex-align: center;
101 | align-items: center;
102 | }
103 |
104 | .button-red:hover,
105 | .active-button {
106 | background: #df3800;
107 | color: #fff;
108 | }
109 |
110 | .button-red:focus {
111 | outline: none;
112 | }
113 |
114 | /* Toggle button and switch */
115 | .toggle-button .button-checkbox,
116 | .toggle-switch .button-checkbox {
117 | position: absolute;
118 | left: -5000px;
119 | }
120 |
121 | input[type="checkbox" i] {
122 | background-color: initial;
123 | cursor: default;
124 | appearance: checkbox;
125 | box-sizing: border-box;
126 | margin: 3px 3px 3px 4px;
127 | padding: initial;
128 | border: initial;
129 | }
130 |
131 | .toggle-button .button-checkbox-label,
132 | .toggle-switch .button-checkbox-label {
133 | cursor: pointer;
134 | display: block;
135 | background: #c1c1c1;
136 | height: 32px;
137 | width: 60px;
138 | border-radius: 50px;
139 | margin: 16px 0;
140 | position: relative;
141 | }
142 |
143 | .toggle-switch .button-checkbox-label {
144 | background: #df3800;
145 | }
146 |
147 | .toggle-button .button-checkbox:checked+.button-checkbox-label {
148 | background-color: #00a45a;
149 | }
150 |
151 | .toggle-switch .button-checkbox:checked+.button-checkbox-label {
152 | background-color: #00a45a;
153 | }
154 |
155 | .toggle-button .button-checkbox:checked+.button-checkbox-label:before,
156 | .toggle-switch .button-checkbox:checked+.button-checkbox-label:before {
157 | left: 32px;
158 | }
159 |
160 | .toggle-button .button-checkbox-label:before,
161 | .toggle-switch .button-checkbox-label:before {
162 | content: "";
163 | display: block;
164 | position: absolute;
165 | z-index: 1;
166 | top: 4px;
167 | left: 4px;
168 | border-radius: 50px;
169 | height: 24px;
170 | width: 24px;
171 | background: white;
172 | -webkit-transition: all 0.3s;
173 | -o-transition: all 0.3s;
174 | transition: all 0.3s;
175 | }
176 |
177 | .toggle-button .button-checkbox:checked+.button-checkbox-label .on {
178 | color: #454545;
179 | }
180 |
181 | .toggle-switch .button-checkbox:checked+.button-checkbox-label .on {
182 | color: #454545;
183 | }
184 |
185 | .toggle-button .button-checkbox-label .on,
186 | .toggle-switch .button-checkbox-label .on {
187 | display: block;
188 | position: absolute;
189 | z-index: 0;
190 | left: 76px;
191 | opacity: 1;
192 | min-width: max-content;
193 | line-height: 32px;
194 | font-weight: 600;
195 | font-size: 16px;
196 | color: #b1b1b1;
197 | -webkit-transition: all 0.3s;
198 | -o-transition: all 0.3s;
199 | transition: all 0.3s;
200 | }
201 |
202 | .toggle-switch .button-checkbox-label .on {
203 | color: #454545;
204 | }
205 |
206 | /* Text */
207 | .page-title {
208 | margin-top: 0;
209 | margin-bottom: 18px;
210 | font-size: 42px;
211 | font-weight: 300;
212 | line-height: 1.35714;
213 | color: #555555;
214 | }
215 |
216 | p {
217 | line-height: 1.75;
218 | }
219 |
220 | .title-link {
221 | color: #00a45a;
222 | position: relative;
223 | }
224 |
225 | .title-link:hover {
226 | text-decoration: underline;
227 | }
228 |
229 | .title-4 {
230 | font-weight: 600;
231 | font-size: 18px;
232 | line-height: 1.44444;
233 | }
234 |
235 | /* Log output */
236 | .event-logs-wrapper.fullwidth {
237 | max-width: 100%;
238 | font-size: 14px;
239 | line-height: 1.42857;
240 | }
241 |
242 | .event-logs-wrapper {
243 | position: relative;
244 | max-width: 736px;
245 | margin: 0 auto;
246 | background: #333;
247 | border-radius: 8px;
248 | display: -webkit-box;
249 | display: -webkit-flex;
250 | display: -ms-flexbox;
251 | display: flex;
252 | -webkit-box-align: center;
253 | -webkit-align-items: center;
254 | -ms-flex-align: center;
255 | align-items: center;
256 | -webkit-box-orient: horizontal;
257 | -webkit-box-direction: normal;
258 | -webkit-flex-flow: row wrap;
259 | -ms-flex-flow: row wrap;
260 | flex-flow: row wrap;
261 | padding: 20px 20px 20px 24px;
262 | font-family: "Roboto Mono", monospace;
263 | font-weight: 500;
264 | font-size: 16px;
265 | line-height: 1.25;
266 | letter-spacing: 0.02em;
267 | text-align: left;
268 | color: #fff;
269 | margin-bottom: 10px;
270 | }
271 |
272 | .content {
273 | height: 95px;
274 | -webkit-box-flex: 1;
275 | -webkit-flex: 1;
276 | -ms-flex: 1;
277 | flex: 1;
278 | white-space: nowrap;
279 | overflow-y: auto;
280 | text-align: left;
281 | overflow: auto;
282 | }
283 |
284 | .log-label {
285 | color: #8ae234;
286 | font-weight: 600;
287 | }
288 |
289 | .log-link {
290 | color: #34e2e2;
291 | position: relative;
292 | }
293 |
294 | .log-link:hover {
295 | text-decoration: underline;
296 | }
297 |
298 | /* Top menu */
299 | .mainheader {
300 | position: absolute;
301 | font-size: 0;
302 | width: 100%;
303 | min-width: 588px;
304 | top: 0;
305 | left: 0;
306 | -webkit-transition: all 0.1s;
307 | -o-transition: all 0.1s;
308 | transition: all 0.1s;
309 | z-index: 999;
310 | border-bottom: 1px solid transparent;
311 | display: block;
312 | -webkit-box-sizing: border-box;
313 | box-sizing: border-box;
314 | }
315 |
316 | .mainheader.fixed-head {
317 | background-color: #fff;
318 | border-bottom: 1px solid #cdcdcf;
319 | -webkit-box-shadow: 0px 2px 10px rgba(226, 230, 232, 0.6);
320 | box-shadow: 0px 2px 10px rgba(226, 230, 232, 0.6);
321 | z-index: 1001;
322 | }
323 |
324 | .mainheader .container-xl {
325 | display: -webkit-box;
326 | display: -webkit-flex;
327 | display: -ms-flexbox;
328 | display: flex;
329 | -webkit-box-align: center;
330 | -webkit-align-items: center;
331 | -ms-flex-align: center;
332 | align-items: center;
333 | -webkit-box-pack: center;
334 | -webkit-justify-content: center;
335 | -ms-flex-pack: center;
336 | justify-content: center;
337 | width: 100%;
338 | max-width: 1920px;
339 | min-width: 770px;
340 | margin: 0 auto;
341 | position: relative;
342 | height: 70px;
343 | }
344 |
345 | .mainheader .logo {
346 | margin-left: 32px;
347 | display: block;
348 | position: absolute;
349 | left: 0;
350 | -webkit-transition: all 0.3s;
351 | -o-transition: all 0.3s;
352 | transition: all 0.3s;
353 | }
354 |
355 | a {
356 | text-decoration: none;
357 | }
358 |
359 | .mainheader .logo img {
360 | display: block;
361 | width: 100%;
362 | }
363 |
364 | img {
365 | max-width: 100%;
366 | height: auto;
367 | border: none;
368 | }
369 |
370 | .mainheader .mainnav {
371 | margin: 0 38px;
372 | }
373 |
374 | .mainheader .mainnav,
375 | .mainheader .mainheader-icons {
376 | padding-top: 2px;
377 | }
378 |
379 | ol,
380 | ul {
381 | list-style: none;
382 | }
383 |
384 | .mainnav {
385 | margin-left: 10px;
386 | }
387 |
388 | .mainnav li {
389 | display: inline-block;
390 | vertical-align: middle;
391 | margin-right: 32px;
392 | }
393 |
394 | @media screen and (max-width: 1200px) {
395 | .mainnav li {
396 | margin-right: 20px;
397 | }
398 | }
399 |
400 | @media screen and (max-width: 1050px) {
401 | .mainnav li {
402 | display: block;
403 | margin-bottom: 3px;
404 | }
405 |
406 | .mainheader .container-xl {
407 | height: 120px;
408 | }
409 | }
410 |
411 | .mainnav li a {
412 | font-size: 15px;
413 | line-height: 1.35714;
414 | text-transform: uppercase;
415 | color: #454545;
416 | position: relative;
417 | font-weight: 600;
418 | }
419 |
420 | .mainnav li a:hover:before {
421 | opacity: 1;
422 | width: 100%;
423 | }
424 |
425 | .mainnav li a:before {
426 | bottom: -2px;
427 | width: 0;
428 | height: 2px;
429 | background: #df3800;
430 | -webkit-transition: all 0.3s;
431 | -o-transition: all 0.3s;
432 | transition: all 0.3s;
433 | opacity: 0;
434 | }
435 |
436 | .mainnav li a:before {
437 | display: block;
438 | position: absolute;
439 | left: 50%;
440 | -webkit-transform: translateX(-50%);
441 | -ms-transform: translateX(-50%);
442 | transform: translateX(-50%);
443 | }
444 |
445 | .mainnav li a:before {
446 | content: "";
447 | display: block;
448 | position: absolute;
449 | }
450 |
451 | /* Side menu */
452 | .side-menu {
453 | float: left;
454 | min-width: 240.67px;
455 | border-right: 1px solid #eaeaea;
456 | }
457 |
458 | .side-menu ol,
459 | .side-menu ul {
460 | list-style: none;
461 | margin: 0;
462 | padding: 0;
463 | }
464 |
465 | .sub-title {
466 | padding-right: 40px;
467 | color: #cdcdcd;
468 | text-align: right;
469 | font-size: 14px;
470 | margin-bottom: 5px;
471 | margin-top: 22px;
472 | }
473 |
474 | .side-menu li a {
475 | display: block;
476 | text-align: right;
477 | padding: 9px 40px 9px 0px;
478 | -webkit-transition: all 0.3s;
479 | -o-transition: all 0.3s;
480 | transition: all 0.3s;
481 | text-transform: uppercase;
482 | color: #555;
483 | font-size: 14px;
484 | line-height: 1.2;
485 | position: relative;
486 | cursor: pointer;
487 | text-decoration: none;
488 | }
489 |
490 | .side-menu li a:hover,
491 | .side-menu li a.router-link-exact-active,
492 | .side-menu li.active a.router-link-exact-active {
493 | color: #df3800;
494 | }
495 |
496 | .side-menu li a.router-link-exact-active:before,
497 | .side-menu-wrap .side-menu li.active a:before {
498 | content: " ";
499 | position: absolute;
500 | right: -1px;
501 | height: calc(100% - 16px);
502 | width: 3px;
503 | background: #df3800;
504 | }
505 |
--------------------------------------------------------------------------------
/testsServer/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const path = require('path');
3 | const app = express();
4 | const port = 4200;
5 | app.listen(port, () => console.log(`Example app listening on port ${port}!`));
6 | app.use(express.static(path.join(__dirname + '/../dist/pivot-angular/browser')));
7 |
8 |
9 | app.get('/', function (req, res) {
10 | res.sendFile(path.join(__dirname, '/../dist/pivot-angular/browser/index.html'));
11 | });
12 |
13 | app.get('/with-amcharts', function (req, res) {
14 | res.sendFile(path.join(__dirname, '/../dist/pivot-angular/browser/index.html'));
15 | });
16 |
17 | app.get('/using-api-calls', function (req, res) {
18 | res.sendFile(path.join(__dirname, '/../dist/pivot-angular/browser/index.html'));
19 | });
20 |
21 | app.get('/customizing-grid', function (req, res) {
22 | res.sendFile(path.join(__dirname, '/../dist/pivot-angular/browser/index.html'));
23 | });
24 |
25 | app.get('/customizing-toolbar', function (req, res) {
26 | res.sendFile(path.join(__dirname, '/../dist/pivot-angular/browser/index.html'));
27 | });
28 |
29 |
30 | app.get('/pivot-table-demo', function (req, res) {
31 | res.sendFile(path.join(__dirname, '/../dist/pivot-angular/browser/index.html'));
32 | });
33 |
34 |
35 | app.get('/handling-events', function (req, res) {
36 | res.sendFile(path.join(__dirname, '/../dist/pivot-angular/browser/index.html'));
37 | });
38 |
39 | app.get('/with-highcharts', function (req, res) {
40 | res.sendFile(path.join(__dirname, '/../dist/pivot-angular/browser/index.html'));
41 | });
42 |
43 | app.get('/updating-data', function (req, res) {
44 | res.sendFile(path.join(__dirname, '/../dist/pivot-angular/browser/index.html'));
45 | });
--------------------------------------------------------------------------------
/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/app",
6 | "types": []
7 | },
8 | "files": [
9 | "src/main.ts",
10 | "src/polyfills.ts"
11 | ],
12 | "include": [
13 | "src/**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "baseUrl": "./",
6 | "outDir": "./dist/out-tsc",
7 | "forceConsistentCasingInFileNames": true,
8 | "esModuleInterop": true,
9 | "strict": true,
10 | "noImplicitReturns": true,
11 | "noFallthroughCasesInSwitch": true,
12 | "sourceMap": true,
13 | "declaration": false,
14 | "experimentalDecorators": true,
15 | "moduleResolution": "node",
16 | "importHelpers": true,
17 | "target": "ES2022",
18 | "module": "es2020",
19 | "lib": [
20 | "es2018",
21 | "dom"
22 | ],
23 | "useDefineForClassFields": false
24 | },
25 | "angularCompilerOptions": {
26 | "enableI18nLegacyMessageIdFormat": false,
27 | // "strictInjectionParameters": true,
28 | // "strictInputAccessModifiers": true,
29 | // "strictTemplates": true
30 | }
31 | }
32 |
--------------------------------------------------------------------------------