WEBAPP: P8PChart - обновление onClick-функции, значения по умолчанию для options, labels, datasets, необязательность labels

This commit is contained in:
Mikhail Chechnev 2025-02-14 13:48:36 +03:00
parent 27bd43afb5
commit 852abd5482
3 changed files with 22 additions and 18 deletions

View File

@ -1767,7 +1767,7 @@ const MyPanel = () => {
`title` - необязательный, строка, заголовок графика, если не указано - заголовок не отображается\ `title` - необязательный, строка, заголовок графика, если не указано - заголовок не отображается\
`legendPosition` - необязательный, строка, расположение легенды, может принимать значения `left|right|top|bottom`, если не указано - легенда не отображается\ `legendPosition` - необязательный, строка, расположение легенды, может принимать значения `left|right|top|bottom`, если не указано - легенда не отображается\
`options` - необязательный, объект, дополнительные параметры графика, формат и допустимый состав атрибутов определены в документации к библиотеке [ChartJS](https://www.chartjs.org/docs/latest/), будет объединён с параметрами графика уже зафиксированными в компоненте `P8PChart` (см. `useEffect` при подключении компонента к старице в его исходном коде, параметры графика, зафиксированные в компоненте, имеют более высокий приоритет по сравнению с данным свойством) `options` - необязательный, объект, дополнительные параметры графика, формат и допустимый состав атрибутов определены в документации к библиотеке [ChartJS](https://www.chartjs.org/docs/latest/), будет объединён с параметрами графика уже зафиксированными в компоненте `P8PChart` (см. `useEffect` при подключении компонента к старице в его исходном коде, параметры графика, зафиксированные в компоненте, имеют более высокий приоритет по сравнению с данным свойством)
`labels` - обязательный, массив строк, список меток для значений графика\ `labels` - необязательный, массив строк, список меток для значений графика\
`datasets` - необязательный, массив объектов, данные для отображения на диаграмме, каждый элемент массива - серия данных для отображения, содержит объекты вида `{label: <ЗАГОЛОВОК_СЕРИИ>, borderColor: <ЦВЕТРАНИЦЫ_СЕРИИ_НАРАФИКЕ>, backgroundColor: <ЦВЕТ_ЗАЛИВКИ_СЕРИИ_НАРАФИКЕ>, data: <МАССИВ_ЗНАЧЕНИЙ_СЕРИИ_ДАННЫХ>, items: <МАССИВ_ОБЪЕКТОВРОИЗВОЛЬНОЙ_СТРУКТУРЫ_ДЛЯ_ОПИСАНИЯ_СЕРИИ_ДАННЫХ>}`\ `datasets` - необязательный, массив объектов, данные для отображения на диаграмме, каждый элемент массива - серия данных для отображения, содержит объекты вида `{label: <ЗАГОЛОВОК_СЕРИИ>, borderColor: <ЦВЕТРАНИЦЫ_СЕРИИ_НАРАФИКЕ>, backgroundColor: <ЦВЕТ_ЗАЛИВКИ_СЕРИИ_НАРАФИКЕ>, data: <МАССИВ_ЗНАЧЕНИЙ_СЕРИИ_ДАННЫХ>, items: <МАССИВ_ОБЪЕКТОВРОИЗВОЛЬНОЙ_СТРУКТУРЫ_ДЛЯ_ОПИСАНИЯ_СЕРИИ_ДАННЫХ>}`\
`onClick` - необязательный, функция, будет вызвана при нажатии на элемент графика, сигнатура функции `f({datasetIndex, itemIndex, item})`, результат функции не интерпретируется. Функции будет передан объект, поле `datasetIndex` которого, будет содержать индекс серии данных, `itemIndex` - индекс элемента серии данных, а `item` - описание элмента данных серии, на котором было зафиксировано нажатие.\ `onClick` - необязательный, функция, будет вызвана при нажатии на элемент графика, сигнатура функции `f({datasetIndex, itemIndex, item})`, результат функции не интерпретируется. Функции будет передан объект, поле `datasetIndex` которого, будет содержать индекс серии данных, `itemIndex` - индекс элемента серии данных, а `item` - описание элмента данных серии, на котором было зафиксировано нажатие.\
`style` - необязательный, объект, стили, которые будут применены к контейнеру `div` графика `style` - необязательный, объект, стили, которые будут применены к контейнеру `div` графика
@ -1859,7 +1859,7 @@ const STYLES = {
//Пример: Графики "P8PChart" //Пример: Графики "P8PChart"
const Chart = ({ title }) => { const Chart = ({ title }) => {
//Собственное состояние - график //Собственное состояние - график
const [chart, setChart] = useState({ loaded: false, labels: [], datasets: [] }); const [chart, setChart] = useState({ loaded: false });
//Подключение к контексту взаимодействия с сервером //Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx); const { executeStored } = useContext(BackEndСtx);

View File

@ -7,7 +7,7 @@
//Подключение библиотек //Подключение библиотек
//--------------------- //---------------------
import React, { useEffect, useRef } from "react"; //Классы React import React, { useCallback, useEffect, useRef } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента import PropTypes from "prop-types"; //Контроль свойств компонента
import Chart from "chart.js/auto"; //Диаграммы и графики import Chart from "chart.js/auto"; //Диаграммы и графики
@ -37,23 +37,26 @@ const P8P_CHART_DATASET_SHAPE = PropTypes.shape({
//----------- //-----------
//График //График
const P8PChart = ({ type, title, legendPosition, options, labels, datasets, onClick, style }) => { const P8PChart = ({ type, title, legendPosition, options = {}, labels = [], datasets = [], onClick, style }) => {
//Ссылки на DOM //Ссылки на DOM
const chartCanvasRef = useRef(null); const chartCanvasRef = useRef(null);
const chartRef = useRef(null); const chartRef = useRef(null);
//Обработка нажатия на элемент графика //Обработка нажатия на элемент графика
const handleClick = e => { const handleClick = useCallback(
const bar = chartRef.current.getElementsAtEventForMode(e, "nearest", { intersect: true }, true)[0]; e => {
if (onClick && bar) const bar = chartRef.current.getElementsAtEventForMode(e, "nearest", { intersect: true }, true)[0];
onClick({ if (onClick && bar)
datasetIndex: bar.datasetIndex, onClick({
itemIndex: bar.index, datasetIndex: bar.datasetIndex,
item: chartRef.current.data.datasets[bar.datasetIndex].items itemIndex: bar.index,
? chartRef.current.data.datasets[bar.datasetIndex].items[bar.index] item: chartRef.current.data.datasets[bar.datasetIndex].items
: null ? chartRef.current.data.datasets[bar.datasetIndex].items[bar.index]
}); : null
}; });
},
[onClick]
);
//При подключении к старнице //При подключении к старнице
useEffect(() => { useEffect(() => {
@ -89,9 +92,10 @@ const P8PChart = ({ type, title, legendPosition, options, labels, datasets, onCl
if (chartRef.current) { if (chartRef.current) {
chartRef.current.data.labels = [...labels]; chartRef.current.data.labels = [...labels];
chartRef.current.data.datasets = [...datasets]; chartRef.current.data.datasets = [...datasets];
chartRef.current.options.onClick = handleClick;
chartRef.current.update(); chartRef.current.update();
} }
}, [datasets, labels]); }, [datasets, labels, handleClick]);
//Генерация содержимого //Генерация содержимого
return ( return (
@ -107,7 +111,7 @@ P8PChart.propTypes = {
title: PropTypes.string, title: PropTypes.string,
legendPosition: PropTypes.string, legendPosition: PropTypes.string,
options: PropTypes.object, options: PropTypes.object,
labels: PropTypes.arrayOf(PropTypes.string).isRequired, labels: PropTypes.arrayOf(PropTypes.string),
datasets: PropTypes.arrayOf(P8P_CHART_DATASET_SHAPE), datasets: PropTypes.arrayOf(P8P_CHART_DATASET_SHAPE),
onClick: PropTypes.func, onClick: PropTypes.func,
style: PropTypes.object style: PropTypes.object

View File

@ -33,7 +33,7 @@ const STYLES = {
//Пример: Графики "P8PChart" //Пример: Графики "P8PChart"
const Chart = ({ title }) => { const Chart = ({ title }) => {
//Собственное состояние - график //Собственное состояние - график
const [chart, setChart] = useState({ loaded: false, labels: [], datasets: [] }); const [chart, setChart] = useState({ loaded: false });
//Подключение к контексту взаимодействия с сервером //Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx); const { executeStored } = useContext(BackEndСtx);