How can I configure all availableCreateTools, such as freehand polyline, freehand polygon, and text?
Currently, I'm able to access all other tools except the three mentioned above.
I followed Sketch | ArcGIS Maps SDK for JavaScript
Below are the details:
ArcGIS Javascript SDK 4.32.13
React 19.0.0
NOTE: I am not using Typescript. instead, I am writing code in .jsx file.
Case-1: Below is the code snippet being used to initialize the sketch component:
const sketchElement = sketchRef.current;
sketchElement.view = mapView;
sketchElement.availableCreateTools = [
"point",
"multipoint",
"freehandPolyline", // Not showing
"polyline",
"freehandPolygon", // Not showing
"polygon",
"rectangle",
"circle",
"text" // Not showing
];
sketchElement.layer = sketchLayer;
I’ve also attempted the second approach as outlined below. Case 2: This is the code snippet used to initialize the sketch component.
<arcgis-sketch
ref={sketchRef}
layout="vertical"
creation-mode="update"
scale="m"
toolbar-kind="docked"
show-create-tools-freehand-polyline
show-create-tools-freehand-polygon
/>
Despite trying both approaches, the freehand polyline, freehand polygon, and text buttons are still not appearing in the Sketch UI. Any insights?
If you're using JSX, you probably need to use the the camelCase for attributes.
However, it does look like the multipoint and text options will not show at the moment. We're looking into this and will have this updated in 5.0.
Ok, small update. I had to set a timeout and the multipoint tool does show up. The text tool does not as that is not quite ready yet. https://codepen.io/odoe/pen/myPJvgd?editors=1001
Thanks @ReneRubalcava for response. I tried what you suggest but still freehandpolygon and freehandpolyline is not showing up in UI.
Here is full code of mine, can you have look at it and help to make it run:
/* eslint-disable react/prop-types */
import React, { useState, useEffect, useRef, useContext, useCallback } from 'react';
import ReactDOM from 'react-dom';
import { useTheme } from '@mui/material/styles';
import { IconButton, Popper, Box, Typography } from "@mui/material";
import IconMarkup from '../../assets/icons/IconMarkup.svg?react';
import { MapContext } from './Context/MapContext.jsx';
import "@arcgis/map-components/components/arcgis-sketch";
import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer";
// Import the new custom tool
import MarkupCustomTool from './MarkupCustomTool.jsx';
function MarkupTool ({
containerStyle,
activeDialog,
onDialogToggle,
}) {
const theme = useTheme();
const dialogId = 'markupDialog';
const dialogIsOpen = activeDialog === dialogId;
const [tooltipAnchorEl, setTooltipAnchorEl] = useState(null);
const [openPopper, setOpenPopper] = useState(false);
const id = openPopper ? 'markup-popper' : undefined;
const [sketchLayer, setSketchLayer] = useState(null);
const sketchRef = useRef(null);
const { mapView } = useContext(MapContext);
// Use useCallback for the ready handler
const handleSketchReady = useCallback(() => {
const sketchElement = document.querySelector("arcgis-sketch");
if (!sketchElement) {
console.log("Sketch element not found in handleSketchReady");
return;
}
console.log("✅ Sketch element ready (handleSketchReady fired)");
// Small timeout to ensure the element is fully initialized
setTimeout(() => {
sketchElement.availableCreateTools = [
"point",
"multipoint",
"polyline",
"freehandPolygon",
"freehandPolyline",
"polygon",
"rectangle",
"circle",
"text" // Not showing intentionally for now
];
console.log("Available tools set:", sketchElement.availableCreateTools);
}, 1000);
}, []);
useEffect(() => {
if (!mapView) return;
const layer = new GraphicsLayer({
id: "markup_graphics_layer",
title: "Markup Graphics"
});
setSketchLayer(layer);
mapView.map.add(layer);
return () => {
if (mapView && !mapView.destroyed) {
mapView.map.remove(layer);
}
};
}, [mapView]);
const handleButtonClick = () => {
onDialogToggle(dialogId);
setOpenPopper(false);
setTooltipAnchorEl(null);
};
const handleMouseEnter = (event) => {
setTooltipAnchorEl(event.currentTarget);
if (!dialogIsOpen) {
setOpenPopper(true);
}
};
const handleMouseLeave = () => {
setOpenPopper(false);
setTooltipAnchorEl(null);
};
useEffect(() => {
if (dialogIsOpen) {
setOpenPopper(false);
setTooltipAnchorEl(null);
}
}, [dialogIsOpen]);
useEffect(() => {
if (!dialogIsOpen || !mapView || !sketchLayer) return;
// Use a slight delay to ensure the element is in the DOM
const timer = setTimeout(() => {
const sketchElement = document.querySelector("arcgis-sketch");
if (!sketchElement) {
console.log("Sketch element not found");
return;
}
console.log("Setting up sketch element");
// Set view and layer first
sketchElement.view = mapView;
sketchElement.layer = sketchLayer;
// Check if already ready (widget property exists)
if (sketchElement.widget) {
console.log("Sketch element already ready");
handleSketchReady();
} else {
console.log("Waiting for arcgisReady event");
// Add event listener for when it becomes ready
sketchElement.addEventListener("arcgisReady", handleSketchReady);
}
// Cleanup function
return () => {
sketchElement.removeEventListener("arcgisReady", handleSketchReady);
};
}, 100);
return () => {
clearTimeout(timer);
};
}, [dialogIsOpen, mapView, sketchLayer, handleSketchReady]);
return (
<>
<IconButton
variant="contained"
style={containerStyle}
sx={{
width: 48,
height: 48,
backgroundColor: dialogIsOpen ? theme.appColor.darkGray : theme.appColor.darkGray,
color: dialogIsOpen ? theme.appColor.lightBlue: 'white',
'&:hover': {
backgroundColor: dialogIsOpen ? theme.appColor.darkGray : 'white',
color: dialogIsOpen ? theme.appColor.lightBlue : theme.appColor.darkGray,
},
'&:active': {
backgroundColor: dialogIsOpen ? 'white' : 'white',
color: dialogIsOpen ? theme.appColor.darkGray : theme.appColor.lightBlue,
},
}}
onClick={handleButtonClick}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
aria-describedby={id}
aria-label="MarkupButton"
>
<IconMarkup alt="Markup" />
</IconButton>
<Popper
id={id}
open={openPopper}
anchorEl={tooltipAnchorEl}
placement="left"
disablePortal={false}
modifiers={[{ name: 'offset', options: { offset: [0, 10] } }]}
>
<Box sx={{
border: '#DFDFDF',
padding: '12px',
bgcolor: 'white',
borderRadius: '8px',
boxShadow: 3,
}}>
<Typography variant="body2">Markup Tools</Typography>
</Box>
</Popper>
{dialogIsOpen && mapView && mapView.container && (
ReactDOM.createPortal(
<Box
sx={{
position: 'absolute',
top: 150,
right: 82,
backgroundColor: 'white',
boxShadow: 3,
borderRadius: '8px',
zIndex: 1300,
}}
>
<arcgis-sketch
ref={sketchRef}
layout="vertical"
creation-mode="update"
scale="m"
toolbar-kind="docked"
hide-selection-tools-lasso-selection
show-create-tools-freehand-polygon
show-create-tools-freehand-polyline
showCreateToolsFreehandPolyline
/>
<MarkupCustomTool
sketchLayer={sketchLayer}
sketchRef={sketchRef}
dialogIsOpen={dialogIsOpen}
/>
</Box>,
mapView.container
)
)}
</>
);
}
export default MarkupTool;
@ReneRubalcava Is there any way we can get a status update on the text functionality in the Sketch component? The `show-create-tools-text` attribute is in the documentation but doesn't seem to work yet.
@ReneRubalcava Tools that are known not to work should not be documented as if they do.
Hello,
In order to display the FreehandPolyline, FreehandPolygon, and Text create tools in <arcgis-sketch />, you need to set the `availableCreateTools` and the following props:
Here is a test app to show this: https://codepen.io/banuelosj/pen/wBgZoLL?editors=1000
Note: The freehand tools will display with the segment tools for lines and polygons. So you need to select the line or polygon tools first to see the freehand line segments.
We are working on improving the documentation for the text create tool this release, and then in the near future the entire API for setting your create tools. We understand that the requirement to view these tools is to set props in 2 places. AvailableCreateTools and their corresponding props. This is not a good API, so we are working on improving this where you only have to worry about setting the create tools in one place to use them in Sketch.
Thanks,
Jose
@JoseBanuelos The text interface also needs a way for the user to change the value of the TextSymbol. It is practically useless without this option. Controls for color, size and other options would also be nice, but are not absolutely necessary.