├── .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 | [![Flexmonster Pivot Table & Charts](https://cdn.flexmonster.com/readmes/angular_new.webp)](https://www.flexmonster.com?r=sample_ngx) 3 | Website: [flexmonster.com](https://www.flexmonster.com?r=sample_ngx) 4 | 5 | [![Github Stars](https://img.shields.io/github/stars/flexmonster?style=social)](https://github.com/flexmonster) [![Twitter](https://img.shields.io/twitter/follow/Flexmonster?style=social)](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 | [![LinkedIn](https://img.shields.io/badge/LinkedIn-blue?style=for-the-badge&logo=linkedin&logoColor=white)](https://linkedin.com/company/flexmonster) [![YouTube](https://img.shields.io/badge/YouTube-red?style=for-the-badge&logo=youtube&logoColor=white)](https://youtube.com/user/FlexMonsterPivot) [![Twitter](https://img.shields.io/badge/Twitter-blue?style=for-the-badge&logo=twitter&logoColor=white)](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 |
2 | 3 |
4 | 5 |
6 | 7 |
8 |
9 |
-------------------------------------------------------------------------------- /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 |
2 |
    3 |
  1. 4 | PIVOT TABLE DEMO 5 |
  2. 6 |
7 |
API and Events
8 |
    9 |
  1. 10 | HANDLING EVENTS 11 |
  2. 12 |
  3. 13 | USING API CALLS 14 |
  4. 15 |
  5. 16 | UPDATING DATA 17 |
  6. 18 |
19 |
Customization
20 |
    21 |
  1. 22 | CUSTOMIZING THE TOOLBAR 23 |
  2. 24 |
  3. 25 | CUSTOMIZING THE GRID 26 |
  4. 27 |
28 |
Integration
29 |
    30 |
  1. 31 | WITH HIGHCHARTS 32 |
  2. 33 |
  3. 34 | WITH AMCHARTS 35 |
  4. 36 |
37 |
-------------------------------------------------------------------------------- /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 | 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 | 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 |
2 |
3 | 6 | 20 |
21 |
-------------------------------------------------------------------------------- /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 |
11 | 13 |
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 |
13 | 15 |
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 | 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 | 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 |
12 | 14 | 15 | 17 | 18 |
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 |
22 |
23 |
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 |
22 |
23 |
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 |
4 |

Integrate Flexmonster with Highcharts and see your data from a new perspective: 5 | Integration with Highcharts. 7 |

8 |
9 | 10 |
11 | 19 | 20 |
21 | 22 |
23 |
24 |
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 | --------------------------------------------------------------------------------