Pass document while rendering a React component in outer window - reactjs

I am trying to handle React components in popup outer windows, I am using FlexLayout, ag-Grid React and SyncFusion React and I managed to handle the outer window with FlexLayout by using const currentDocument = this.selfRef.current.ownerDocument; -check Floating Tabs (Popouts) in FlexLayout- and pass this currentDocument to getDocument() callback in ag-Grid and now I wanted to do the same with SyncFusion, but I found no method/property in SyncFusion to pass the currentDocument to it.
So, is there anyway to pass the outer window document to the SyncFusion component which will be re-rendered after going in outer window and leave the origin document?
Attached a screenshot for the issue when not passing the currentDocument (new outer window) to SyncFusion components I have pressed the Date Picker button in the outer window (on the right), but the DatePicker component rendered in the original window (on the left)!
SyncFusion DatePicker Issue Screenshot

You can align the popup position relate to input element by setting X and Y position in the open event of DateTimePicker popup as mentioned in the below code example.
this.onOpen = (args) => {
args.popup.position = { X: "left", Y: "bottom" };
};
The possible values for popup position are left, right, top and bottom. Try specifying the all possible combination of values to align the popup based on your viewport.
Also, you can set the offsetX and offsetY value in number (Provide the x and y value by imaging x and y axis) to align the DateTimePicker popup relate to the input element. Here, we have provided the offsetX and offsetY value based on the desktop mode. You can customize it based on the view port.
this.onOpen = (args) => {
args.popup.offsetX= 1000;
args.popup.offsetY= 1000;
};
Sample Link: https://stackblitz.com/edit/react-yhgq4y-w2avy2?file=index.js
Provide more details about your query, if the solution suggested above does not help you.

You can customize the DatePicker popup’s in the desired position using the appendTo method in the open event argument. Kindly refer the below code,
render() {
return (
<div className="control-pane">
<div className="control-section">
<div className="datepicker-control-section">
<DatePickerComponent open={this.onOpen.bind(this)} />
</div>
</div>
<div id="target" />
</div>
);
}
onOpen(args) {
args.appendTo = document.body.querySelector("#target");
}
Please find the sample below,
Sample link: https://stackblitz.com/edit/react-eekdsn?file=index.js

Related

Highcharts automatic resize using drag/resize react-rnd library

I want to create a component where the size of the chart automatically adjusts with resize events of the container holding the graph. It would be great if someone can help me with an example. Here si the link to the library. react-rnd library
E.x somehting like this but using highcharts codebox react-rnd with googlecharts
const Highchart = () => {
return (
<rnd>
<div>
<HightchartsReact highcharts={Highcharts} constructorType={'chart'} options={option} />
</div>
</rnd>
)
}
You need to call chart.reflow method in onResizeStop event callback function.
return (
<Rnd
...
onResizeStop={(e, direction, ref, delta, position) => {
const chart = this.chartComponent.current?.chart;
if (chart) {
chart.reflow();
}
...
}}
>
...
</Rnd>
);
From Highcharts API:
reflow( [e])
Reflows the chart to its container. By default, the chart reflows
automatically to its container following a window.resize event, as per
the chart.reflow option. However, there are no reliable events for div
resize, so if the container is resized without a window resize event,
this must be called explicitly.
Live demo: https://codesandbox.io/s/cranky-hoover-cz-czw5k?file=/src/index.js
API Reference: https://api.highcharts.com/class-reference/Highcharts.Chart#reflow

Mimic React custom component

I have a custom Reactjs component to display Pagination with next/previous buttons at the bottom of a grid. Now, the business needs to display the same component on top of the grid as well. How to display the previous /next button events based on the input provided in prev/next buttons at the bottom of the grid?
I tried using javascript innerHTML to mimic the behaviour. It works only with the display. It does not attach the event listener of the buttons. I tried even with
document.querySelector.addEventListener('click', ()=>{console.log('test')})
It does not work. Is there a better way to do with react.
I am going to just add some more content to Shmili Breuer answer.
If i understood you correctly you have 2 navigations, one at the top one at the bottom. The way you connect them would be through a state of you component, or a parent component if you are using functional component to render pagination stuff. So if you change the state it will reflect on both of your navigations. Also you can use only one function here, by passing a parameter, im gonna copy a code from before mentioned answer.
// first create a function
nextFunction = (condition) => {
if(condition){
this.setState(prevState=>({
page: prevState.page-1
}))
} else {
this.setState(prevState=>({
page: prevState.page+1
}))
}
}
// then use it in your button
<button onClick={() => this.nextFunction(some condition)}>Next</button>
Just put that component on top and bottom
<Grid>
<Pagination />
{...someOtherComponents}
<Pagination />
</Grid>
it's ok in react. Optimization that you want to do is overhead.
In react you would add an onClick attribute to an element you want to handle a click on.
Something like this
// first create a function
nextFunction = () => {
do next functionality....
}
// then use it in your button
<button onClick={() => this.nextFunction()}>Next</button>
This way you can have both top and bottom pagination call the same function.
Hope this helps

How to check to see if a scrollbar is present in React?

