.. _geoext.wfs.editing: Editing Features and Their Attributes ===================================== We will now enhance our application by making the layer and its attributes editable, and using WFS-T to commit changes. Making Layer and Grid Editable ------------------------------ Let's modify our application to allow for editing feature geometries and attributes. On the layer side this requires replacing the SelectFeature control that the FeatureSelectionModel automatically creates with a ModifyFeature control. On the grid side, we have to replace the GridPanel with an EditorGridPanel, provide editors for the columns, and reconfigure the FeatureSelectionModel a bit. .. rubric:: Tasks #. Open :file:`wfs-editor.html` in your text editor. Add a ModifyFeature control to the map and activate it. To do so, find the mapPanel definition, and add the following code just below: .. code-block:: javascript var modifyControl = new OpenLayers.Control.ModifyFeature(layer); mapPanel.map.addControl(modifyControl); modifyControl.activate(); #. Reconfigure the FeatureSelectionModel to use the internal SelectFeature control of the modifyControl, and enable ``singleSelect`` (meaning that only one feature can be selected at a time, which makes sense for editing). The FeatureSelectionModel instantiation should now look like this: .. code-block:: javascript sm: new GeoExt.grid.FeatureSelectionModel({ selectControl: modifyControl.selectControl, singleSelect: true }), #. Replace the GridPanel with an EditorGridPanel and configure editors for the columns: TextField by default, and NumberField for the "# of Facilities" column. This is how the whole gridPanel definition should look now: .. code-block:: javascript var gridPanel = new Ext.grid.EditorGridPanel({ title: "Feature Table - Manhattan (NY) landmarks", region: "center", viewConfig: {forceFit: true}, store: store, sm: new GeoExt.grid.FeatureSelectionModel({ selectControl: modifyControl.selectControl, singleSelect: true }), cm: new Ext.grid.ColumnModel({ defaults: { sortable: true, editor: {xtype: "textfield"} }, columns: [ {header: "Name", dataIndex: "LANAME"}, {header: "CFCC", dataIndex: "CFCC"}, {header: "Land", dataIndex: "LAND", width: 35}, { xtype: "numbercolumn", header: "Area", dataIndex: "AREA", format: "1,000", align: "right", editor: {xtype: "numberfield"} } ] }) }); Adding "Create" and "Delete" Buttons ------------------------------------ We are already able to modify existing features, but we also want to be able to add and remove features. To add features, we will use an `OpenLayers.Control.DrawFeature `_. Thanks to our FeatureStore, a feature added to the layer will automatically also show up in the grid. For deleting features, we add a button with a custom handler. .. rubric:: Tasks #. Create a DrawFeature control. To do so, add the following right above the mapPanel definition: .. code-block:: javascript var drawControl = new OpenLayers.Control.DrawFeature( layer, OpenLayers.Handler.Polygon, {handlerOptions: {multi: true}} ); Add the following below the mapPanel definition: .. code-block:: javascript mapPanel.map.addControl(drawControl); #. Add a bottom toolbar (``bbar``) property to the mapPanel definition. Now the mapPanel definition should look like this: .. code-block:: javascript var mapPanel = new GeoExt.MapPanel({ title: "Map", region: "west", width: 400, layers: [layer], extent: new OpenLayers.Bounds(-74.047, 40.68, -73.908, 40.882), bbar: [ new GeoExt.Action({ control: drawControl, text: "Create", enableToggle: true }), { text: "Delete", handler: function() { gridPanel.getSelectionModel().each(function(rec) { var feature = rec.get("feature"); modifyControl.unselectFeature(feature); store.remove(rec); }) } } ] }); #. Save your file. Open or refresh @workshop_url@/wfs-editor.html in your browser. Double-click in a grid cell to modify it. Click on a feature in the map and modify it by playing with the vertices. Remove a feature by hitting "Delete". Hit "Create" and draw a new feature. Scroll down to the bottom of the Feature Table and edit its attributes. Hit the "Create" button again to turn back to selection mode. .. figure:: editing.png Modified layer after heavy feature editing. A Closer Look ````````````` The "Create" button uses a `GeoExt.Action `_ to turn an OpenLayers control into a button. It is important to understand that any OpenLayers control can be added to a toolbar or menu by wrapping it into such an Action. .. code-block:: javascript new GeoExt.Action({ control: drawControl, text: "Create", enableToggle: true }), The "Delete" button is just a plain Ext.Button. When clicked, it performs the action defined in its handler. .. code-block:: javascript { text: "Delete", handler: function() { gridPanel.getSelectionModel().each(function(rec) { var feature = rec.get("feature"); modifyControl.unselectFeature(feature); store.remove(rec); }) } } The handler function uses the selection model's ``each`` method to walk through the selected records (which will either be none ore one in our case, with ``singleSelect`` set to true). Before removing the record, we use the modifyControl's ``unselectFeature`` method to remove the feature's editing vertices and unselect the feature, bringing the layer in a clean state. Next Steps ---------- It is nice to be able to create, modify and delete features, but finally we will need to save our changes. The :ref:`final section ` of this module will teach you how to use the WFS-T functionality of OpenLayers to commit changes to the server.