In Part 1, we introduced the first partnering opportunity with our new sister company HydroMax USA. This initial project involved the replacement of HydroMax’s existing Trimble-based field survey data collection process with Esri’s Collector and Survey123. The post laid the foundation required to begin coding a custom widget. So…let’s now start coding.
There are a number of methods that are predefined in the widget.js file. Following our process flowchart (shown in Part 1), the first task needing accomplishment is to allow the drawing of a shape on the map that will act as a selection box. Using the onOpen function (Figure 1), it ensures that the drawing doesn’t start automatically because the widget has been added to the application.
When the widget is opened, the OnOpen function starts a new drawToolbar event. When the tool’s functionality is no longer required, the onClose function (Figure 2) is utilized to clear the graphics layer of any active drawings and deactivate the drawToolbar. Otherwise…drawing will still be possible even if the widget isn’t active.
Now that some prerequisites have been addressed, the startup function is next to execute the necessary code to draw the shape on the map (Figure 3). This is used to assign some variables that will be leveraged throughout the process by giving the widget’s map variable a specific value.

Following variable population, the graphics layer will be needed to render the selection shape. Since the graphics layer is not part of the application’s map, it must be added with a bit of code (Figure 4).
Now that the foundation has been created for drawing, the actual drawing tool can be coded (Figure 5).
Needless to say, there are several manual steps just to create the drawing, so the user knows which points will be selected. But now that the geometry exists, querying for points will be much simpler. In this example the points are provided by an address layer. The address layer needs to be retrieved and saved to a variable for subsequent query for points within the geometry. The layerid is stored in configuration variable for user later with a query.
Now that the address layer is available, a query is necessary (Figure 6). The query object has a geometry property that is set to the same geometry created by the draw event previously. The property is then passed into the selectFeatures function of the address layer. One of the parameters of the selectFeatures function is an anonymous function that provides the result of the query.
As seen in Figure 6, this is passed to another function (createAssignPopulateTable) that is responsible for adding each result to a table in the UI. Between these two methods each result is added to a table in the UI called createResults. With that, the code to make a shape-based selection from a custom widget is complete and retrievable for creating the assignments or adding data to any layer provided by the map.
Now it is time to add functionality to actually do something useful with the selected data. This is done through using an event triggered by a button in the UI. Upon clicking the button an event handler called onClickCreateWorkforce is called. This method has the task of creating the point that will represent a workforce assignment.
In order to save a feature to the point layer, an object needs to be created and defined (as well as a “Results” table and “Assignments” layer). After grabbing these items, the remaining requirement is to loop through each result and add it to the assignments layer. A new point is created using attributes from the results table. This then gets passed to a function of a feature layer: applyEdits. This function is for committing edits in a feature layer that will need to be reflected in the data. The odd thing here to note is that this function call is assigned to a variable called promise (Figure7).
This is because applyEdits acts asynchronously, meaning the request to save is sent to the server but code execution continues even though a response hasn’t been received yet. To handle this, a function of a promise is then used to receive the returned value. Since nothing needs to be done after the new assignment has been created, the function does not perform any work with the returned result. After creating the point, a refresh of the layer will ensure the new assignments appear.
Look for Part 3 which will outline the final implementation of our custom widget.
What do you think?