react-highcharts how to call reflow? - reactjs

I use kirjs/react-highcharts plugin for react but I have no idea how to get Highchart component in order to call reflow like: $('#container1').highcharts().reflow()
From docs its tells:
For access to methods & properties from the Highcharts library you can use ReactHighcharts.Highcharts. For example, the Highcharts options are available via ReactHighcharts.Highcharts.getOptions().
but I don't see there any reflow() method.
Any ideas?
Edit
its located under ReactHighcharts.Highcharts.charts so I can call
ReactHighcharts.Highcharts.charts[0].reflow()
but it has list of all highchart instances so I have no information what index is mine

I am using highcharts-react-official and highcharts. They are available via npm . Although I am using different packages, the working principle should be the same.
The way of using reflow() function in react-highchart is also Highcharts.charts[i].reflow(). I have prepared 2 code sandboxes for the demonstration. The first code sandbox shows the way of re-flowing every chart, and the second code sandbox shows the way of re-flowing a particular chart.
The first code sandbox link is here.
There is a button on App.js to hide and show highchart divs.
The child component is React.memo (for performance optimization), therefore the hidden highchart will not be auto resized after it becomes visible.
To let every chart window resize with respect to the window size. The following code is placed in App.js. It looks for all existing charts and re-flow them:
for (var i = 0; i < Highcharts.charts.length; i++) {
if (Highcharts.charts[i] !== undefined) {
Highcharts.charts[i].reflow();
}
}
The second code sandbox link is here.
Almost the same as the first code sandbox, but there is a ref array of referencing every chart.
The chart which needs re-flowing is placed with an id in its chart option.
Iterate every chart and get the index of the chart with that id e.g. "secondChart" for this example.
for (var i = 0; i < chartRef.current.length; i++) {
if (
chartRef.current[i].chart.userOptions.id !== undefined &&
chartRef.current[i].chart.userOptions.id === "secondChart"
)
Highcharts.charts[chartRef.current[i].chart.index].reflow();
}
Re-flow that chart.

The Reflow can be set with event load in options.
Workaround: You have to set reflow() using setTimeout() this will trigger the resizing. Time is set to 0 to avoid delay.
Solution
const options = {
chart: {
type: 'column',
style: {},
events: {
load() {
setTimeout(this.reflow.bind(this), 0);
},
},
},
title: 'Column Chart',
}
Usage
<HighchartsReact highcharts={Highcharts} options={options} />

Related

React apex pie chart not showing label

I am trying to plot a series using a pie/radial chart to react. As per the documentation, I am passing the showAlways: true property that keeps showing a certain value in the middle of the chart even when the cursor is hovered or not hovered over the radial area.
But the following property does not seem to work in my case. Here is the link to the working snippet.
https://codesandbox.io/s/amazing-violet-wrp7y
I am not sure what's going wrong with the code here. Any help to resolve the same.
Your total.formatter function was not returning after calculating the total.
Here is the updated code
formatter(w) {
return w.globals.seriesTotals.reduce((a, b) => a + b, 0)
}
Updated CodeSandbox

how to set a text for a group in vis.js using groupTemplate

I have an application and using vis.js to build timeline events.
I'm using React.
I want to add an icon near each event, so I using groupTemplate and I want to render there a component with group text and icon.
in the options I add:
groupTemplate: (item, element) => {
if (!item) return;
ReactDOM.render(<TimelineGroupComp item={item}/>, element);
}
TimelineGroupComp component render function:
return (
<div className="primary-wrapper" key={this.props.item.content}>
<div style="background-image:url(../images/myIcon.svg);"/>
</div>
);
I get the correct Icon but the text is the item.id instead item.content.
I try to add a span with the correct text in the TimelineGroupComp but it renders also the item.id, not only the correct text.
Also I have another problem: when I collapse/expaned the group, I have an error in the console:
Warning: render(...): It looks like the React-rendered content of this
container was removed without using React. This is not supported and will
cause errors. Instead, call ReactDOM.unmountComponentAtNode to empty a
container.
and the group is render normal, ignored my component.
I know this post is almost a year old, but I thought I'd post the answer to this question anyways for anyone who gets the same issue in the future. I've had the same issue and this is how I fixed it.
Starting with React 16, if you want to use React templates in Vis Timeline you'll have to use React.createPortal in the groupTemplate option, see https://jsfiddle.net/api/post/library/pure/.
For the code above, the correct groupTemplate would be:
groupTemplate: (item, element) => {
if (!item) return;
ReactDOM.createPortal(
ReactDOM.render(<TimelineGroupComp item={item}/>, element),
element
)
}

Ant design bar chart hide label

