├── .editorconfig ├── .gitignore ├── .yarnrc.yml ├── README.md ├── angular.json ├── examples └── angular-cli │ ├── .browserslistrc │ ├── .editorconfig │ ├── .gitignore │ ├── README.md │ ├── angular.json │ ├── karma.conf.js │ ├── package.json │ ├── src │ ├── app │ │ ├── app.component.css │ │ ├── app.component.html │ │ ├── app.component.spec.ts │ │ ├── app.component.ts │ │ └── app.module.ts │ ├── assets │ │ └── .gitkeep │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ ├── polyfills.ts │ ├── styles.css │ └── test.ts │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ └── yarn.lock ├── package.json ├── projects └── amcharts │ └── amcharts3-angular │ ├── karma.conf.js │ ├── ng-package.json │ ├── package.json │ ├── src │ ├── lib │ │ ├── amcharts3-angular.directive.ts │ │ ├── amcharts3-angular.module.ts │ │ └── amcharts3-angular.service.ts │ ├── public-api.ts │ └── test.ts │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ └── tsconfig.spec.json ├── tsconfig.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | /.yarn 10 | 11 | # dependencies 12 | /node_modules 13 | 14 | # profiling files 15 | chrome-profiler-events*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | yarn-error.log 41 | testem.log 42 | /typings 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Official Angular plugin for amCharts V3 2 | 3 | Installation 4 | ============ 5 | 6 | * If you are using Angular 12 or higher: 7 | 8 | ``` 9 | npm install @amcharts/amcharts3-angular --save 10 | ``` 11 | 12 | * If you are using Angular 5 to 11: 13 | 14 | ``` 15 | npm install @amcharts/amcharts3-angular^2.2.5 --save 16 | ``` 17 | 18 | * If you are using Angular 2 to 4: 19 | 20 | ``` 21 | npm install @amcharts/amcharts3-angular@^1.5.0 --save 22 | ``` 23 | 24 | How to use 25 | ========== 26 | 27 | 1) In your `index.html` file, load the amCharts library using ` 31 | 32 | 33 | ``` 34 | 35 | If you are using stock charts, you should use these ` 39 | 40 | 41 | 42 | ``` 43 | 44 | If you are using maps, you should use these ` 48 | 49 | 50 | ``` 51 | 52 | If you are using other chart types, you should change `serial.js` to the chart type that you are using: 53 | 54 | ```html 55 | 56 | 57 | 58 | ``` 59 | 60 | ---- 61 | 62 | 2) In your app component, import the `AmChartsModule` module and add it to the `imports`: 63 | 64 | ```typescript 65 | import { Component } from '@angular/core'; 66 | import { CommonModule } from '@angular/common'; 67 | import { RouterOutlet } from '@angular/router'; 68 | import { AmChart, AmChartsService, AmChartsModule } from '@amcharts/amcharts3-angular'; 69 | 70 | @Component({ 71 | selector: 'app-root', 72 | standalone: true, 73 | // Add the import here 74 | imports: [CommonModule, RouterOutlet, AmChartsModule], 75 | templateUrl: './app.component.html', 76 | styleUrl: './app.component.css' 77 | }) 78 | export class AppComponent { 79 | ``` 80 | 81 | ---- 82 | 83 | 3) Inject the `AmChartsService` into your app component, create a `
` element with an `id`, then use the `makeChart` method to create the chart: 84 | 85 | ```html 86 |
87 | ``` 88 | 89 | ```typescript 90 | import { Component } from '@angular/core'; 91 | import { CommonModule } from '@angular/common'; 92 | import { RouterOutlet } from '@angular/router'; 93 | import { AmChart, AmChartsService, AmChartsModule } from '@amcharts/amcharts3-angular'; 94 | 95 | @Component({ 96 | selector: 'app-root', 97 | standalone: true, 98 | // Add the import here 99 | imports: [CommonModule, RouterOutlet, AmChartsModule], 100 | templateUrl: './app.component.html', 101 | styleUrl: './app.component.css' 102 | }) 103 | export class AppComponent { 104 | private chart: AmChart | undefined; 105 | 106 | // Inject the service here 107 | constructor(private AmCharts: AmChartsService) {} 108 | 109 | ngAfterViewInit() { 110 | this.chart = this.AmCharts.makeChart("chartdiv", { 111 | "type": "serial", 112 | "theme": "light", 113 | "dataProvider": [] 114 | ... 115 | }); 116 | } 117 | 118 | ngOnDestroy() { 119 | if (this.chart) { 120 | this.AmCharts.destroyChart(this.chart); 121 | } 122 | } 123 | } 124 | ``` 125 | 126 | The first argument to `makeChart` must be the same as the `
`'s `id`. The `id` can be whatever you want, but if you display multiple charts each chart must have a different `id` 127 | 128 | When you are finished with the chart, you must call the `destroyChart` method. It's good to put this inside the `ngOnDestroy` method. 129 | 130 | ---- 131 | 132 | 4) If you want to change the chart after the chart has been created, you must make the changes using the `updateChart` method: 133 | 134 | ```typescript 135 | // This must be called when making any changes to the chart 136 | this.AmCharts.updateChart(this.chart, () => { 137 | // Change whatever properties you want 138 | this.chart.dataProvider = []; 139 | }); 140 | ``` 141 | 142 | ---- 143 | 144 | 5) If you want to add event listeners, use the `addListener` method: 145 | 146 | ```typescript 147 | this.AmCharts.addListener(this.chart, "init", (e) => { 148 | // Do stuff when the event happens 149 | }); 150 | ``` 151 | 152 | The `addListener` method returns a function which you can call if you want to stop listening to the event: 153 | 154 | ```typescript 155 | const stop = this.AmCharts.addListener(this.chart, "init", (e) => { 156 | // Do stuff when the event happens 157 | }); 158 | 159 | // Call the stop function when you want to stop listening to the event 160 | stop(); 161 | ``` 162 | 163 | ---- 164 | 165 | 6) Rather than using `AmChartsService` you can instead use the `` tag in your template: 166 | 167 | ```typescript 168 | @Component({ 169 | template: `` 170 | }) 171 | export class AppComponent { 172 | public options = { 173 | "type": "serial", 174 | "theme": "light", 175 | "dataProvider": [] 176 | ... 177 | }; 178 | } 179 | ``` 180 | 181 | This is much easier than using `AmChartsService`, but you cannot call the `AmCharts` methods, and it is difficult to change the chart options, so it works best for charts which do not change. 182 | 183 | ---- 184 | 185 | You can see some examples in the `examples` directory. 186 | 187 | ## Changelog 188 | 189 | ### 3.0.7 190 | * Adding in support for Angular 19 191 | 192 | ### 3.0.6 193 | * Adding in support for Angular 18 194 | 195 | ### 3.0.5 196 | * Adding in support for Angular 17 197 | 198 | ### 3.0.4 199 | * Adding in support for Angular 16 200 | 201 | ### 3.0.3 202 | * Adding in support for Angular 15 203 | 204 | ### 3.0.2 205 | * Adding in support for Angular 14 206 | 207 | ### 3.0.1 208 | * Adding in support for Angular 13 209 | 210 | ### 3.0.0 211 | * Adding in support for Angular 12 Ivy 212 | 213 | ### 2.2.5 214 | * Upgrading to Angular 9 - 12 215 | 216 | ### 2.2.4 217 | * Upgrading to Angular 8 218 | 219 | ### 2.2.3 220 | * Upgrading to Angular 7 221 | 222 | ### 2.2.1 223 | * Adding in `StockEvent` and `StockLegend` constructors for dynamically adding stock events/legend. 224 | 225 | ### 2.2.0 226 | * Adding in `StockPanel` and `StockGraph` constructors for dynamically adding stock panels/graphs. 227 | 228 | ### 2.1.0 229 | * Adding in `addInitHandler`, `addPrefix`, `clear`, `formatDate`, `formatNumber`, and `stringToDate` methods to `AmChartsService` 230 | 231 | ### 2.0.0 232 | * Upgrading to Angular 5 233 | * Removing the Quickstart Seed example 234 | 235 | ### 1.5.0 236 | * Adding in `addListener` method 237 | 238 | ### 1.4.0 239 | * Undeprecating the `AmChartsDirective` 240 | * Adding in `delay` option for `AmChartsDirective` 241 | 242 | ### 1.3.0 243 | * Adding in all of the global `AmCharts` properties to the `AmChartsService` 244 | 245 | ### 1.2.1 246 | * Updating to the latest version of the Angular compiler 247 | 248 | ### 1.2.0 249 | * Adding in support for Angular 4 250 | * Deprecating the `` element in favor of the new `AmChartsService` 251 | 252 | ### 1.1.0 253 | * Various fixes 254 | * Adding examples 255 | 256 | ### 1.0.0 257 | * Initial release 258 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "@amcharts/amcharts3-angular": { 7 | "projectType": "library", 8 | "root": "projects/amcharts/amcharts3-angular", 9 | "sourceRoot": "projects/amcharts/amcharts3-angular/src", 10 | "prefix": "lib", 11 | "architect": { 12 | "build": { 13 | "builder": "@angular-devkit/build-angular:ng-packagr", 14 | "options": { 15 | "project": "projects/amcharts/amcharts3-angular/ng-package.json" 16 | }, 17 | "configurations": { 18 | "production": { 19 | "tsConfig": "projects/amcharts/amcharts3-angular/tsconfig.lib.prod.json" 20 | }, 21 | "development": { 22 | "tsConfig": "projects/amcharts/amcharts3-angular/tsconfig.lib.json" 23 | } 24 | }, 25 | "defaultConfiguration": "production" 26 | }, 27 | "test": { 28 | "builder": "@angular-devkit/build-angular:karma", 29 | "options": { 30 | "main": "projects/amcharts/amcharts3-angular/src/test.ts", 31 | "tsConfig": "projects/amcharts/amcharts3-angular/tsconfig.spec.json", 32 | "karmaConfig": "projects/amcharts/amcharts3-angular/karma.conf.js" 33 | } 34 | } 35 | } 36 | } 37 | }, 38 | "defaultProject": "@amcharts/amcharts3-angular" 39 | } 40 | -------------------------------------------------------------------------------- /examples/angular-cli/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /examples/angular-cli/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /examples/angular-cli/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | 16 | # IDEs and editors 17 | /.idea 18 | .project 19 | .classpath 20 | .c9/ 21 | *.launch 22 | .settings/ 23 | *.sublime-workspace 24 | 25 | # IDE - VSCode 26 | .vscode/* 27 | !.vscode/settings.json 28 | !.vscode/tasks.json 29 | !.vscode/launch.json 30 | !.vscode/extensions.json 31 | .history/* 32 | 33 | # misc 34 | /.sass-cache 35 | /connect.lock 36 | /coverage 37 | /libpeerconnection.log 38 | npm-debug.log 39 | yarn-error.log 40 | testem.log 41 | /typings 42 | 43 | # System Files 44 | .DS_Store 45 | Thumbs.db 46 | -------------------------------------------------------------------------------- /examples/angular-cli/README.md: -------------------------------------------------------------------------------- 1 | # AngularCli 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.2.10. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 28 | -------------------------------------------------------------------------------- /examples/angular-cli/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "angular-cli": { 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-devkit/build-angular:browser", 19 | "options": { 20 | "outputPath": "dist/angular-cli", 21 | "index": "src/index.html", 22 | "main": "src/main.ts", 23 | "polyfills": "src/polyfills.ts", 24 | "tsConfig": "tsconfig.app.json", 25 | "assets": [ 26 | "src/favicon.ico", 27 | "src/assets" 28 | ], 29 | "styles": [ 30 | "src/styles.css" 31 | ], 32 | "scripts": [] 33 | }, 34 | "configurations": { 35 | "production": { 36 | "budgets": [ 37 | { 38 | "type": "initial", 39 | "maximumWarning": "500kb", 40 | "maximumError": "1mb" 41 | }, 42 | { 43 | "type": "anyComponentStyle", 44 | "maximumWarning": "2kb", 45 | "maximumError": "4kb" 46 | } 47 | ], 48 | "fileReplacements": [ 49 | { 50 | "replace": "src/environments/environment.ts", 51 | "with": "src/environments/environment.prod.ts" 52 | } 53 | ], 54 | "outputHashing": "all" 55 | }, 56 | "development": { 57 | "buildOptimizer": false, 58 | "optimization": false, 59 | "vendorChunk": true, 60 | "extractLicenses": false, 61 | "sourceMap": true, 62 | "namedChunks": true 63 | } 64 | }, 65 | "defaultConfiguration": "production" 66 | }, 67 | "serve": { 68 | "builder": "@angular-devkit/build-angular:dev-server", 69 | "configurations": { 70 | "production": { 71 | "browserTarget": "angular-cli:build:production" 72 | }, 73 | "development": { 74 | "browserTarget": "angular-cli:build:development" 75 | } 76 | }, 77 | "defaultConfiguration": "development" 78 | }, 79 | "extract-i18n": { 80 | "builder": "@angular-devkit/build-angular:extract-i18n", 81 | "options": { 82 | "browserTarget": "angular-cli:build" 83 | } 84 | }, 85 | "test": { 86 | "builder": "@angular-devkit/build-angular:karma", 87 | "options": { 88 | "main": "src/test.ts", 89 | "polyfills": "src/polyfills.ts", 90 | "tsConfig": "tsconfig.spec.json", 91 | "karmaConfig": "karma.conf.js", 92 | "assets": [ 93 | "src/favicon.ico", 94 | "src/assets" 95 | ], 96 | "styles": [ 97 | "src/styles.css" 98 | ], 99 | "scripts": [] 100 | } 101 | } 102 | } 103 | } 104 | }, 105 | "defaultProject": "angular-cli" 106 | } 107 | -------------------------------------------------------------------------------- /examples/angular-cli/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, './coverage/angular-cli'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /examples/angular-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-cli", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "watch": "ng build --watch --configuration development", 9 | "test": "ng test" 10 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@amcharts/amcharts3-angular": "^3.0.0", 14 | "@angular/animations": "~12.2.0", 15 | "@angular/common": "~12.2.0", 16 | "@angular/compiler": "~12.2.0", 17 | "@angular/core": "~12.2.0", 18 | "@angular/forms": "~12.2.0", 19 | "@angular/platform-browser": "~12.2.0", 20 | "@angular/platform-browser-dynamic": "~12.2.0", 21 | "@angular/router": "~12.2.0", 22 | "rxjs": "~6.6.0", 23 | "tslib": "^2.3.0", 24 | "zone.js": "~0.11.4" 25 | }, 26 | "devDependencies": { 27 | "@angular-devkit/build-angular": "~12.2.10", 28 | "@angular/cli": "~12.2.10", 29 | "@angular/compiler-cli": "~12.2.0", 30 | "@types/jasmine": "~3.8.0", 31 | "@types/node": "^12.11.1", 32 | "jasmine-core": "~3.8.0", 33 | "karma": "~6.3.0", 34 | "karma-chrome-launcher": "~3.1.0", 35 | "karma-coverage": "~2.0.3", 36 | "karma-jasmine": "~4.0.0", 37 | "karma-jasmine-html-reporter": "~1.7.0", 38 | "typescript": "~4.3.5" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/angular-cli/src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amcharts/amcharts3-angular2/a62de6b8a3e9ce87a3b5313a5c1d27648a4da5d5/examples/angular-cli/src/app/app.component.css -------------------------------------------------------------------------------- /examples/angular-cli/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /examples/angular-cli/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | declarations: [ 8 | AppComponent 9 | ], 10 | }).compileComponents(); 11 | }); 12 | 13 | it('should create the app', () => { 14 | const fixture = TestBed.createComponent(AppComponent); 15 | const app = fixture.componentInstance; 16 | expect(app).toBeTruthy(); 17 | }); 18 | 19 | it(`should have as title 'angular-cli'`, () => { 20 | const fixture = TestBed.createComponent(AppComponent); 21 | const app = fixture.componentInstance; 22 | expect(app.title).toEqual('angular-cli'); 23 | }); 24 | 25 | it('should render title', () => { 26 | const fixture = TestBed.createComponent(AppComponent); 27 | fixture.detectChanges(); 28 | const compiled = fixture.nativeElement as HTMLElement; 29 | expect(compiled.querySelector('.content span')?.textContent).toContain('angular-cli app is running!'); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /examples/angular-cli/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { AmChart, AmChartsService } from '@amcharts/amcharts3-angular'; 3 | 4 | @Component({ 5 | selector: 'app-root', 6 | templateUrl: './app.component.html', 7 | styleUrls: ['./app.component.css'] 8 | }) 9 | export class AppComponent { 10 | public options: any; 11 | private chart: AmChart | undefined; 12 | private timer: number | undefined; 13 | 14 | constructor(private AmCharts: AmChartsService) {} 15 | 16 | makeRandomDataProvider() { 17 | const dataProvider = []; 18 | 19 | // Generate random data 20 | for (let year = 1950; year <= 2005; ++year) { 21 | dataProvider.push({ 22 | year: '' + year, 23 | value: Math.floor(Math.random() * 100) - 50 24 | }); 25 | } 26 | 27 | return dataProvider; 28 | } 29 | 30 | makeOptions(dataProvider: object) { 31 | return { 32 | 'type': 'serial', 33 | 'theme': 'light', 34 | 'marginTop': 0, 35 | 'marginRight': 80, 36 | 'dataProvider': dataProvider, 37 | 'valueAxes': [{ 38 | 'axisAlpha': 0, 39 | 'position': 'left' 40 | }], 41 | 'graphs': [{ 42 | 'id': 'g1', 43 | 'balloonText': '[[category]]
[[value]]', 44 | 'bullet': 'round', 45 | 'bulletSize': 8, 46 | 'lineColor': '#d1655d', 47 | 'lineThickness': 2, 48 | 'negativeLineColor': '#637bb6', 49 | 'type': 'smoothedLine', 50 | 'valueField': 'value' 51 | }], 52 | 'chartScrollbar': { 53 | 'graph': 'g1', 54 | 'gridAlpha': 0, 55 | 'color': '#888888', 56 | 'scrollbarHeight': 55, 57 | 'backgroundAlpha': 0, 58 | 'selectedBackgroundAlpha': 0.1, 59 | 'selectedBackgroundColor': '#888888', 60 | 'graphFillAlpha': 0, 61 | 'autoGridCount': true, 62 | 'selectedGraphFillAlpha': 0, 63 | 'graphLineAlpha': 0.2, 64 | 'graphLineColor': '#c2c2c2', 65 | 'selectedGraphLineColor': '#888888', 66 | 'selectedGraphLineAlpha': 1 67 | }, 68 | 'chartCursor': { 69 | 'categoryBalloonDateFormat': 'YYYY', 70 | 'cursorAlpha': 0, 71 | 'valueLineEnabled': true, 72 | 'valueLineBalloonEnabled': true, 73 | 'valueLineAlpha': 0.5, 74 | 'fullWidth': true 75 | }, 76 | 'dataDateFormat': 'YYYY', 77 | 'categoryField': 'year', 78 | 'categoryAxis': { 79 | 'minPeriod': 'YYYY', 80 | 'parseDates': true, 81 | 'minorGridAlpha': 0.1, 82 | 'minorGridEnabled': true 83 | }, 84 | 'export': { 85 | 'enabled': true 86 | } 87 | }; 88 | } 89 | 90 | ngOnInit() { 91 | // Create chartdiv1 92 | this.options = this.makeOptions(this.makeRandomDataProvider()); 93 | 94 | // Create chartdiv2 95 | this.chart = this.AmCharts.makeChart('chartdiv', this.makeOptions(this.makeRandomDataProvider())); 96 | 97 | this.timer = window.setInterval(() => { 98 | // Update chartdiv1 99 | this.options = this.makeOptions(this.makeRandomDataProvider()); 100 | 101 | // Update chartdiv2 102 | this.AmCharts.updateChart(this.chart!, () => { 103 | this.chart!["dataProvider"] = this.makeRandomDataProvider(); 104 | }); 105 | }, 3000); 106 | } 107 | 108 | ngOnDestroy() { 109 | clearInterval(this.timer); 110 | 111 | if (this.chart) { 112 | this.AmCharts.destroyChart(this.chart); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /examples/angular-cli/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { AmChartsModule } from '@amcharts/amcharts3-angular'; 4 | import { AppComponent } from './app.component'; 5 | 6 | @NgModule({ 7 | declarations: [ 8 | AppComponent 9 | ], 10 | imports: [ 11 | BrowserModule, 12 | AmChartsModule, 13 | ], 14 | providers: [], 15 | bootstrap: [AppComponent] 16 | }) 17 | export class AppModule { } 18 | -------------------------------------------------------------------------------- /examples/angular-cli/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amcharts/amcharts3-angular2/a62de6b8a3e9ce87a3b5313a5c1d27648a4da5d5/examples/angular-cli/src/assets/.gitkeep -------------------------------------------------------------------------------- /examples/angular-cli/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /examples/angular-cli/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 | -------------------------------------------------------------------------------- /examples/angular-cli/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amcharts/amcharts3-angular2/a62de6b8a3e9ce87a3b5313a5c1d27648a4da5d5/examples/angular-cli/src/favicon.ico -------------------------------------------------------------------------------- /examples/angular-cli/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AngularCli 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/angular-cli/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 | -------------------------------------------------------------------------------- /examples/angular-cli/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 | * IE11 requires the following for NgClass support on SVG elements 23 | */ 24 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 25 | 26 | /** 27 | * Web Animations `@angular/platform-browser/animations` 28 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 29 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 30 | */ 31 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 32 | 33 | /** 34 | * By default, zone.js will patch all possible macroTask and DomEvents 35 | * user can disable parts of macroTask/DomEvents patch by setting following flags 36 | * because those flags need to be set before `zone.js` being loaded, and webpack 37 | * will put import in the top of bundle, so user need to create a separate file 38 | * in this directory (for example: zone-flags.ts), and put the following flags 39 | * into that file, and then add the following code before importing zone.js. 40 | * import './zone-flags'; 41 | * 42 | * The flags allowed in zone-flags.ts are listed here. 43 | * 44 | * The following flags will work for all browsers. 45 | * 46 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 47 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 48 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 49 | * 50 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 51 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 52 | * 53 | * (window as any).__Zone_enable_cross_context_check = true; 54 | * 55 | */ 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js'; // Included with Angular CLI. 61 | 62 | 63 | /*************************************************************************************************** 64 | * APPLICATION IMPORTS 65 | */ 66 | -------------------------------------------------------------------------------- /examples/angular-cli/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /examples/angular-cli/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: { 11 | context(path: string, deep?: boolean, filter?: RegExp): { 12 | keys(): string[]; 13 | (id: string): T; 14 | }; 15 | }; 16 | 17 | // First, initialize the Angular testing environment. 18 | getTestBed().initTestEnvironment( 19 | BrowserDynamicTestingModule, 20 | platformBrowserDynamicTesting(), 21 | { teardown: { destroyAfterEach: true }}, 22 | ); 23 | 24 | // Then we find all the tests. 25 | const context = require.context('./', true, /\.spec\.ts$/); 26 | // And load the modules. 27 | context.keys().map(context); 28 | -------------------------------------------------------------------------------- /examples/angular-cli/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 | -------------------------------------------------------------------------------- /examples/angular-cli/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 | "strict": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "sourceMap": true, 12 | "declaration": false, 13 | "downlevelIteration": true, 14 | "experimentalDecorators": true, 15 | "moduleResolution": "node", 16 | "importHelpers": true, 17 | "target": "es2017", 18 | "module": "es2020", 19 | "lib": [ 20 | "es2018", 21 | "dom" 22 | ] 23 | }, 24 | "angularCompilerOptions": { 25 | "enableI18nLegacyMessageIdFormat": false, 26 | "strictInjectionParameters": true, 27 | "strictInputAccessModifiers": true, 28 | "strictTemplates": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/angular-cli/tsconfig.spec.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/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "amcharts3-angular", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build --configuration production && cpr README.md dist/amcharts/amcharts3-angular/README.md", 8 | "publish": "cd dist/amcharts/amcharts3-angular && npm publish", 9 | "watch": "ng build --watch --configuration development", 10 | "test": "ng test" 11 | }, 12 | "private": true, 13 | "dependencies": { 14 | "@angular/animations": "~12.2.0", 15 | "@angular/common": "~12.2.0", 16 | "@angular/compiler": "~12.2.0", 17 | "@angular/core": "~12.2.0", 18 | "@angular/forms": "~12.2.0", 19 | "@angular/platform-browser": "~12.2.0", 20 | "@angular/platform-browser-dynamic": "~12.2.0", 21 | "@angular/router": "~12.2.0", 22 | "rxjs": "~6.6.0", 23 | "tslib": "^2.3.0", 24 | "zone.js": "~0.11.4" 25 | }, 26 | "devDependencies": { 27 | "@angular-devkit/build-angular": "~12.2.10", 28 | "@angular/cli": "~12.2.10", 29 | "@angular/compiler-cli": "~12.2.0", 30 | "@types/jasmine": "~3.8.0", 31 | "@types/node": "^12.11.1", 32 | "cpr": "^3.0.1", 33 | "jasmine-core": "~3.8.0", 34 | "karma": "~6.3.0", 35 | "karma-chrome-launcher": "~3.1.0", 36 | "karma-coverage": "~2.0.3", 37 | "karma-jasmine": "~4.0.0", 38 | "karma-jasmine-html-reporter": "~1.7.0", 39 | "ng-packagr": "^12.1.1", 40 | "typescript": "~4.3.5" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /projects/amcharts/amcharts3-angular/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, '../../../coverage/amcharts/amcharts3-angular'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /projects/amcharts/amcharts3-angular/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../../dist/amcharts/amcharts3-angular", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/amcharts/amcharts3-angular/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@amcharts/amcharts3-angular", 3 | "version": "3.0.7", 4 | "description": "Official Angular 2 plugin for amCharts V3", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/amcharts/amcharts3-angular2.git" 8 | }, 9 | "peerDependencies": { 10 | "@angular/core": "^12.2.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 11 | }, 12 | "dependencies": { 13 | "tslib": "^2.3.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /projects/amcharts/amcharts3-angular/src/lib/amcharts3-angular.directive.ts: -------------------------------------------------------------------------------- 1 | import type { SimpleChanges, AfterViewInit, OnChanges, OnDestroy } from '@angular/core'; 2 | import type { AmChart } from './amcharts3-angular.service'; 3 | import { Directive, ElementRef, Input, NgZone } from '@angular/core'; 4 | import { AmChartsService } from './amcharts3-angular.service'; 5 | 6 | 7 | function getType(x: any) { 8 | // TODO make this faster ? 9 | return {}.toString.call(x); 10 | } 11 | 12 | function hasOwnKey(obj: any, key: any) { 13 | return {}.hasOwnProperty.call(obj, key); 14 | } 15 | 16 | 17 | function copyObject(x: any) { 18 | const output: any = {}; 19 | 20 | // TODO use Object.keys ? 21 | for (const key in x) { 22 | if (hasOwnKey(x, key)) { 23 | output[key] = copy(x[key]); 24 | } 25 | } 26 | 27 | return output; 28 | } 29 | 30 | function copyArray(x: any) { 31 | const length = x.length; 32 | 33 | const output = new Array(length); 34 | 35 | for (let i = 0; i < length; ++i) { 36 | output[i] = copy(x[i]); 37 | } 38 | 39 | return output; 40 | } 41 | 42 | // TODO can this be made faster ? 43 | // TODO what about regexps, etc. ? 44 | function copy(x: any) { 45 | switch (getType(x)) { 46 | case '[object Array]': 47 | return copyArray(x); 48 | 49 | case '[object Object]': 50 | return copyObject(x); 51 | 52 | // TODO is this necessary ? 53 | case '[object Date]': 54 | return new Date(x.getTime()); 55 | 56 | default: 57 | return x; 58 | } 59 | } 60 | 61 | 62 | function isNaN(x: any) { 63 | return x !== x; 64 | } 65 | 66 | function isNumberEqual(x: any, y: any) { 67 | return x === y || (isNaN(x) && isNaN(y)); 68 | } 69 | 70 | 71 | function removeChartListeners(chart: any, x: any, y: any) { 72 | if (x !== y) { 73 | // TODO is this necessary ? 74 | if (x == null) { 75 | x = []; 76 | } 77 | 78 | // TODO is this necessary ? 79 | if (y == null) { 80 | y = []; 81 | } 82 | 83 | const xLength = x.length; 84 | const yLength = y.length; 85 | 86 | for (let i = 0; i < xLength; ++i) { 87 | const xValue = x[i]; 88 | 89 | let has = false; 90 | 91 | // TODO make this faster ? 92 | for (let j = 0; j < yLength; ++j) { 93 | const yValue = y[j]; 94 | 95 | // TODO is this correct ? 96 | if (xValue.event === yValue.event && 97 | xValue.method === yValue.method) { 98 | has = true; 99 | break; 100 | } 101 | } 102 | 103 | if (!has) { 104 | // TODO is this correct ? 105 | chart.removeListener(chart, xValue.event, xValue.method); 106 | } 107 | } 108 | } 109 | } 110 | 111 | 112 | function updateArray(a: any, x: any, y: any) { 113 | let didUpdate = false; 114 | 115 | if (x !== y) { 116 | const xLength = x.length; 117 | const yLength = y.length; 118 | 119 | if (xLength !== yLength) { 120 | a.length = yLength; 121 | didUpdate = true; 122 | } 123 | 124 | for (let i = 0; i < yLength; ++i) { 125 | if (i < xLength) { 126 | if (update(a, i, x[i], y[i])) { 127 | didUpdate = true; 128 | } 129 | 130 | } else { 131 | // TODO make this faster ? 132 | a[i] = copy(y[i]); 133 | // TODO is this necessary ? 134 | didUpdate = true; 135 | } 136 | } 137 | } 138 | 139 | return didUpdate; 140 | } 141 | 142 | 143 | function update(obj: any, key: any, x: any, y: any) { 144 | let didUpdate = false; 145 | 146 | if (x !== y) { 147 | const xType = getType(x); 148 | const yType = getType(y); 149 | 150 | if (xType === yType) { 151 | switch (xType) { 152 | case '[object Array]': 153 | if (updateArray(obj[key], x, y)) { 154 | didUpdate = true; 155 | } 156 | break; 157 | 158 | case '[object Object]': 159 | if (updateObject(obj[key], x, y)) { 160 | didUpdate = true; 161 | } 162 | break; 163 | 164 | case '[object Date]': 165 | if (x.getTime() !== y.getTime()) { 166 | // TODO make this faster ? 167 | obj[key] = copy(y); 168 | didUpdate = true; 169 | } 170 | break; 171 | 172 | case '[object Number]': 173 | if (!isNumberEqual(x, y)) { 174 | // TODO is the copy necessary ? 175 | obj[key] = copy(y); 176 | didUpdate = true; 177 | } 178 | break; 179 | 180 | default: 181 | if (x !== y) { 182 | // TODO is the copy necessary ? 183 | obj[key] = copy(y); 184 | didUpdate = true; 185 | } 186 | break; 187 | } 188 | 189 | // TODO is this correct ? 190 | } else { 191 | // TODO make this faster ? 192 | obj[key] = copy(y); 193 | didUpdate = true; 194 | } 195 | } 196 | 197 | return didUpdate; 198 | } 199 | 200 | function updateObject(chart: any, oldObj: any, newObj: any) { 201 | let didUpdate = false; 202 | 203 | if (oldObj !== newObj) { 204 | // TODO use Object.keys ? 205 | for (const key in newObj) { 206 | if (hasOwnKey(newObj, key)) { 207 | // TODO make this faster ? 208 | if (hasOwnKey(oldObj, key)) { 209 | // TODO should this count as an update ? 210 | if (key === 'listeners') { 211 | // TODO make this faster ? 212 | removeChartListeners(chart, oldObj[key], newObj[key]); 213 | } 214 | 215 | if (update(chart, key, oldObj[key], newObj[key])) { 216 | didUpdate = true; 217 | } 218 | 219 | } else { 220 | // TODO make this faster ? 221 | chart[key] = copy(newObj[key]); 222 | didUpdate = true; 223 | } 224 | } 225 | } 226 | 227 | // TODO use Object.keys ? 228 | for (const key in oldObj) { 229 | if (hasOwnKey(oldObj, key) && !hasOwnKey(newObj, key)) { 230 | if (key === 'listeners') { 231 | removeChartListeners(chart, oldObj[key], []); 232 | } 233 | 234 | delete chart[key]; 235 | didUpdate = true; 236 | } 237 | } 238 | } 239 | 240 | return didUpdate; 241 | } 242 | 243 | 244 | @Directive({ 245 | selector: 'amCharts' 246 | }) 247 | export class AmChartsDirective implements AfterViewInit, OnChanges, OnDestroy { 248 | @Input() id!: string; 249 | @Input() options: any; // TODO better type for this 250 | @Input() delay = 0; 251 | 252 | private chart: AmChart | undefined; 253 | 254 | constructor(private el: ElementRef, private AmCharts: AmChartsService, private zone: NgZone) {} 255 | 256 | ngAfterViewInit() { 257 | // AmCharts mutates the config object, so we have to make a deep copy to prevent that 258 | const props = copy(this.options); 259 | 260 | const el = this.el.nativeElement; 261 | 262 | el.id = this.id; 263 | el.style.display = 'block'; 264 | 265 | this.chart = this.AmCharts.makeChart(this.id, props, this.delay); 266 | } 267 | 268 | // TODO is this correct ? 269 | ngOnChanges(x: SimpleChanges) { 270 | const el = this.el.nativeElement; 271 | 272 | if (x.id) { 273 | el.id = x.id.currentValue; 274 | } 275 | 276 | if (x.options) { 277 | // Update the chart after init 278 | if (this.chart) { 279 | // This is needed to avoid triggering ngDoCheck 280 | this.zone.runOutsideAngular(() => { 281 | const didUpdate = updateObject(this.chart, x.options.previousValue, x.options.currentValue); 282 | 283 | // TODO make this faster 284 | if (didUpdate) { 285 | this.chart!.validateNow(true); 286 | } 287 | }); 288 | } 289 | } 290 | } 291 | 292 | ngOnDestroy() { 293 | if (this.chart) { 294 | this.AmCharts.destroyChart(this.chart); 295 | } 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /projects/amcharts/amcharts3-angular/src/lib/amcharts3-angular.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { AmChartsDirective } from './amcharts3-angular.directive'; 3 | import { AmChartsService } from './amcharts3-angular.service'; 4 | 5 | @NgModule({ 6 | declarations: [ 7 | AmChartsDirective 8 | ], 9 | exports: [ 10 | AmChartsDirective 11 | ], 12 | providers: [ 13 | AmChartsService 14 | ] 15 | }) 16 | export class AmChartsModule {} 17 | -------------------------------------------------------------------------------- /projects/amcharts/amcharts3-angular/src/lib/amcharts3-angular.service.ts: -------------------------------------------------------------------------------- 1 | import { NgZone, Injectable } from '@angular/core'; 2 | 3 | 4 | // TODO better type for this 5 | declare const AmCharts: any; 6 | 7 | 8 | export interface AmChart { 9 | [key: string]: any; 10 | } 11 | 12 | export interface AmEvent { 13 | [key: string]: any; 14 | } 15 | 16 | export interface Formatter { 17 | precision: number; 18 | decimalSeparator: string; 19 | thousandsSeparator: string; 20 | } 21 | 22 | 23 | export declare class StockPanel { 24 | constructor(); 25 | [key: string]: any; 26 | } 27 | 28 | export declare class StockGraph { 29 | constructor(); 30 | [key: string]: any; 31 | } 32 | 33 | export declare class StockEvent { 34 | constructor(); 35 | [key: string]: any; 36 | } 37 | 38 | export declare class StockLegend { 39 | constructor(); 40 | [key: string]: any; 41 | } 42 | 43 | 44 | @Injectable({ 45 | providedIn: 'root' 46 | }) 47 | export class AmChartsService { 48 | constructor(private zone: NgZone) {} 49 | 50 | 51 | get StockPanel(): typeof StockPanel { 52 | return AmCharts.StockPanel; 53 | } 54 | 55 | get StockGraph(): typeof StockGraph { 56 | return AmCharts.StockGraph; 57 | } 58 | 59 | get StockEvent(): typeof StockEvent { 60 | return AmCharts.StockEvent; 61 | } 62 | 63 | get StockLegend(): typeof StockLegend { 64 | return AmCharts.StockLegend; 65 | } 66 | 67 | 68 | get baseHref(): boolean { 69 | return AmCharts.baseHref; 70 | } 71 | 72 | set baseHref(v: boolean) { 73 | AmCharts.baseHref = v; 74 | } 75 | 76 | 77 | get useUTC(): boolean { 78 | return AmCharts.useUTC; 79 | } 80 | 81 | set useUTC(v: boolean) { 82 | AmCharts.useUTC = v; 83 | } 84 | 85 | 86 | get dayNames(): Array { 87 | return AmCharts.dayNames; 88 | } 89 | 90 | set dayNames(v: Array) { 91 | AmCharts.dayNames = v; 92 | } 93 | 94 | 95 | get monthNames(): Array { 96 | return AmCharts.monthNames; 97 | } 98 | 99 | set monthNames(v: Array) { 100 | AmCharts.monthNames = v; 101 | } 102 | 103 | 104 | get shortDayNames(): Array { 105 | return AmCharts.shortDayNames; 106 | } 107 | 108 | set shortDayNames(v: Array) { 109 | AmCharts.shortDayNames = v; 110 | } 111 | 112 | 113 | get shortMonthNames(): Array { 114 | return AmCharts.shortMonthNames; 115 | } 116 | 117 | set shortMonthNames(v: Array) { 118 | AmCharts.shortMonthNames = v; 119 | } 120 | 121 | 122 | // TODO better type for this 123 | get theme(): any { 124 | return AmCharts.theme; 125 | } 126 | 127 | // TODO better type for this 128 | set theme(v: any) { 129 | AmCharts.theme = v; 130 | } 131 | 132 | 133 | get processDelay(): number { 134 | return AmCharts.processDelay; 135 | } 136 | 137 | set processDelay(v: number) { 138 | AmCharts.processDelay = v; 139 | } 140 | 141 | 142 | get charts(): Array { 143 | return AmCharts.charts; 144 | } 145 | 146 | 147 | addInitHandler(handler: (chart: AmChart) => void, types?: Array): void { 148 | // TODO use this.zone.runOutsideAngular ? 149 | AmCharts.addInitHandler(handler, types); 150 | } 151 | 152 | addPrefix( 153 | value: number, 154 | prefixesBig: Array<{ number: number, prefix: string }>, 155 | prefixesSmall: Array<{ number: number, prefix: string }>, 156 | numberFormatter: Formatter 157 | ): string { 158 | // TODO use this.zone.runOutsideAngular ? 159 | return AmCharts.addPrefix(value, prefixesBig, prefixesSmall, numberFormatter); 160 | } 161 | 162 | clear(): void { 163 | // TODO use this.zone.runOutsideAngular ? 164 | AmCharts.clear(); 165 | } 166 | 167 | formatDate(date: Date, format: string): string { 168 | // TODO use this.zone.runOutsideAngular ? 169 | return AmCharts.formatDate(date, format); 170 | } 171 | 172 | formatNumber(value: number, formatter: Formatter, zeroCount: number): string { 173 | // TODO use this.zone.runOutsideAngular ? 174 | return AmCharts.formatNumber(value, formatter, zeroCount); 175 | } 176 | 177 | stringToDate(value: string, format: string): Date { 178 | // TODO use this.zone.runOutsideAngular ? 179 | return AmCharts.stringToDate(value, format); 180 | } 181 | 182 | 183 | // TODO is Node the correct type ? 184 | // TODO better type for config 185 | makeChart(id: string | Node, config: any, delay?: number): AmChart { 186 | return this.zone.runOutsideAngular(() => AmCharts.makeChart(id, config, delay)); 187 | } 188 | 189 | 190 | addListener(chart: AmChart, type: string, fn: (event: AmEvent) => void): () => void { 191 | const callback = (e: AmEvent) => { 192 | this.zone.run(() => { 193 | fn(e); 194 | }); 195 | }; 196 | 197 | this.zone.runOutsideAngular(() => { 198 | chart.addListener(type, callback); 199 | }); 200 | 201 | return () => { 202 | this.zone.runOutsideAngular(() => { 203 | chart.removeListener(chart, type, callback); 204 | }); 205 | }; 206 | } 207 | 208 | 209 | updateChart(chart: AmChart, fn: () => void): void { 210 | this.zone.runOutsideAngular(() => { 211 | fn(); 212 | chart.validateNow(true); 213 | }); 214 | } 215 | 216 | 217 | destroyChart(chart: AmChart): void { 218 | this.zone.runOutsideAngular(() => { 219 | chart.clear(); 220 | }); 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /projects/amcharts/amcharts3-angular/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of amcharts3-angular 3 | */ 4 | 5 | export * from './lib/amcharts3-angular.service'; 6 | export * from './lib/amcharts3-angular.directive'; 7 | export * from './lib/amcharts3-angular.module'; 8 | -------------------------------------------------------------------------------- /projects/amcharts/amcharts3-angular/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js'; 4 | import 'zone.js/testing'; 5 | import { getTestBed } from '@angular/core/testing'; 6 | import { 7 | BrowserDynamicTestingModule, 8 | platformBrowserDynamicTesting 9 | } from '@angular/platform-browser-dynamic/testing'; 10 | 11 | declare const require: { 12 | context(path: string, deep?: boolean, filter?: RegExp): { 13 | keys(): string[]; 14 | (id: string): T; 15 | }; 16 | }; 17 | 18 | // First, initialize the Angular testing environment. 19 | getTestBed().initTestEnvironment( 20 | BrowserDynamicTestingModule, 21 | platformBrowserDynamicTesting(), 22 | { teardown: { destroyAfterEach: true }}, 23 | ); 24 | 25 | // Then we find all the tests. 26 | const context = require.context('./', true, /\.spec\.ts$/); 27 | // And load the modules. 28 | context.keys().map(context); 29 | -------------------------------------------------------------------------------- /projects/amcharts/amcharts3-angular/tsconfig.lib.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/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "exclude": [ 17 | "src/test.ts", 18 | "**/*.spec.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /projects/amcharts/amcharts3-angular/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /projects/amcharts/amcharts3-angular/tsconfig.spec.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/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "paths": { 6 | "@amcharts/amcharts3-angular": [ 7 | "dist/amcharts/amcharts3-angular/amcharts-amcharts3-angular", 8 | "dist/amcharts/amcharts3-angular" 9 | ] 10 | }, 11 | "baseUrl": "./", 12 | "outDir": "./dist/out-tsc", 13 | "forceConsistentCasingInFileNames": true, 14 | "strict": true, 15 | "noImplicitReturns": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "sourceMap": true, 18 | "declaration": false, 19 | "downlevelIteration": true, 20 | "experimentalDecorators": true, 21 | "moduleResolution": "node", 22 | "importHelpers": true, 23 | "target": "es2017", 24 | "module": "es2020", 25 | "lib": [ 26 | "es2018", 27 | "dom" 28 | ] 29 | }, 30 | "angularCompilerOptions": { 31 | "enableI18nLegacyMessageIdFormat": false, 32 | "strictInjectionParameters": true, 33 | "strictInputAccessModifiers": true, 34 | "strictTemplates": true 35 | } 36 | } 37 | --------------------------------------------------------------------------------