Editing Auto Populate Coordinate Field

2458
7
03-20-2012 08:45 PM
SchoppMatthieu
New Contributor III
Hi !

I need to create a button in the Editing Widget that will automatically populate the Coordinate for Editable Point Feature.

I don't thing this should be using a geoprocessing tool because I guess a geoprocessing tool would need a data schema that doesn't change (I can be wrong). I'd like to use this function for many different Point dataset that have different data schema.

I'm thinking more about something like this:

<Editing Widget>
.......
Function on Button Click(event:Event):void{

           If (Data is Point){
                 If (Data.Field[CoordX] && Data.Field[CoordY]){
                            For Each (Data){
                                     Data.Field[CoordX]=Data.x
                                     Data.Field[CoordY]=Data.y
                                }
                      }
           }
}

.....
</Editing Widget>

Did anyone has done that before ?
Can I have a bit of help please ?

Thank you,
Matt
Tags (2)
0 Kudos
7 Replies
IvanBespalov
Occasional Contributor III
Schopp,

try add to EditWidgetAttributeInspectorSkin.mxml highlighted code (Button and it's click handler):
<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (c) 2010 Esri

     All rights reserved under the copyright laws of the United States
     and applicable international laws, treaties, and conventions.

     You may freely redistribute and use this sample code, with or
     without modification, provided you include the original copyright
     notice and use restrictions.

     See use restrictions in use_restrictions.txt.
-->
<!---
     Custom skin class for the AttributeInspector component.
-->
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
             xmlns:mx="library://ns.adobe.com/flex/mx"
             xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Metadata>
        /**
         * A strongly typed property that references the component to which this skin is applied.
         */
        [HostComponent("com.esri.ags.components.AttributeInspector")]

        [Event(name="attachmentGroupClicked", type="flash.events.Event")]
        [Event(name="okButtonClicked", type="flash.events.Event")]
    </fx:Metadata>

 <fx:Script>
  <![CDATA[
   import com.esri.ags.Graphic;
   import com.esri.ags.components.AttributeInspector;
   
   import mx.controls.Alert;
   protected function onGetGeometryButtonClick(event:MouseEvent):void
   {
    var ai:AttributeInspector = hostComponent as AttributeInspector;
    if (ai != null)
    {
     var af:Graphic = ai.activeFeature;
     if (af != null && af.geometry != null)
     {
                                                // so the "af.geometry" is that you need
      Alert.show(af.geometry.toString()); 
     }
     else
     {
      Alert.show("AttributeInspector has no active features!");
     }
    }
    else
    {
     Alert.show("AttributeInspector is null!");
    }
   }
  ]]>
 </fx:Script>


    <fx:Script>
        <![CDATA[
   import com.esri.ags.layers.FeatureLayer;
   
   import mx.containers.FormItem;
   import mx.containers.FormItemDirection;
   import mx.events.ChildExistenceChangedEvent;

            // configurable through the edit widget's config file
            [Bindable]
            public static var showAttachmentsText:String;
            [Bindable]
            public static var deleteLabel:String;
            [Bindable]
            public static var okLabel:String;

            private function attachmentGroup_clickHandler(event:MouseEvent):void
            {
                dispatchEvent(new Event("attachmentGroupClicked", true, true));
            }

            protected function okButton_clickHandler(event:MouseEvent):void
            {
                dispatchEvent(new Event("okButtonClicked", true, true));
            }

   protected function form_childAddHandler(event:ChildExistenceChangedEvent):void
   {
    var displayObject:DisplayObject = event.relatedObject;
    if (displayObject != null && displayObject is FormItem)
    {
     var formItem:FormItem = displayObject as FormItem;
     var labelValue:String = formItem.label;
     formItem.label = "";
     
     var lbl:Label = new Label();
     lbl.text = labelValue;
     formItem.addChildAt(lbl, 0);
    }
   }

        ]]>
    </fx:Script>

    <s:states>
        <s:State name="normal"/>
        <s:State name="disabled"/>
        <s:State name="invalid"/>
    </s:states>

    <s:layout>
        <s:VerticalLayout horizontalAlign="center"/>
    </s:layout>

    <!--- Form to display the attributes of the active feature. -->
    <mx:Form id="form"
             width="100%" height="100%"
             enabled.disabled="false"
             horizontalScrollPolicy="off"
             maxHeight="{hostComponent.getStyle('formMaxHeight')}"
             verticalScrollPolicy="auto" childAdd="form_childAddHandler(event)">
    </mx:Form>

    <s:HGroup verticalAlign="middle">
        <!--- Button to delete the active feature. -->
        <s:Button id="deleteButton"
                  enabled.disabled="false"
                  label="{deleteLabel}"/>

        <s:Button id="okButton"
                  click="okButton_clickHandler(event)"
                  enabled.disabled="false"
                  label="{okLabel}"/>
  
 <s:Button label="Geometry?" click="onGetGeometryButtonClick(event)" />
    </s:HGroup>
    <s:HGroup id="attachmentGroup"
              width="100%" height="100%"
              horizontalAlign="right"
              includeInLayout="{FeatureLayer(hostComponent.activeFeature.graphicsLayer).layerDetails.hasAttachments}"
              verticalAlign="middle"
              visible="{FeatureLayer(hostComponent.activeFeature.graphicsLayer).layerDetails.hasAttachments}">
        <s:Label buttonMode="true"
                 click="attachmentGroup_clickHandler(event)"
                 fontWeight="bold"
                 text="{showAttachmentsText}"/>
        <mx:Image id="img"
                  width="25" height="25"
                  buttonMode="true"
                  click="attachmentGroup_clickHandler(event)"
                  source="@Embed('/assets/images/edit_attachments.png')"/>
    </s:HGroup>
</s:SparkSkin>
0 Kudos
SchoppMatthieu
New Contributor III
Hello,

I've made some progress but I'm stuck to the next step:

In the Editing Widget, the featureLayer_selectionComplete function is called by a FeatureLayerEvent:

I just integrate my function in there:

           private function featureLayer_selectionComplete(event:FeatureLayerEvent):void
            { 
       for each (var featureo:Graphic in event.features){
    
      for each (var fieldo:Field in event.target.layerDetails.fields){
     
      if (fieldo.name == "X_Coord" && fieldo.type == Field.TYPE_DOUBLE){
       
        if (featureo.geometry.type == "esriGeometryPoint"){

             var myPoint:MapPoint = new MapPoint;
         myPoint = featureo.geometry as MapPoint; 
          featureo.attributes[fieldo.name]=myPoint.x.toFixed(2).toString();
       
        }
                         }
     }
    }

This allow me to populate a X_Coord Field (type double) as soon as it exist.

When I click on the map, the X coordinate is automatically generated in the "X_Coord" textInput of the AttributeEditor infoWindow.

The problem is that the value is not "saved" by the Editor. I think that the editor "save" the value only on the textInput's changeEvent (triggered by the user) so the value added by the function is ignored.
A potential solution would be to replace the textInput's changeEvent (in the AttributeEditor infoWindow) by a valueCommitEvent (triggered by either the user or the system). However the source code for the Attribute Editor infoWindow is not accessible.


Does anyone have an idea about how I can force the Editor to save my values generated through a function ?

Thanks
Matt
0 Kudos
SchoppMatthieu
New Contributor III
Hahahaha !!!

I found out by myself, :cool:

thank you for not helping me... 😉


            private function featureLayer_selectionComplete(event:FeatureLayerEvent):void
            {
       
       for each (var featureo:Graphic in event.features){
    
    
    
      for each (var fieldo:Field in event.target.layerDetails.fields){


     
      if (fieldo.name == "X_Coord" && fieldo.type == Field.TYPE_DOUBLE){
       
        if (featureo.geometry.type == "esriGeometryPoint"){

            var myPoint:MapPoint = new MapPoint;
         myPoint = featureo.geometry as MapPoint;

         featureo.attributes[fieldo.name]=myPoint.x.toFixed(2);
        
         event.featureLayer.applyEdits(null, [featureo], null);
       
       }
      }
     }
    }  (..}..)


Cheers,
Matt
0 Kudos
DilsonKitoko
New Contributor III

Hello Matshopp,

Do you mind to share you code? I'm trying also to implement this function.

Regards,

Dilson

0 Kudos
Ahmad_TarmiziTalib
New Contributor
Thank you so much Matt. I was stuck on the same issue too. your post helped me solve the "point-click-update-latlong-coordinate" thing. however though i see another slight problem when the user moves the point. the coordinate wont save. as the coordinate save only "on click". unless of course if the user clicks on the point again after the "moves". is this problem apply to yours too?

here is my codes:
                        //-My changes start-//
   public static const LAT:String = "lat";
   public static const LON:String = "lon";
   public var longitude:String;
   public var latitude:String;
   import widgets.Coordinate.DegToDMS;
   import mx.formatters.NumberBaseRoundType;

   private function MapClicked(event:MouseEvent):void
   {
    var mapPoint:MapPoint = map.toMapFromStage(event.stageX, event.stageY);
    const latlong:MapPoint = WebMercatorUtil.webMercatorToGeographic(mapPoint) as MapPoint;
    longitude = DegToDMS.format(latlong.x,"lon");
    latitude = DegToDMS.format(latlong.y,"lat");
   }
   //-My changes end-//

            private function basewidget_widgetConfigLoaded(event:Event):void
            {
    numberFormatter.precision = parseFloat("6"); //-My changes-//
    map.addEventListener(MapMouseEvent.MAP_CLICK, MapClicked); //-My changes-//
                // hide map infowindow if any
                map.infoWindow.hide();

                if (configXML)
                {
                    if (GeometryServiceSingleton.instance.url) // using GeometryServiceSingleton
                    {
            ...
            ...
            ...
            }

            private function featureLayer_selectionComplete(event:FeatureLayerEvent):void
            {
                for each (var field:Field in event.target.layerDetails.fields)
                {
                    if (field.type == Field.TYPE_DATE)
                    {
                        for each (var feature:Graphic in event.features)
                        {
                            var date:Date = new Date(feature.attributes[field.name]);
                            if (date.milliseconds == 999)
                            {
                                date.milliseconds++; //Add 1ms to date values ending in 999 to workaround REST date bug
                                feature.attributes[field.name] = date.time;
                            }
                        }
                    }
     //-My changes start-//
     if (field.name == "Longitude")
     {
      //var feature:Graphic;
      feature.attributes[field.name] = longitude;
      event.featureLayer.applyEdits(null, [feature], null)
     }
     if (field.name == "Latitude")
     {
      //var feature:Graphic;
      feature.attributes[field.name] = latitude;
      event.featureLayer.applyEdits(null, [feature], null)
     }
     //-My changes end-//
                }
            }
0 Kudos
SchoppMatthieu
New Contributor III
Thank you for sharing Ahmad 🙂
0 Kudos
RhettZufelt
MVP Frequent Contributor
Thank you so much Matt. I was stuck on the same issue too. your post helped me solve the "point-click-update-latlong-coordinate" thing. however though i see another slight problem when the user moves the point. the coordinate wont save. as the coordinate save only "on click". unless of course if the user clicks on the point again after the "moves". is this problem apply to yours too? 

here is my codes: 
                        //-My changes start-//
   public static const LAT:String = "lat";
   public static const LON:String = "lon";
   public var longitude:String;
   public var latitude:String;
   import widgets.Coordinate.DegToDMS;
   import mx.formatters.NumberBaseRoundType;

   private function MapClicked(event:MouseEvent):void
   {
    var mapPoint:MapPoint = map.toMapFromStage(event.stageX, event.stageY);
    const latlong:MapPoint = WebMercatorUtil.webMercatorToGeographic(mapPoint) as MapPoint;
    longitude = DegToDMS.format(latlong.x,"lon");
    latitude = DegToDMS.format(latlong.y,"lat");
   }
   //-My changes end-//

            private function basewidget_widgetConfigLoaded(event:Event):void
            {
    numberFormatter.precision = parseFloat("6"); //-My changes-//
    map.addEventListener(MapMouseEvent.MAP_CLICK, MapClicked); //-My changes-//
    map.addEventListener(MouseEvent.MOUSE_MOVE, MapClicked);                // hide map infowindow if any
                map.infoWindow.hide();

......................


Don't see a MapMouseEvent.MOUSE_MOVE so maybe the regular MouseEvent.MOUSE_MOVE will work. Guess it can't hurt to try.

You may try this. No idea if it will work, but that is what it took to get my coordinatewidget modifications to update on mouse move. Don't know if it will actually give the xy of the "moved" point, or just the cursor location.

If not, maybe a MOUSE_UP event will capture the xy when you release it on move......

Just some thoughts,

R_
0 Kudos