The documentation and type correctness of dataElementType
- Dominant language
- JavaScript
- Stars
- 67.7k
- Forks
- 11.9k
- Avg merge
- 7h 39m
- Merged PRs (30d)
- 5
Description
### Expected behavior
## Described behavior
According to the documentation [`docs/developers/charts.md`](https://github.com/chartjs/Chart.js/blob/master/docs/developers/charts.md?plain=1#L37) the chart `static defaults = { ... }` allow `dataElementType` to be `null` or `false` with the following comment:
> ```js
> defaults: {
> // If set to `false` or `null`, no dataset level element is created.
> // If set to a string, this is the type of element to create for the dataset.
> // For example, a line create needs to create a line element so this is the string 'line'
> datasetElementType: string | null | false,
>
> // If set to `false` or `null`, no elements are created for each data value.
> // If set to a string, this is the type of element to create for each data value.
> // For example, a line create needs to create a point element so this is the string 'point'
> dataElementType: string | null | false,
> }
> ```
and the type hints in [`src/types/index.d.ts`](https://github.com/chartjs/Chart.js/blob/master/src/types/index.d.ts#L672) allow the `dataElementType` to be even ~~undefined~~ unspecified:
> ```ts
>export interface DatasetControllerChartComponent extends ChartComponent {
> defaults: {
> datasetElementType?: string | null | false;
> dataElementType?: string | null | false;
> };
> }
> ```
although this might be wrong since `DatasetControllerChartComponent` is never used again in the whole codebase and just stays as an exported type.
If I do not specify `dataElementType` or set it to `null | false | undefined` the code should not crash unexpectedly (and should not allocate any arrays, create new objects, ... - unless parsing I guess?).
### Current behavior
```ts
class MyController extends DatasetController {
static id = 'my';
static defaults = {
dataElementType: null,
}
parse() { }
draw() { }
}
```
results in
```
core.registry.js:178 Uncaught Error: "null" is not a registered element.
at Registry._get (core.registry.js:178:13)
at Registry.getElement (core.registry.js:74:17)
at Chart.buildOrUpdateControllers (core.controller.js:445:37)
at Chart.update (core.controller.js:495:33)
at new Chart (core.controller.js:193:12)
at (index):31:1
```
The same behavior as with `null` can be observed with `dataElementType` set to `false` (allowed by docs) and eve with `dataElementType` not being defined at all (kinda allowed by the unused type, disallowed by docs).
This happens in
[`src/core/core.datasetController.js::DatasetController::_insertElements`](https://github.com/chartjs/Chart.js/blob/master/src/core/core.datasetController.js#L1009) which does not check the value of `dataElementType` in any way. This function also allocates the `meta.data` array even though it should not be needed in this case (especially when parsing disabled - probably?).
I found also something similar in
[`src/core/core.datasetController.js::DatasetController::constructor`](https://github.com/chartjs/Chart.js/blob/master/src/core/core.datasetController.js#L275) but this somehow never gets called, at least in my experiments.
### Reproducible sample
https://jsfiddle.net/cb37sr54/2/
### Optional extra steps/info to reproduce
Gist GitHub: https://gist.github.com/antoninkriz/2ced01a7e90db8ac2dd417064e6a08a7
JSFiddle: https://jsfiddle.net/cb37sr54/2/
This code will raise the described error.
```html
{
"imports": {
"@kurkle/color": "https://cdn.jsdelivr.net/npm/@kurkle/color@0.4.0/+esm",
"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.0/chunks/helpers.dataset.js": "https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chunks/helpers.dataset.js"
}
}
import { Chart } from 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.0/chart.js'
import { DatasetController } from 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.0/chart.js'
import { BarController, BarElement, CategoryScale, LinearScale } from 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.0/chart.js'
class MyController extends DatasetController {
static id = 'my';
static defaults = {
dataElementType: false,
}
parse() { }
draw() { }
}
Chart.register(MyController)
Chart.register(BarController, BarElement, CategoryScale, LinearScale);
new Chart(document.getElementById('myChart'), {
data: {
labels: ['a', 'b', 'c', 'd'],
datasets: [{
type: 'my',
data: [1, 2, 3, 4],
}],
},
});
```
### Possible solution
Here I define an element to keep the code from crying and successfully render a completely empty chart.
Anyway since I do not define `inRange` and `events: []` is not set in the config I get error on mouse moves over the chart.
```
core.interaction.js:174 Uncaught TypeError: element.inRange is not a function
at evaluationFunc (core.interaction.js:174:29)
at evaluateInteractionItems (core.interaction.js:83:9)
at getNearestCartesianItems (core.interaction.js:195:3)
at getNearestItems (core.interaction.js:216:7)
at nearest (core.interaction.js:356:14)
at Chart.getElementsAtEventForMode (core.controller.js:823:14)
at Chart._getActiveElements (core.controller.js:1260:17)
at Chart._handleEvent (core.controller.js:1213:25)
at Chart._eventHandler (core.controller.js:1176:26)
at listener (core.controller.js:988:12)
```
```html
{
"imports": {
"@kurkle/color": "https://cdn.jsdelivr.net/npm/@kurkle/color@0.4.0/+esm",
"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.0/chunks/helpers.dataset.js": "https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chunks/helpers.dataset.js"
}
}
import { Chart } from 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.0/chart.js'
import { DatasetController, Element } from 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.0/chart.js'
import { BarController, BarElement, CategoryScale, LinearScale } from 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.0/chart.js'
class NoopElement extends Element {
static id = 'noop'
}
class MyController extends DatasetController {
static id = 'my';
static defaults = {
dataElementType: 'noop',
}
parse() { }
draw() { }
}
Chart.register(NoopElement, MyController)
Chart.register(BarController, BarElement, CategoryScale, LinearScale);
new Chart(document.getElementById('myChart'), {
data: {
labels: ['a', 'b', 'c', 'd'],
datasets: [{
type: 'my',
data: [1, 2, 3, 4],
}],
},
});
```
### Context
_No response_
### chart.js version
4.5.0
### Browser name and version
Chrome 143, macOS 26, Apple ARM
### Link to your project
_No response_
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.