Creating widgets

This page describes an older version, please read about the latest version at:
http://resources.arcgis.com/en/help/flex-viewer/concepts/

Requirements

You can modify an existing widget or create a new widget. In addition to the source code for all the main widgets, there is also three example widgets in the src\widgets\Samples folder (that is, HelloWorld, TestOpenClose, and ThematicQuery). The HelloWorld widget is a bare-bones widget that is a good start for understanding how a widget works. The TestOpenClose widget was added in version 2.4 and contains sample code for opening and closing widgets.

Basic steps for creating widgets

  1. Use the HelloWorld widget as a starting point.
  2. Copy the HelloWorld widget into a new location and rename it.

    In Flash Builder, with the Flex Viewer project open, in the tree (Package Explorer), open FlexViewer > src > widgets > Samples. Right-click the "HelloWorld" package and select Copy. Assuming that you want the new widget to also be in the Samples folder, right-click the "Samples" directory and select Paste. A dialog box appears asking you to enter the name for the new widget. Type the new name and click OK. You should also rename the actual widget (not just the package name). Right-click the .mxml file and rename it (do the same for the .xml file).

  3. Add your code as appropriate.
  4. Compile your widget, like any other Flex module.

    In Flash Builder, with the Flex Viewer project open, go to Project > Properties > Flex modules. Click Add, click Browse, then navigate to your new widget .mxml file. Click OK three times.

  5. Make sure the SWF [and optionally your widget configuration file if you use that]) file is copied into your bin-debug folder, for example, C:\inetpub\wwwroot\flexviewer\widgets\samples\MyWidget.

If your widget adds its own layers

TipTip:

As a viewer standard, the widget should hide any layers it created when users close the widget. When the widget is minimized, the layers should normally remain. To do this, make sure you use the open and closed events of the viewer:WidgetTemplate:

<viewer:WidgetTemplate id="wTemplate"
                       height="100%" width="100%"
                       minHeight="190"
                       minWidth="220"
                       closed="widgetClosedHandler(event)"
                       open="widgetOpenedHandler(event)">

In your Script section use code similar to the following:

private function widgetClosedHandler(event:Event):void
{
    if (graphicsLayer)
    {
        graphicsLayer.visible = false;
    }
}

private function widgetOpenedHandler(event:Event):void
{
    if (graphicsLayer)
    {
        graphicsLayer.visible = false;
    }
}

If your widget needs to get hold of the map

Any widget that extends BaseWidget will have access to the main map as "map."

The following is a code example from the Bookmark widget:

var ext:Extent = map.extent;

The following is a code example from the Coordinate widget:

if (map.loaded)
...
map.addEventListener(MapEvent.LOAD, map_loadHandler);
...
map.addEventListener(MouseEvent.MOUSE_MOVE, map_mouseMoveHandler);

The following is a code example from the Data Extract widget:

map.addLayer(graphicsLayer);
...
gp.processSpatialReference = map.spatialReference;
gp.outSpatialReference = map.spatialReference;

If your widget wants to add a graphics layer

Wait for widgetConfigLoaded, then proceed like the GeoRSS widget:

graphicsLayer = new GraphicsLayer();
graphicsLayer.name = "GeoRSS Feed";
graphicsLayer.symbol = resultMarkerSymbol;
graphicsLayer.addEventListener(FlexEvent.HIDE, graphicsLayer_hideHandler);
map.addLayer(graphicsLayer);
Don't forget to turn off the graphicslayer when the widget is closed, and turn it back on when the widget is reopened.
<viewer:WidgetTemplate
    ....
    closed="wTemplate_closeHandler(event)"
    ...
    open="wTemplate_openHandler(event)">
...
private function wTemplate_widgetClosedHandler(event:Event):void
{
    if (graphicsLayer)
    {
        graphicsLayer.visible = false;
        hideInfoWindow();
    }
}
...
private function wTemplate_widgetOpenedHandler(event:Event):void
{
    if (graphicsLayer)
    {
        graphicsLayer.visible = true;
    }
}

If your widget needs to get hold of the layers in the map

Review the layers property of the map.

for each (var layer:Layer in map.layers)
{
    // Loops through all layers in the main map.
}

If your widget needs to know when the basemap changes

Add an event listener for BASEMAP_SWITCH.

If you want to access other widgets

The WidgetManager has four useful functions for working with other widgets. See the TestOpenClose widget in the samples folder for an example.

getWidget
public function getWidget(widgetId:Number, openWidgetIfNot:Boolean = false):IBaseWidget
Gets the widget by the widget ID. Returns the widget by ID if the widget has been loaded, or null if the widget has not been loaded. The openWidgetIfNot option indicates whether to open the widget if it is not already in the open state.
getAllLoadedWidgetIds
public function getAllLoadedWidgetIds():Array
Returns an array of the widget IDs that have already been loaded.
getNumWidgets
public function getNumWidgets():Number
Returns the total number of widgets.
getWidgetId
public function getWidgetId(widgetLabel:String):Number
Returns the widget ID for a specific widget based on the widget label.

2/15/2012