I use ant design bar chart in my react project.
https://codesandbox.io/s/9qmjm0k7yw
Doc: https://pro.ant.design/components/Charts
I want to show the data with x-axis as date format (29/09/2018 for example). If I show like 30 days, it would not have enough space for all the label so it looks weird.
I want to hide the label of bar chart. Like this
if (more than 15 days) chart shows label
else hide label
Or is there any way that I show the chart for 30 days but only show the label for let's say 10 days?
How can I hide the label?
Unfortunately what you want to do is not supported by Antd-Pro Charts. It is stated in the docs that they designed the charts components with focus on ease-of-use over customization.
However Antd-Pro Charts are just a simplified subset of BizCharts (which itself is a port of G2) with reduced api options. If you need complicated chart options consider using the parent BizCharts library instead. You can do what you want by adjusting the < Axis > object in BizCharts.
In my example below, I have used a Column chart with x field of "week" and y field of "views". I did not want to display the label on the x field.
render() {
// console.log(this.state.data)
const config = {
data: this.state.data,
title: {
visible: true,
text: 'Your Stats',
},
xField: 'week',
yField: 'views',
meta: {
week: {
alias: " "
}
}
};
return (
<React.Fragment>
<Column {...config} />
</React.Fragment>
);
}
The data used is as follows:
Which yielded this outcome:
In order to develop your own project, I strongly recommend that you keep all of your software business in your own project, and use third party libraries just for their own business, rather than manipulating your software business because they simply change these libraries and To apply these changes, you may need to do a lot of work.
it does not only give you more performance but also increases your ability to develop.
for your topic, you can simply get an array and handle whatever you want and pass your processed array to component

React-slick Slider stays on same page if slides items are changed

I am stuck with an issue with react-slick. The subject line may not make sense, but I will try to explain the scenario in detail. See this example fiddle to see the issue in action.
var DemoSlider = React.createClass({
getSlides(count) {
var slides = [];
for(var i = 0; i < count; i++) {
slides.push((<img key={i} src='http://placekitten.com/g/400/200' />));
}
return slides;
},
render: function() {
var settings = {
dots: false,
infinite: false,
slidesToShow: 3,
slidesToScroll: 3
}
var slides = this.getSlides(this.props.count);
return (
<div className='container'>
<Slider {...settings}>
{ slides }
</Slider>
</div>
);
}
});
In this demo, initially the slider shows 20 slides (3 per page). The idea is that if you click the button, it will generate a random number, which would be the new number of slides. The code is fairly simple and self-explanatory.
To reproduce the problem,
1. keep on clicking Next arrow until you reach the last slide.
2. click on the button that says 'Click' to generate a new random number of slides.
My expectation was that the slide will go back to the first slide but not to stay on the page where it previously was. Even worse, if the new number of slides is lower than the previous number, the user will see a blank page with no slides. On clicking Previous error, he/she can go to the previous slides, and everything works normally but the initial display ruins the user experience.
Is there something I am missing to add in the code, or is this a bug?
Thanks,
Abhi.
I would say it is rather a buggy behavior, but still you can achieve what you want by forcing a redraw after new collection has been passed as props, by resetting react's key:
<DemoSlider key={Date.now()} count={this.state.count}/>
UPDATED FIDDLE
Quick workaround: When you change to a new set of slides, remove the component, and reconstruct it again. It would then start with the first slide. You can do this by incrementing the key attribute of DemoSlider.
For a proper fix, you'd need to tell the component to change the 'current slide', so that it's not looking at a slide index beyond the end, but a casual look at the source at https://cdnjs.cloudflare.com/ajax/libs/react-slick/0.11.0/react-slick.js suggests it currently does not allow this. A change would need to be made to InnerSlider.componentWillReceiveProps() to check state.currentSlide against props.slidesToShow and state.slideCount.
It would also benefit from allowing currentSlide to be passed as props.

Bootstrap dropdown in column header

I've been trying to use the ng-grid 3.0 (ui-grid). I have managed to populate my grid and it's been very responsive and it's features are really amazing. But I'm trying to customize my column headers, as I need more info there.
I can create a custom header cell template, as indicated in the docs, but I don't seem able to use a Bootstrap Dropdown there, it gets cropped and I can't use it at all. Some googling got me thinking it is probably some issue with the overflow attributes, but still I can't solve it. My grid options is as follows:
$scope.columnDefs = [
{ name:'name', displayName: 'Vdd', headerCellTemplate: 'headerTemplate.html' },
{ name:'gender', headerCellTemplate: 'headerTemplate.html' },
{ name:'company' }
]
$scope.gridOptions = {
columnDefs: $scope.columnDefs,
rowTemplate: 'rowTemplate.html',
data: 'data'
};
I have forked an example in plunkr and managed to reproduce my issue:
http://plnkr.co/edit/qdrFiifiz18fxB8w6Aja?p=preview
I want to replace the built-in dropdown menu (since it doesn't seem to allow nesting and sub-menus) and add another one (so in the end, I'd have two dropdown menus in each header cell)
Any help is appreciated =)
I am proud to say I think I've figured it out. I've been digging through ui-grid's source code and narrowed it down to this block (lines: 2847 - 2852).
function syncHorizontalHeader(scrollEvent){
var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
if (containerCtrl.headerViewport) {
containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
}
}
I noticed that containerCtrl.headerViewport.scrollLeft was never getting set to newScrollLeft. A quick google search led me to this StackOverflow thread which says that you can't set the scrollLeft property of an element if it's overflow is set to visible.
My solution was to replace containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid); with containerCtrl.headerViewport.style.marginLeft = -gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid) + 'px'; which just sets a negative margin on the header. Then add an overflow:hidden; style to .ui-grid-render-container-body to hide headers that extend beyond the main grid viewport.
Doing this messed up the placement of column menus, but there is an easy fix. On line 514 replace var containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].scrollLeft; with var containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].style.marginLeft; to use the margin instead of the scroll value in the menu placement calculation.

Resources