Here, I am trying to implement pie chart (donut series) in angular. These are my html, css and ts files. I am following this resource. https://apexcharts.com/angular-chart-demos/pie-charts/simple-donut/
Link to CodeSandBox - https://codesandbox.io/s/apx-donut-simple-8fnji?from-embed
import { Component, OnInit, ViewChild } from '@angular/core';
import { ChartComponent } from "ng-apexcharts";
import {
ApexNonAxisChartSeries,
ApexResponsive,
ApexChart
} from "ng-apexcharts";
export type ChartOptions = {
series: ApexNonAxisChartSeries;
chart: ApexChart;
responsive: ApexResponsive[];
labels: any;
};
@Component({
selector: 'app-second-page',
templateUrl: './second-page.component.html',
styleUrls: ['./second-page.component.css']
})
export class SecondPageComponent implements OnInit {
@ViewChild("chart") chart: ChartComponent;
public chartOptions: Partial<ChartOptions>;
constructor() {
this.chartOptions = {
series: [44, 55, 13, 43, 22],
chart: {
type: "donut"
},
labels: ["Team A", "Team B", "Team C", "Team D", "Team E"],
responsive: [
{
breakpoint: 480,
options: {
chart: {
width: 200
},
legend: {
position: "bottom"
}
}
}
]
};
}
ngOnInit(): void {
}
}
#chart {
max-width: 380px;
margin: 35px auto;
padding: 0;
}
<div id="chart">
<apx-chart
[series]="chartOptions.series"
[chart]="chartOptions.chart"
[labels]="chartOptions.labels"
[responsive]="chartOptions.responsive"
></apx-chart>
</div>
I am facing the undefined issue, but its working for them in the tutorial. Somebody please help me on this.
Error: src/app/second-page/second-page.component.html:32:8 - error TS2322: Type 'ApexNonAxisChartSeries | undefined' is not assignable to type 'ApexAxisChartSeries | ApexNonAxisChartSeries'.
Type 'undefined' is not assignable to type 'ApexAxisChartSeries | ApexNonAxisChartSeries'.
32 [series]="chartOptions.series"
~~~~~~
src/app/second-page/second-page.component.ts:19:16
19 templateUrl: './second-page.component.html',
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component SecondPageComponent.
Error: src/app/second-page/second-page.component.html:33:8 - error TS2322: Type 'ApexChart | undefined' is not assignable to type 'ApexChart'.
Type 'undefined' is not assignable to type 'ApexChart'.
33 [chart]="chartOptions.chart"
~~~~~
src/app/second-page/second-page.component.ts:19:16
19 templateUrl: './second-page.component.html',
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component SecondPageComponent.
Error: src/app/second-page/second-page.component.html:35:8 - error TS2322: Type 'ApexResponsive[] | undefined' is not assignable to type 'ApexResponsive[]'.
Type 'undefined' is not assignable to type 'ApexResponsive[]'.
35 [responsive]="chartOptions.responsive"
~~~~~~~~~~
src/app/second-page/second-page.component.ts:19:16
19 templateUrl: './second-page.component.html',
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component SecondPageComponent.
Error: src/app/second-page/second-page.component.ts:23:23 - error TS2564: Property 'chart' has no initializer and is not definitely assigned in the constructor.
23 @ViewChild("chart") chart: ChartComponent;
~~~~~
✖ Failed to compile.
CodePudding user response:
I'm not entirely sure about the specifics of the library, but I can explain what the compiler is complaining about.
Whenever you use Partial
in TypeScript, this can be seen as making all keys in the subject interface optional, for example
interface SomeInterface {
key1: string;
key2: number;
}
type PartialSomeInterface = Partial<SomeInterface>
// which is equivalent to
interface PartialSomeInterface {
key1?: string;
key2?: number;
}
// which is equivalent to
interface PartialSomeInterface {
key1: string | undefined;
key2: number | undefined;
}
Effectively, by declaring chartOptions
as Partial<ChartOptions>
you are saying that the object being stored may have as little as 0 keys, i.e. all of them may be missing or undefined
, and that is an acceptable value for chartOptions
.
When a property on this chartOptions
is then passed to the <apx-chart>
component, the chart component needs to have | undefined
in the type definition for the property being passed in. For example, looking at the series
input:
// Component definition needed
@Input() series?: ApexAxisChartSeries | ApexNonAxisChartSeries
or
@Input() series: ApexAxisChartSeries | ApexNonAxisChartSeries | undefined
The compiler is complaining that this is not the case, and a value of undefined
is not acceptable. Which most likely means that the component definition is in fact:
@Input() series: ApexAxisChartSeries | ApexNonAxisChartSeries
In short Partial<ChartOptions>
does not appear to be an acceptable type for chartOptions
based on the demands of the child component <apx-chart>
.
This is confusing, as you have quite rightly followed the documentation/example provided.
Couple of things to try/investigate:
- As you are fortunate enough to have defined all of the properties of the
ChartOptions
interface in yourchartOptions
variable initial values, simply remove thePartial
. This will tell the underlying component that every property inchartOptions
is expected to be defined, and therefore all 4 keys can be passed into the component as you have done - If you still need to use
Partial
, i.e. you intend to not define all starting properties ofchartOptions
, is there a chance that the version ofapx-chart
you are using is outdated/does not match the version used in the demos?
CodePudding user response:
See the last error, it shows you the problem:
error TS2564: Property 'chart' has no initializer and is not definitely assigned in the constructor.
It's related to the typescript flag --strictPropertyInitialization
introduced in version 2.7.
If --strictPropertyInitialization
is enabled, the compiler checks if all properties of the component are initialized. info
There are several ways to fix that. For example, disable --strictPropertyInitialization
flag in typescript compiler options in tsconfig.json
file.
"compilerOptions": {
...
"strictPropertyInitialization":false
...
}