React-Leaflet-v3 Reusable Custom Control - reactjs

Background
For React Leaflet v2, there was an NPM plugin, react-leaflet-control, that allowed you to create any kind of control and place it into the react-leaflet control container. Obviously with the introduction of RL-v3, this no longer works in v3 with the API changes. I want to create a custom control wrapper to allow me to place in it any type of React Node.
Current status
The code that I have currently works...but doesn't. I pulled from the example in this Stack Overflow post: React Leaflet V3 Custom Control that gets me to the 99% solution of creating a custom control. However, my use case is a toolbar on the map with buttons that are interactable (colors to designate active tool). With this code, however, I have that functionality, but because every render causes a new control to be created, the Tooltip flickers as it is losing its anchor element.
Desired behavior
I want a toolbar that allows users to select tools to perform actions on the map (think old-school leaflet-draw. And to provide feedback, I want the button to change color when the tool is active and for UX, I want tooltips to describe the action of the button.
Actual behavior
The toolbar exists, users can select tools and there is UI feedback, however, the tooltips lose their anchor element as the control is removed and re-added on every render when selecting a tool.
Code Sandbox
https://codesandbox.io/s/react-leaflet-custom-control-n1xpv

I ended up with an answer that kind of takes in what #teddybeard was saying. If I just created my new div with the class as suggested, it would be placed on top of any default controls such as ZoomControl or ScaleControl. Instead, what I did was grab the actual position div container from the DOM, and then created a ReactDOM portal into that container and added my control in that way.
It works, doesn't have the issues with visual flashing due to the React Effect removing and re-adding the control on every render and I still get the same positioning.
It's live on npm and github at https://github.com/chris-m92/react-leaflet-custom-control and https://npmjs.com/package/react-leaflet-custom-control
const POSITION_CLASSES = {
bottomleft: 'leaflet-bottom leaflet-left',
bottomright: 'leaflet-bottom leaflet-right',
topleft: 'leaflet-top leaflet-left',
topright: 'leaflet-top leaflet-right',
}
const Control = (props: Props): JSX.Element => {
const [container, setContainer] = React.useState<any>(document.createElement('div'))
const positionClass = (props.position && POSITION_CLASSES[props.position] || POSITION_CLASSES.topright)
React.useEffect(() => {
const targetDiv = document.getElementsByClassName(positionClass)
setContainer(targetDiv[0])
}, [])
const controlContainer = (
<div className='leaflet-control leaflet-bar'>{props.children}</div>
)
L.DomEvent.disableClickPropagation(container)
return ReactDOM.createPortal(
controlContainer,
container
)
}
export default Control

Related

How to add text box in Microsoft webchat smart display sample?

For a project I am using Microsoft webchat smart display sample.
Smart Display github link
Now I want to add a Text box on the screen so that user can use voice as well as text as input. As the code is using directlinespeech adaptor how can I add textbox in this code.
You can achieve this by simply including the SendTextBox component within the Composer API container. There is nothing pretty about how the below code renders as it is lacking any styling. You will need to play with the CSS to get it to look how you wish. As you can see in the included image, the send box is rendered at the top of the page. I did change the background color to make it more visible within the image.
import { Components } from 'botframework-webchat';
const { SendTextBox, Composer } = Components;
[...]
return (
!!directLineSpeechAdapters && (
<Composer {...directLineSpeechAdapters}>
<SmartDisplay />
<SendTextBox />
</Composer>
)
);
Hope of help!

AppBar / Dialog within child container boundaries

My issue stems from wishing to have a mobile phone rendered in the page, which mimics that of an actual phone. I would like to use components from Material UI such as AppBar and Dialog, however they do not stay confined to the container of the phone, and instead still show in the entire browser window.
When I use a Dialog Component however, it's still relative to the actual browser viewport, and not that of the "phone", such as the following:
I would like it to do what is seen in the picture below, without using an IFrame.
Is there a way I can set an anchor for the components - or at least force them to treat a specific element as their boundary? Thanks.
For those wondering if this is resolved, the solution was to roll my own Dialog and Backdrop Components with Paper, and Box components.
A ref was passed into a Box component which surrounds the entire "Phone App", and it's current Element is passed into a Mui Portal's container property.
This allows for the container of the Custom "Dialog" to be the container I wished to have things bounded by.

How do I set my default theme for all icons on Antd?

I am looking to set the default theme for all the Icons that I'm using through ANTD to 'filled' rather than having to pass theme='filled' to every individual icon I create. I have many instances of Icon throughout my APP and going to pass in that to every one (as well as modals) , it would be time consuming. How can I go about setting a default theme on all icons to be 'filled' without changing every instance (also effecting icons used in modals).
There is no direct way to modify at one place and it will reflect to all places. But you can always wrap Icon component of andt for your custom component like following
const CustomIcon = (props) => {
return (
<Icon theme="filled" {...props} />
)
}
Also, you can use regex to search the icon component in all your files and change/add theme to filled.
NOTE: Many icons in default theme are not present in other themes.

React/Material UI - Prevent body scrolling on popover

New to React and MUI, and having a UX issue where when we have a popover (dropdown menu, or autoselect dropdown) we can still scroll the main body of the site. I see that its fixed in the new beta V1 for MUI, but using the current stable release, Ive been asked to see if we can hack it up to stop the scrolling - but I cant seem to target/catch anything when we have a popover appear.
Examples: Current MUI - http://www.material-ui.com/#/components/auto-complete
V1 Beta MUI - https://material-ui-next.com/demos/autocomplete/
So, if you were to input something in those examples and trigger the downdown/popover, youll see that in the current MUI, you can still scroll the
I was hoping someone may have had this issue and had a solution they'd like to share?
Thanks guys!
I had a similar problem and solve it using 'disablePortal' Autocomplete property:
You can take a look at 'disablePortal' definition in here:
https://material-ui.com/api/autocomplete/#props
disablePortal: Disable the portal behavior. The children stay within it's parent DOM hierarchy.
I also had to add some styles to get pop up get positioned relative to input component.
Here is some sort of example:
const useStyles = makeStyles({
popperDisablePortal: {
position: 'relative',
}
})
const classes = useStyles()
<Autocomplete
classes={classes}
disablePortal={true}
{...props}
/>
So you may have to:
set up disablePortal property
define associated popperDisablePortal style with 'relative' position
EDIT: actually this error should not happen as part of default MUI Autocomplete set up. In my case, the error was some conflicting CSS property that was generating this scroller bug. Not sure in your case, but to me it happens to be some overflow: auto property defined on page HTML tag (sometimes you can find it on body tag). Replace with overflow: 'visible' and scrolling error should be gone without even changing one line of autocomplete component definition.

Silverlight component not loaded on MSCRM 2011 form

I have a section with silverlight component that is visible depending on the status of records.
If I set that section's Visible By Default = true and hide it in some cases => it works.
But I could not set it Visible by default = true because the screen loading is NOT smooth (the silverlight component appears and disapears)
Alternately, I hide it by default (Visible by default = false) and only show it if needed (jscript - onload)
=> it does NOT work!! The silverlight component is empty! I've already tried a very simple silverlight component with just a simple label, but it's still the same issue.
I guess it's a problem of loading siverlight webresource on MSCRM 2011...
Please help. Thanks.
I found out the problem, I think it's a bug in CRM. In my onload, I add it
var s = document.getElementById("WebResource_silverlight");
s.style.height = "100%"
and then it's visible again :)

Resources