I haven't seen a thread that handles this, at least not for React.
My case: I want to conditionally render a back to top button only when scrolling is an option. It makes no sense to have such a feature if it can't affect the page.
The only solutions I can find are in jQuery. I'm using react-scroll but couldn't find any functionality there for this.
When a scrollbar is visible then window.visualViewport.width < window.Width.
var buttonIsVisible = window.visualViewport.width < window.Width;
To check if scrollbar is visible in vertical appearance.
document.body.clientHeight > window.innerHeight
I added this code in a useEffect.
useEffect(() => {
if (document.body.clientHeight > window.innerHeight) {
something()
}
}, [state]);
Luke.
By "scrolling is an option" I am assuming here that you mean "when the scrollbar is visible."
As far as I am aware, there is not any way to check for scrollbar visibility using the React API. There is the DOM boolean window.scrollbars.visible; however, I have not had luck with this. It seems to always return true whether a scrollbar is visible or not. The following approach may work for you:
You could set an event listener for onScroll and check window.scrollY. If window.scrollY > 0, then you could conditionally render the button. If window.scrollY is 0, then the page is already scrolled to the top and there is no need to display the button.
Depending on the design of your web app, checking once for scrollbar visibility (e.g., on componentDidMount) may not be the best option, since some DOM elements may continue to load after the component initially mounts and the height of the page may change.
I hope this is helpful.
If you have a wrapper around the element that has the scroll you can detect the width difference.
<div className="wrapper">
<div className="scrollingContent">
Very long content here
</div>
</div>
const scrollBarWidth = this.wrapper.clientWidth - this.scrollingContent.clientWidth;
this.setState({ scrollBarWidth });
Most of the time (depending on edge cases where elements are sized differently). You can use an element ref to check if the scrollWidth is greater than the current width (or height for vertical scroll). The ref might not update scroll properties with useEffect hence why you need state in the dependencies array. Plus you will likely want to add a window resize event listener to run the same code.
const ref = useRef(null);
const [hasScrollBar, setHasScrollBar] = useState(false);
useEffect(() => {
function updateState() {
const el = ref.current;
el && setHasScrollBar(el.scrollWidth > el.getBoundingClientRect().width);
}
updateState();
window.addEventListener('resize', updateState);
return () => window.removeEventListener('resize', updateState);
}, [state]);
<div ref={ref} style={{ overflowX: 'auto' }}>
{state}
</div>

Change accessibility focus in react-native app on drawer/modal open

I'm trying to improve accessibility on a react native app and am facing the following problem: when the user opens the menu drawer, the focus doesn't change to the modal drawer content. Instead swiping left and right focuses content that's in the background.
I have tried setting dynamic accessibility props to the drawer and main content area:
<NavigationMenu
importantForAccessibility={isNavigationVisible ? 'yes' : 'no-hide-descendants'}
/>
<DashboardContent
importantForAccessibility={isNavigationVisible ? 'no-hide-descendants' : 'yes'}
/>
Where isNavigationVisible is a prop that gets updated when the drawer opens, but this had no effect.
Is there any way to force the focus change to the drawer when it opens?
This is what i ended up using:
const setFocus = ({ current: ref }) => {
const FOCUS_ON_VIEW = 8;
const reactTag = findNodeHandle(ref);
Platform.OS === 'android'
? UIManager.sendAccessibilityEvent(reactTag, FOCUS_ON_VIEW)
: AccessibilityInfo.setAccessibilityFocus(reactTag);
}
Currently, React-Native doesn't provide a way, to out-of-the-box, traverse the view tree and get the first focusable element to set the focus for it.
So you need to use AccessibilityInfo.setAccessibilityFocus passing a reactTag case by case.
Looks like there is a bug on AccessibilityInfo.setAccessibilityFocus(reactTag), it doesn't work consistently and calling it more than once increase the chance of success.
See this answer for how to make this call twice to do the focus on view launch.
See this open issue on github for more detail.

React: empty placeholder div gets re-rendered and thereby removes children (asynchr attached chart)

I am working on a widget dashboard which has DC.JS charts as content for each widget.
Widgets are created/ removed using react-grid-layout which creates an empty placeholder node like this:
<div id={"content_" + this.props.id} className="widgetContent"> /* chart is later drawn here */ </div>)
DC.JS later selects the div by Id and attaches its SVG chart as a child.
The problem is that for some events (like toggling static or changing Ids of the widgets), react re-renders the widgets and thereby "overwrites" the existing charts (children) with a brand new empty placeholder div as above.
My question is if that issue can be solved by React-techniques (can I prevent a div from ever being re-rendered?) or if this is an issue with the library itself.
Very similar code can be found here. The code in action is here. Imagine the snippet line above (the empty chart placeholder where a chart is attached later) in line 44.
The common solution here is to wrap this chart in a component where shouldComponentUpdate is set to false. That way react will never alter the element which your charting library modifies. An example wrapper component can be found here (including below)
var React = require('react/addons');
var ReactIgnore = {
displayName: 'ReactIgnore',
shouldComponentUpdate (){
return false;
},
render (){
return React.Children.only(this.props.children);
}
};
module.exports = {
Class: ReactIgnore,
Component: React.createClass(ReactIgnore)
};

Resources