I have implemented a bar chart with rangeslider using react-plotly.js. I set initial range of the slider based on the input given in a date format. I have also implemented onClick event on barchart which would select a particular bar and change the color when I click on it.
In addition to that, I would also like to set the rangeslider to select the area where I have clicked the bar.
Currently, as you can see in the image above, the rangeslider sets itself back to the initial range value everytime the onClick event is performed. So in order to see the bar that was clicked, I have to manually move the slider to that area.
xaxis: {
type: 'date',
autorange: false,
fixedrange: true,
showgrid: false,
range: [moment.unix(this.state.startTime).format('YYYY-MM-DD'), moment.unix(this.state.endTime).format('YYYY-MM-DD')],
rangeslider: {
visible: true
}
}
<Plot
data={this.prepData(this.state.chartData)}
onClick={(data) => {
var colors = [];
var clickedPoint = data.points[0].pointNumber;
for (var i = 0; i < data.points[0].data.y.length; i++) {
if (i === clickedPoint) {
colors[i] = '#9b1e83';
} else {
colors[i] = this.state.defaultColor[i];
}
}
this.setState({
currentColorsArray: colors,
barClicked: data.points[0].pointNumber,
showSummaryPanel: true
})
}}
onHover={(hover) => this.getHoverInfo(hover)}
type={'bar'}
/>
How should I pass values to onRelayout such that it sets the rangeslider to the area where the onClick event was performed ?
Related
I am trying to remove empty spaces between bars when the value of bar is 0. To do so I am trying to use plugin in beforeDraw. The thing is that when I am trying to implement it I am getting error "Canvas is already in use. Chart with ID '1' must be destroyed before the canvas with ID '' can be reused." What may be a problem here?
<Bar
options={barOptions}
data={barData}
plugins={[
{
id: "remover",
beforeDraw: function ({ chart }: any) {
chart.data.datasets.forEach(function ({
dataset,
datasetIndex,
}: any) {
console.log(dataset);
dataset.data.forEach(function ({ value, index }: any) {
if (value === 0) {
chart.getDatasetMeta(datasetIndex).data[
index
].hidden = true;
}
});
});
},
},
]}
/>
I have already try putting this plugin in options but it didn't work at all. There is bar between black and blue bar but since its value is 0 its not visible. I want to remove this space so bars will be next to each other. (same with space between blue and green)
current chart
How to change the chart title dynamically on hover in Highcharts
JSfiddle
http://jsfiddle.net/q4b7dvmx/1/
tried with setState but its not working perfectly
tooltip:{
enabled: true,
borderRadius: 0,
borderWidth: 0,
shadow: false,
shared: true,
useHTML: true,
zIndex: 99999,
formatter() {
// ToolTip Built Here
const { x , y } = this;
let tooltipString = `<div > ${y}
</div>`;
// that.props.updateDates( this.points[0].series.userOptions.dates[this.points[0].key] );
return tooltipString;
}
}
The easiest way is to change a title text attribute in tooltip formatter function.
tooltip: {
...,
formatter(e) {
const {
x,
y
} = this;
e.chart.title.attr({
text: 'ftest' + ' x value: ' + x
});
}
}
Live demo: http://jsfiddle.net/BlackLabel/tk1avpze/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGElement#attr
Do you mean on hover of a data-point? in that case, your demo does nothing to the chart title.
Either way, you should check this post;
How can I access a hover state in reactjs?
EDIT;
Did you see https://api.highcharts.com/highcharts/tooltip.formatter - it adresses the formatter. It seems to be the answer, from the looks of a similar question;
Highcharts.js : get specific value from data to tooltip
I am using Fluent UI DetailsList. My table looks like below:
I need filters below every column (text or drop-down) as shown below:
Please let me know if this is possible? Or maybe a way to display custom header (using html) ?
This actually turned out to be easier than I thought it'd be...
If you're ok with clicking the column header to reveal the choices (vs having the dropdown directly under the title) then this can be achieved using the ContextualMenu component in conjunction with DetailsList. I got it working by tweaking from the variable row height example in the official docs: https://developer.microsoft.com/en-us/fluentui#/controls/web/detailslist/variablerowheights.
Add a ContextualMenu underneath your DetailsList:
<DetailsList
items={items}
columns={columns}
/>
{this.state.contextualMenuProps && <ContextualMenu {...this.state.contextualMenuProps} />}
Inside your column definition, set the hasDropdown action so the user gets a UI indicator that they can/should click the header, and call a contextMenu method (note I'm using onColumnContextMenu as well as onColumnClick so it doesn't matter if they left or right click the header:
{
key: 'dept',
name: 'Department',
fieldName: 'dept',
minWidth: 125,
maxWidth: 200,
onColumnContextMenu: (column, ev) => {
this.onColumnContextMenu(column, ev);
},
onColumnClick: (ev, column) => {
this.onColumnContextMenu(column, ev);
},
columnActionsMode: ColumnActionsMode.hasDropdown,
}
When the onColumnContextMenu method gets invoked, we need to build the context menu properties that will get consumed by the ContextualMenu component. Note the dismissal method as well, which clears out the state so the menu is hidden.
private onContextualMenuDismissed = (): void => {
this.setState({
contextualMenuProps: undefined,
});
}
private onColumnContextMenu = (column: IColumn, ev: React.MouseEvent<HTMLElement>): void => {
if (column.columnActionsMode !== ColumnActionsMode.disabled) {
this.setState({
contextualMenuProps: this.getContextualMenuProps(ev, column),
});
}
};
Finally, inside of getContextualMenuProps you need to determine what the options should be for the user to click. In this example, I'm simply giving sort options (you'll need to add an onClick handler to actually do something when the user clicks the item), but I'll use the column to determine what those items should actually be and paint the filters into the items collection so the user can select one to filter.
private getContextualMenuProps = (ev: React.MouseEvent<HTMLElement>, column: IColumn): IContextualMenuProps => {
const items: IContextualMenuItem[] = [
{
key: 'aToZ',
name: 'A to Z',
iconProps: { iconName: 'SortUp' },
canCheck: true,
checked: column.isSorted && !column.isSortedDescending,
},
{
key: 'zToA',
name: 'Z to A',
iconProps: { iconName: 'SortDown' },
canCheck: true,
checked: column.isSorted && column.isSortedDescending,
}
];
return {
items: items,
target: ev.currentTarget as HTMLElement,
directionalHint: DirectionalHint.bottomLeftEdge,
gapSpace: 10,
isBeakVisible: true,
onDismiss: this.onContextualMenuDismissed,
}
}
Note the target on the ContextualMenuProps object, which is what tells the ContextualMenu where to lock itself onto (in this case, the column header that you clicked to instantiate the menu.
Detail list filter for each column without context menu -
https://codesandbox.io/s/rajesh-patil74-jzuiy?file=/src/DetailsList.CustomColumns.Example.tsx
For instance - Providing filter in text field associated with each column will apply filter on color column.
I have a custom tooltip in react-chartjs-2;
I found a solution of making custom tooltip, but my tooltip is always visible, in that solution tooltip hides when tooltip.opacity is 0, but in my case tooltip opacity is always 1, can smbd help me pls?
tooltips: {
enabled: false,
mode: 'x',
intersect: false,
custom: (tooltipModel) => {
if (tooltipModel.opacity === 0) {
// never called because opacity is always 1
this.hide();
return;
}
// const position = this.chartRef.current.chartInstance.canvas.getBoundingClientRect();
// set position of tooltip
// const left = position.left + tooltipModel.caretX;
// const top = position.top + tooltipModel.caretY;
// set values for display of data in the tooltip
const date = tooltipModel.dataPoints[0].xLabel;
const value = tooltipModel.dataPoints[0].yLabel;
// this.setPositionAndData(top, left, date, value);
},
Just to clarify for any other person who needs help on this.
When you create your handle for a custom toolbar, you need to pay attention to not overwrite the this(scope) object. Try with arrow function and remove the bind, the fn will get automatically the new scope and the opacity will be update when you move out from a chart bar/line etc.
The same issue will happen with the legend if you try to overwrite the onClick function using inline arrow function or functions. Some examples bellow.
_tooltip = (tooltipModel) => {
...
}
_legendOnClick = (ev) => {
ev.preventDefault()
}
render() {
const defaultOpt = {
legend: {
onClick: this._legendOnClick
},
tooltips: {
enabled: false,
custom: this._tooltip,
mode: 'index'
}
}
}
If you want to improve perfomance, you should remove the defaultOpt from the render method.
That's
Instead of this:
intersect: false,
custom: (tooltipModel) => {
if (tooltipModel.opacity === 0) {
use this workaround:
intersect: false,
custom: function(tooltipModel){
let hit=this._active[0].inRange(this._eventPosition.x, this._eventPosition.y);
if (tooltipModel.opacity === 0 || !hit) {
make sure not to use arrow function to keep 'this'.
In my case the root of the problem was that I defined the 'options' object in the render function of my component along with the 'custom' tooltip handler and called a setState from the inside of it - which caused an other render call immediately. This broke down the tooltip handling of chart.js. Moving the handler outside of the render function solved it without needing the above workaround.
I want to create a toggle button thats add/remove groupable option in my KENDO grid. In initialize i have not property 'groupable'.
{
type: "button",
togglable: true,
id: "groupableToggle",
toggle: function (e) {
var grid = $("#grid" + config.id).data("kendoGrid");
if (e.checked) {
grid.options.groupable = {
messages: {
empty: "drag a column header and drop it here to group by that column"
}
};
}
else
grid.options.groupable = false
grid._thead();
grid.refresh();
}
}
but this is not work!
OK!! I FOUND IT!
if (e.checked) {
grid.setOptions({
groupable: true,
messages: {
empty: "drag a column header and drop it here to group by that column"
}
});
}
else {
grid.setOptions({
groupable: false
});
}
grid._thead();
grid.refresh();
and now plays
The groupable setting cannot be changed on the fly without recreating the Grid. Use the setOptions method of the Grid, or k-rebind to achieve that.
http://docs.telerik.com/kendo-ui/api/javascript/ui/widget#methods-setOptions
http://docs.telerik.com/kendo-ui/AngularJS/introduction#widget-update-upon-option-changes