More on ESRI Flex and Config.xml
More often than not, when building a Flex application that includes a URL that references a map service, you’ll have to swap out that URL from your development environment to production when you go live. The following script/technique is intended to alleviate having to completely rebuild your application during deployment.
Take a look at the following mxml file and note that there are 3 things in particular to note.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | < ?xml version="1.0" encoding="utf-8"?> <mx :Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:esri="http://www.esri.com/2008/ags" layout="absolute" initialize="init()" styleName="plain" > </mx><mx :Script> < ![CDATA[ import mx.collections.XMLListCollection; import mx.collections.ArrayCollection; import com.esri.ags.Graphic; import com.esri.ags.events.MapMouseEvent; import com.esri.ags.geometry.MapPoint; import com.esri.ags.geometry.Extent; import com.esri.ags.events.ExtentEvent; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.controls.Alert; import flash.external.*; import mx.events.FlexEvent; import com.esri.ags.layers.TiledMapServiceLayer; import mx.controls.Button; import mx.controls.Text; import com.esri.ags.layers.ArcGISDynamicMapServiceLayer; import mx.rpc.http.HTTPService; private function initXML():void { var configService:HTTPService = new HTTPService(); configService.url = "config.xml"; configService.resultFormat = "e4x"; configService.addEventListener(ResultEvent.RESULT, configResult); configService.addEventListener(FaultEvent.FAULT, configFault); configService.send(); } private function configResult(event:ResultEvent):void { var configXML:XML = event.result as XML; var serviceList:XMLList = configXML..service; for (var i:int = 0; i < serviceList.length(); i++) { var serviceName:String = serviceList[i].name; var serviceURL:String = serviceList[i].url; var serviceAlpha:int = serviceList[i].alpha; var serviceVisible:Boolean = serviceList[i].visible; var serviceLayers:ArrayCollection = new ArrayCollection(serviceList[i].layers.split(",")); var tLayer:ArcGISDynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(serviceURL); tLayer.id = serviceName; tLayer.visible = serviceVisible; tLayer.alpha = serviceAlpha; tLayer.visibleLayers = serviceLayers; myMap.addLayer(tLayer); } } private function configFault(event:FaultEvent):void { Alert.show(event.fault.faultString); } private function layerShowHandler(event:FlexEvent):void { // update the LODs/zoomslider to use/show the levels for the selected base map var tiledLayer:TiledMapServiceLayer = event.target as TiledMapServiceLayer; myMap.lods = tiledLayer.tileInfo.lods; } //add a callback for js to flex communication public function init():void { initXML(); if (flash.external.ExternalInterface.available) flash.external.ExternalInterface.addCallback("changeExtent", changeExtent); } //call from js public function changeExtent(sextent:String):void { //var avals = sextent.split("|"); //var ext:Extent = new Extent(new Number(avals[0]),new Number(avals[2]),new Number(avals[1]),new Number(avals[3])); //ext.spatialReference = myMap.spatialReference; //myMap.extent = ext; } public function onBasemapCreationComplete():void { myMap.addEventListener(MouseEvent.CLICK, pushExtentEvent); } //send extents to html/js public function pushExtentEvent(event:MouseEvent):void { if (flash.external.ExternalInterface.available) { const mapPoint:MapPoint = myMap.toMapFromStage(event.stageX, event.stageY); var extent:Array = new Array(); flash.external.ExternalInterface.call("displayExtent", mapPoint.y.toFixed(6), mapPoint.x.toFixed(6)); } } private function onMapClick(event:MapMouseEvent):void { myMap.infoWindow.label = "Event Location "; myMap.infoWindow.show(event.mapPoint); } ]]> </mx> <esri :Map id="myMap" width="100%" height="100%" mapClick="onMapClick(event)" > </esri><esri :extent> </esri><esri :Extent xmin="-122.2" ymin="24.89" xmax="-70.59" ymax="46.92" > <esri :SpatialReference wkid="4326"/> </esri> <esri :ArcGISTiledMapServiceLayer visible="{bb.selectedIndex == 0}" show="layerShowHandler(event)" url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" creationComplete="onBasemapCreationComplete()" /> <esri :ArcGISTiledMapServiceLayer visible="{bb.selectedIndex == 1}" show="layerShowHandler(event)" url="http://server.arcgisonline.com/ArcGIS/rest/services/NGS_Topo_US_2D/MapServer" creationComplete="onBasemapCreationComplete()"/> <esri :ArcGISTiledMapServiceLayer visible="{bb.selectedIndex == 2}" show="layerShowHandler(event)" url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer" creationComplete="onBasemapCreationComplete()" /> <mx :ToggleButtonBar id="bb" horizontalGap="2" selectedIndex="0" themeColor="0x00FF00" right="5" top="5"> </mx><mx :dataProvider> </mx><mx :Array> </mx><mx :String>Streets</mx> <mx :String>Topo</mx> <mx :String>Imagery</mx> |
First, note the code block that references an external XML file (config.xml). It really doesn’t get any easier than this. What’s really cool about this XML file is that basically, all the web service configuration options from the ArcGIS Service are configured through here. You can traverse through the config.xml file by referencing the node you want in the XMLList or serviceList:XMLList.
var serviceName:String = serviceList[i].name;
var serviceURL:String = serviceList[i].url;
var serviceAlpha:int = serviceList[i].alpha;
var serviceVisible:Boolean = serviceList[i].visible;
var serviceLayers:ArrayCollection = new ArrayCollection(serviceList[i].layers.split(“,”));
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | private function initXML():void { var configService:HTTPService = new HTTPService(); configService.url = "config.xml"; configService.resultFormat = "e4x"; configService.addEventListener(ResultEvent.RESULT, configResult); configService.addEventListener(FaultEvent.FAULT, configFault); configService.send(); } private function configResult(event:ResultEvent):void { var configXML:XML = event.result as XML; var serviceList:XMLList = configXML..service; for (var i:int = 0; i < serviceList.length(); i++) { var serviceName:String = serviceList[i].name; var serviceURL:String = serviceList[i].url; var serviceAlpha:int = serviceList[i].alpha; var serviceVisible:Boolean = serviceList[i].visible; var serviceLayers:ArrayCollection = new ArrayCollection(serviceList[i].layers.split(",")); var tLayer:ArcGISDynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(serviceURL); tLayer.id = serviceName; tLayer.visible = serviceVisible; tLayer.alpha = serviceAlpha; tLayer.visibleLayers = serviceLayers; myMap.addLayer(tLayer); } } private function configFault(event:FaultEvent):void { Alert.show(event.fault.faultString); } |
The XML is below: Note the configuration options that you would normally have to set in your compiled code. I just included the service name, url, alpha and visibility in this demonstration. There are many more options to choose from…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | < ?xml version="1.0"?> <configuration> <service> <name> Service Name </name> <url> http://yoururl.com/yourserver/rest/services/BaseMap/MapServer/ </url> <alpha> 1.0 </alpha> <visible> true </visible> <layers> 0,1 </layers> </service> </configuration> |
The next thing to take a look at is the fact that there is an Event that grabs the Latitude and Longitude from your map when it's clicked on (MouseEvent.CLICK). Moreover, it passes them to an HTML Input text box in the host page through an ExternalInterface call. The corresponding javascript should resemble the following. Note the < %= this.latitude.ClientID %> and < %= this.longitude.ClientID %> as they are required if you are embedding this in a ASP.NET for C# application.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <script language="JavaScript" type="text/javascript">
//call flex function changeExtent
function mapextentchange(value)
{
if(value != ''){
getFlexApp('FlexMaps').changeExtent(value);
}
}
//called from flex
function displayExtent(latitude,longitude)
{
document.getElementById("< %= this.latitude.ClientID %>").value = latitude;
document.getElementById("< %= this.longitude.ClientID %>").value = longitude;
}
</script> |
Finally, I snagged an example off of the ESRI Flex Community page that allowed me to toggle between Streetmap, Topographic Maps and Imagery data. As the selected Index changes, the base map changes...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <esri :ArcGISTiledMapServiceLayer visible="{bb.selectedIndex == 0}" show="layerShowHandler(event)" url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" creationComplete="onBasemapCreationComplete()" /> <esri :ArcGISTiledMapServiceLayer visible="{bb.selectedIndex == 1}" show="layerShowHandler(event)" url="http://server.arcgisonline.com/ArcGIS/rest/services/NGS_Topo_US_2D/MapServer" creationComplete="onBasemapCreationComplete()"/> <esri :ArcGISTiledMapServiceLayer visible="{bb.selectedIndex == 2}" show="layerShowHandler(event)" url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer" creationComplete="onBasemapCreationComplete()" /> <mx :ToggleButtonBar id="bb" horizontalGap="2" selectedIndex="0" themeColor="0x00FF00" right="5" top="5"> </mx><mx :dataProvider> </mx><mx :Array> </mx><mx :String>Streets</mx> <mx :String>Topo</mx> <mx :String>Imagery</mx> |
So, I've had fun playing with this an I've actually been able to use the entire script in a project I was a part of. I hope that someone else gets as much use out of it as I did.
More from Adam Estrada
- Customizing config.xml in the ESRI FlexViewer
- ESRI Flex API without ESRI
- jQuery tabs view state
- C# and GMapEZ
- ESRI FlexViewer and Error 1065