I recently upgraded my Material UI from V4 to 5 and stuck with a truckload of issues. One of them is that the styles are messing up when i move away from JSS
The arrow icon need to get the styles and the styles are not getting applied.
const StyledPopper = styled(Popper)(({ theme }) => {
return {
[`&.${classes.popper}`]: {
top: "100px !important",
left: "200px !important",
zIndex: 1,
'&[x-placement*="bottom"] $arrow': {
// is not getting applied
marginTop: theme.spacing(-5.25),
"&::before": {
borderWidth: "0 1em 1em 1em",
borderColor: `transparent transparent red transparent`
}
}
},
[`& .${classes.arrow}`]: {
position: "absolute",
"&::before": {
content: '""',
display: "block",
borderStyle: "solid"
}
}
};
});
<StyledPopper
open
placement="bottom-end"
anchorEl={
document && document.getElementById("location-confirmer-desktop")
}
modifiers={{ arrow: { enabled: true, element: arrowRef } }}
className={classes.popper}
>
<Box ref={setArrowRef} className={classes.arrow} />
<Box>This is the content</Box>
</StyledPopper>
https://codesandbox.io/s/combobox-demo-material-ui-forked-v5-8-4-g0pyhg?file=/demo.tsx
I'm having the following code:
<SafeAreaView style={styles.container}>
<StatusBar />
<KeyboardAwareScrollView keyboardShouldPersistTaps='handled' contentContainerStyle={styles.keyboardAwareScrollView}>
<ScrollView ref={scrollViewRef} onContentSizeChange={() => scrollViewRef.current.scrollToEnd({ animated: true })} keyboardShouldPersistTaps='handled'>
{steps.map(item => { return (<SingleAlgorithmStep key={item["Question"]} step={item} stepsDone={steps} clickedButtons={clickedButtons} algorithmJson={currentAlgorithmJson} actualizeSteps={(item) => updateSteps(item)} actualizeButtons={(item) => updateClickedButton(item)} />) })}
</ScrollView>
</KeyboardAwareScrollView>
</SafeAreaView>
with these styles:
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: '#fff',
alignItems: 'center',
padding: 10
},
keyboardAwareScrollView: {
flex: 1
},
Sometimes the SingleAlgorithmStep contains just buttons sometimes it contains a textinput. If runnig the app on android, everything works fine. But when i'm running it on ios and i get a text input, the scrollview does not scrolling completly down. I have to close the keyboard and reopen it oder manually scroll down. How can I fix this?
I am using #react-native-mapbox-gl/maps and I want to implement clustering for markers. I couldn't find any solution for my implementation. Attach image will show that two markers should be combined but they are not.
Below I am pasting my code:
<MapboxGL.MapView
showUserLocatin={true}
zoomLevel={10}
zoomEnabled={zoomEnabled}
pitchEnabled={true}
onPress={onMapPress}
onRegionIsChanging={onRegionIsChanging}
surfaceView={true}
rotateEnabled={rotateEnabled}
compassEnabled={false}
showUserLocation={false}
userTrackingMode={MapboxGL.UserTrackingModes.None}
scrollEnabled={scrollEnabled}
styleURL={styleURL}
centerCoordinate={getFocusPoint() || getStartingPoint()}
ref={(c) => (_map = c)}
onRegionDidChange={onRegionChange}
style={style}
cluster
>
{renderLines()}
<MapboxGL.SymbolLayer
id={'abc'}
sourceID={MapboxGL.StyleSource.DefaultSourceID}
/>
<MapboxGL.Camera
zoomLevel={zoom}
centerCoordinate={getFocusPoint() || getStartingPoint()}
/>
{(simplePlaceData?.length > 0 || places?.length > 0) && renderMarkers()}
</MapboxGL.MapView>
Below is our renderMarkers function( basically I am displaying any RN component like image/icon inside MapboxGL.PointAnnotation):
const renderMarkers = () => {
if (simplePlaceData)
return simplePlaceData?.map((_place) => {
const {lat, lng, id} = _place
const latVal = parseFloat(lat)
const lngVal = parseFloat(lng)
if (!lat || !lng || isNaN(latVal) || isNaN(lngVal)) return null
return (
<MapboxGL.PointAnnotation
key={`${id}`}
id={`${id}`}
title={`${lat}-${lng}`}
coordinate={[parseFloat(lng), parseFloat(lat)]}>
<Col style={styles.mapMarkers}>
<Icon
name={'map-marker'}
family={'materialCommunity'}
color={Colors.linkBlue}
size={31}
/>
</Col>
</MapboxGL.PointAnnotation>
)
})
else
return places?.length > 0 && places.map(_place => {
const {lat, lng, id, image, name} = _place.trip_place.place
const isSelected = (getFocusPoint() || getStartingPoint())?.first() == lng &&
(getFocusPoint() || getStartingPoint())?.last() == lat
if (Platform.OS === 'ios') {
return (
<MapboxGL.PointAnnotation
key={`${id}`}
id={`${id}`}
title={name}
coordinate={[parseFloat(lng), parseFloat(lat)]}
>
<MapMarker
image={{uri: image}}
imageSize={isSelected ? 41 : 31}
style={isSelected ? styles.mapMarkersSelected : styles.mapMarkers}
onPress={() => selectPlace(_place.trip_place.place, true)}
/>
</MapboxGL.PointAnnotation>
)
} else {
return (
<MapboxGL.MarkerView
id={`${id}`}
key={`${id}`}
coordinate={[parseFloat(lng), parseFloat(lat)]}
title={name}
>
<View style={isSelected ? styles.mapMarkerContainerSelected : styles.mapMarkerContainer}>
<MapMarker
image={{uri: image}}
imageSize={isSelected ? 41 : 31}
style={isSelected ? styles.mapMarkersSelected : styles.mapMarkers}
onPress={() => selectPlace(_place.trip_place.place, true)}
/>
</View>
</MapboxGL.MarkerView>
)
}
})
}
Is there any solution to to apply for MapboxGL.PointAnnotation to show markers as a combined cluster with number of items inside? Or there is anothe component of MapboxGL which I can use to achieve this functionality?
Thanks
So from my experience with React Native Mapbox GL, you can't use point annotations for clustering. You'll have to use icons. One rule you have to keep in mind for this to work is that your markers have to be GEO JSON features collection. Checkout the link below if you don't know what that is.
https://enterprise.arcgis.com/en/geoevent/latest/ingest/GUID-F489B3D2-74DB-4EA2-8A4E-330628193843-web.png
Once you have your feature collection, you feed it into the Shapsource and clusters should start showing up.
<MapboxGL.ShapeSource
ref={shapeSource}
shape={{ type: 'FeatureCollection', features: [...''] }}
id="symbolLocationSource"
hitbox={{ width: 18, height: 18 }}
onPress={async point => {
if (point.features[0].properties.cluster) {
const collection = await shapeSource.current.getClusterLeaves(
point.features[0],
point.features[0].properties.point_count,
0,
)
// Do what you want if the user clicks the cluster
console.log(collection)
} else {
// Do what you want if the user clicks individual marker
console.log(point.features[0])
}
}}
clusterRadius={50}
clusterMaxZoom={14}
cluster
>
In order to get individual pictures for markers to show up once you zoom in; You'll need to get the image from the individual marker. So if you have a feature collection, each feature should have an image, you could either use an image stored in your project folder and replace the iconImage property in the symbol. Or if your feature has a link to an image, you could use the property in the feature like so:
iconImage: ['get', '___ whatever name you gave the link___'],
<MapboxGL.SymbolLayer
id="singlePoint"
filter={['!', ['has', 'point_count']]}
style={{
iconImage: ['get', '___ whatever name you gave the link___'],
iconSize: 0.3,
iconHaloColor: 'black',
iconHaloWidth: 10,
iconColor: 'white',
iconHaloColor: 'black',
iconHaloWidth: 400,
iconAllowOverlap: true,
}}
/>
in order to get that to show up you need mapbox images
<MapboxGL.Images
images={images}
onImageMissing={async url => {
setImages({ ...images, [url]: { uri: await getImage(url) } })
}}
/>
So that get request we did with the link, will call the mapbox images. Just make sure you have an images, and setImages in your state. This will then allow you to show the current image of your point annotation. Only problem is that it's hard to edit, so you can't just make them appear as circles unless they're cropped that way.
<MapboxGL.MapView
style={styles.map}
ref={mapRef}
styleURL="___ url___"
zoomEnabled
>
<MapboxGL.Camera
animationDuration={250}
ref={ref => (this.camera = ref)}
minZoomLevel={5}
zoomLevel={6}
maxZoomLevel={20}
animationMode="flyTo"
centerCoordinate={currrentLocation}
Level={stateZoomLevel}
/>
<MapboxGL.Images
images={images}
onImageMissing={async url => {
setImages({ ...images, [url]: { uri: await getImage(url) } })
}}
/>
{/* Cluster Individual Drop View */}
<MapboxGL.ShapeSource
ref={shapeSource}
shape={{ type: 'FeatureCollection', features: [...''] }}
id="symbolLocationSource"
hitbox={{ width: 18, height: 18 }}
onPress={async point => {
if (point.features[0].properties.cluster) {
const collection = await shapeSource.current.getClusterLeaves(
point.features[0],
point.features[0].properties.point_count,
0,
)
// Do what you want if the user clicks the cluster
console.log(collection)
} else {
// Do what you want if the user clicks individual marker
console.log(point.features[0])
}
}}
clusterRadius={50}
clusterMaxZoom={14}
cluster
>
<MapboxGL.SymbolLayer
id="pointCount"
style={layerStyles.clusterCount}
/>
<MapboxGL.UserLocation
visible
onUpdate={location => {
setCurrentLocation({
latitude: location.coords.latitude,
longitude: location.coords.longitude,
})
}}
/>
<MapboxGL.CircleLayer
id="clusteredPoints"
belowLayerID="pointCount"
filter={['has', 'point_count']}
style={{
circlePitchAlignment: 'map',
circleColor: '#A59ADD',
circleRadius: [
'step',
['get', 'point_count'],
20,
100,
25,
250,
30,
750,
40,
],
circleOpacity: 0.84,
circleStrokeWidth: 0,
circleStrokeColor: 'blue',
}}
/>
<MapboxGL.SymbolLayer
id="singlePoint"
filter={['!', ['has', 'point_count']]}
style={{
iconImage: ['get', '__image name___'],
iconSize: 0.3,
iconHaloColor: 'black',
iconHaloWidth: 10,
iconColor: 'white',
iconHaloColor: 'black',
iconHaloWidth: 400,
iconAllowOverlap: true,
}}
/>
</MapboxGL.ShapeSource>
</MapboxGL.MapView>
const layerStyles = {
singlePoint: {
circleColor: 'green',
circleOpacity: 0.84,
circleStrokeWidth: 2,
circleStrokeColor: 'white',
circleRadius: 5,
circlePitchAlignment: 'map',
},
clusteredPoints: {},
clusterCount: {
textField: '{point_count}',
textSize: 12,
textPitchAlignment: 'map',
},
}
If this helped upvote!
I'm having an issue with replacing the Input component for react-select v2 with the Input component from Material UI.
I've made an attempt so far in the codesandbox below, but unable to invoke the filtering upon typing into the Input?
https://codesandbox.io/s/jjjwoj3yz9
Also, any feedback on the Option replacement implementation would be appreciated. Am I going about it the right way with grabbing the text of the clicked option and search for the Option object from my options list to pass to the selectOption function?
Much appreciated,
Eric
V1
refer the documentation from here : https://material-ui.com/demos/autocomplete/
it provides clear documentation about how to use react-select with material-ui
here is a working example for your question: https://codesandbox.io/s/p9jpl9l827
as you can see material-ui Input component can take react-select as inputComponent.
V2
It's almost same as the previous approach :
implement the Input component:
<div className={classes.root}>
<Input
fullWidth
inputComponent={SelectWrapped}
value={this.state.value}
onChange={this.handleChange}
placeholder="Search your color"
id="react-select-single"
inputProps={{
options: colourOptions
}}
/>
</div>
and then SelectWrapped component implementation should be:
function SelectWrapped(props) {
const { classes, ...other } = props;
return (
<Select
components={{
Option: Option,
DropdownIndicator: ArrowDropDownIcon
}}
styles={customStyles}
isClearable={true}
{...other}
/>
);
}
and I overrides the component Option and DropdownIndicator to make it more material and added customStyles also:
const customStyles = {
control: () => ({
display: "flex",
alignItems: "center",
border: 0,
height: "auto",
background: "transparent",
"&:hover": {
boxShadow: "none"
}
}),
menu: () => ({
backgroundColor: "white",
boxShadow: "1px 2px 6px #888888", // should be changed as material-ui
position: "absolute",
left: 0,
top: `calc(100% + 1px)`,
width: "100%",
zIndex: 2,
maxHeight: ITEM_HEIGHT * 4.5
}),
menuList: () => ({
maxHeight: ITEM_HEIGHT * 4.5,
overflowY: "auto"
})
};
and Option:
class Option extends React.Component {
handleClick = event => {
this.props.selectOption(this.props.data, event);
};
render() {
const { children, isFocused, isSelected, onFocus } = this.props;
console.log(this.props);
return (
<MenuItem
onFocus={onFocus}
selected={isFocused}
onClick={this.handleClick}
component="div"
style={{
fontWeight: isSelected ? 500 : 400
}}
>
{children}
</MenuItem>
);
}
}
please find the example from here: https://codesandbox.io/s/7k82j5j1qx
refer the documentation from react select and you can add more changes if you wish.
hope these will help you.
Im currently using ExtJs5 MVVM architecture and I require "sencha-chart" than "ext-chart" on the app.json file, Charts works fine but adding tooltip on the bar series im using doesn't work. No error logs.
I also check their example on sencha chart kitchensink (which chart tooltip is working) found out that they require "ext-chart" for that. My code for bar series with tooltip config:
series: [{
type: 'bar',
xField: 'name',
yField: ['data1'],
style: {
opacity: 0.80
},
highlight: {
fill: '#000',
'stroke-width': 20,
stroke: '#fff'
},
tips: {
trackMouse: true,
style: 'background: #FFF',
height: 20,
renderer: function(storeItem, item) {
this.setTitle(storeItem.get('name') + ': ' + storeItem.get('data1') + '%');
}
}
}]
Is there something wrong with my codes?
Thanks
Your code needs one small change "tips" for EXTjs 5 becomes "tooltip."
tooltip: {
trackMouse: true,
style: 'background: #FFF',
height: 20,
renderer: function(storeItem, item) {
this.setTitle(storeItem.get('name') + ': ' + storeItem.get('data1') + '%');
}
}
However, there are a lot of bugs with the EXTjs 5 charts. I had this same issue, and submitted a bug to Sencha:
http://www.sencha.com/forum/showthread.php?289313-Sencha-EXTjs-5-Charts-Broken-Tooltips
tooltip: {
trackMouse: true,
style: 'background: #FFF',
height: 20,
renderer: function(storeItem, item) {
this.setHtml(storeItem.get('name') + ': ' + storeItem.get('data1') + '%');
}
}
I used tooltip inplace of tips and this.setHtml() in place of this.setTitle() ,and it worked for me.