.. _geoext.wfs.grid: Creating a Grid View of WFS Features ==================================== GeoExt borrows most of its WFS support from OpenLayers. What it does provide though is the `GeoExt.data.FeatureStore `_, so showing feature attributes in a grid is a very easy task. If we just want to display features in a grid, we can use a `GeoExt.data.ProtocolProxy `_, so we don't even need an OpenLayers layer. Vector Features in a Table -------------------------- Let's start with some code that reads a WFS layer and displays the feature attributes in a table: .. _geoext.wfs.grid.grid: .. code-block:: html GeoExt WFS Editor .. rubric:: Tasks #. Open a text editor, paste the code from above into a new file and save it as :file:`wfs-editor.html` in the root of your workshop directory. #. After saving your changes, point your browser to @workshop_url@/wfs-editor.html. You should see a grid, populated with data. .. figure:: grid.png A table view of WFS features. Understanding the FeatureStore `````````````````````````````` Let's have a look at the FeatureStore definition: .. _geoext.wfs.grid.store: .. code-block:: javascript var store = new GeoExt.data.FeatureStore({ fields: [ {name: "LANAME", type: "string"}, {name: "CFCC", type: "string"}, {name: "LAND", type: "float"}, {name: "AREA", type: "int", defaultValue: 10000} ], proxy: new GeoExt.data.ProtocolProxy({ protocol: new OpenLayers.Protocol.WFS({ url: "/geoserver/wms", version: "1.1.0", featureType: "poly_landmarks", featureNS: "http://www.census.gov", srsName: "EPSG:4326" }) }), autoLoad: true }); Two things are important: the field definition, and some way to tell the store where to get its data from. The field definition is straight forward -- we just need to make sure that we use the corect name of the attributes, and assign an appropriate type. Not all fields of the layer need to be mapped here -- only those we want to use. For the "AREA" field we also set a default value, to make sure that we always display a number. There are many ways to tell a feature store where to find its data. When working with a map and a vector layer, it is enough to point it to that layer and it will synchronize itself with the layer. We will see how that works in the :ref:`next section `. For now, since we don't use a layer here, we use a ProtocolProxy. This is a wrapper for an `OpenLayers.Protocol `_ instance. A Closer Look at the Grid ````````````````````````` A grid needs at least a store and a column definition to work properly. Let's see how we have done this for our feature grid: .. code-block:: javascript var gridPanel = new Ext.grid.GridPanel({ title: "Feature Table - Manhattan (NY) landmarks", region: "center" viewConfig: {forceFit: true}, store: store, cm: new Ext.grid.ColumnModel({ defaults: { sortable: true }, columns: [ {header: "Name", dataIndex: "LANAME"}, {header: "CFCC", dataIndex: "CFCC"}, {header: "Land", dataIndex: "LAND", width: 10}, { xtype: "numbercolumn", header: "Area", dataIndex: "AREA", format: "1,000", align: "right" } ] }) }); We have discussed the :ref:`store ` already, so let's have a look at the definition of the ColumnModel: the columns are connected to fields of FeatureRecords using the ``dataIndex`` property. The numeric column ("Area") needs some extra attention: we want to ``align`` it to the right, and we can provide a number ``format`` property. This works exactly as the number formats in your favorite spreadsheet application. Next Steps ---------- Features in a grid are somewhat boring. We want to add a geospatial component to our application and give it a map. The :ref:`next section ` explains how to do that.