Tutorial 41: How to use the Map Component

This tutorial describes how to use the map component in a Formspider application. It covers following topics;

  • how to add a map component into a panel
  • how to add a marker to the map
  • how to remove marker(s) from the map

Formspider Map Component

Formspider map component is based on the Google Maps infrastructure. It allows the user to display markers, add new markers and remove them. The attributes of a map marker are listed below:

Attribute Definition
id Unique identifier of the marker. Formspider automatically generates and returns this value when a new marker is added
latitude Decimal value representing the latitude coordinate of the marker
longitude Decimal value representing the longitude coordinate of the marker

For instance, the Formspider map is not a data-driven component, it only displays the markers that are created at runtime. The attributes of the map component are listed below:

Attribute Definition
name Name of the map component which is used in Formspider API calls
latitude Decimal value representing the latitude coordinate of the map’s main area which is shown when the map is initially displayed
longitude decimal value representing the longitude coordinate of the main area which is shown when the map is initially displayed
zoom Integer value representing initial map zoom level. Valid values are between the range 0 and 21, inclusive. If not specified, 9 is used as the default value

You may click here to run the completed application.

Open Formspider IDE and click “New Application” under the “File” menu, the “New Application” dialog shows up. Enter “map” as the name of the application and “HR” as datasource schema name.  If you are using Formspider Online, you do not need to enter database schema name since your account is already configured to use your online database. Leave other fields empty and click “OK”. This creates the “map” application with a default mainframe (called “mainFrame”) and a default panel (called “mainPanel”).

In this tutorial, you will keep the data belonging to the markers which are added to the map component at runtime in a Formspider datasource. In this way, you will be aware of all the markers which are currently displaying on the map.

Creating a Datasource Holding Markers Data

Create a new datasource definition holding markers data. To achieve this, expand the “Datasource Definitions” accordion, select the “Datasource Definitions” node and click the “+” button. Alternatively, you may right click the “Datasource Definitions” node and select “New” from the pop up menu. The “New Datasource Definition” dialog shows up. Select the “Query” radio button from the “Based On” section and enter “markerList” as “Name” of the datasource definition.

Creating “markerList” datasource definition

Select “Query” node in the navigation tree on the left. Enter the following SQL Statement:

select -1 as markerID, -1 as longitude, -1 as latitude
from dual
where 1 = 2

Entering Query for “markerList” datasource definition

Click “OK” to save and close the “New Datasource Definition” dialog. This creates the “markerList” datasource definition and the “markerList1″ datasource.

Adding a Marker

Expand the “Panels” node from the “Containers” tree and double click the “mainPanel” to open it in the editor. Add a map component named “map” with 46.042736 as latitude, 14.765625 as longitude and 5 as zoom values. Add three textFields named “tf_latitude”, “tf_longitude” and “tf_zoom” and a button labeled “Put Marker”. Finally add a grid and bind the “markerList1” datasource to this grid to display all the markers that are currently displaying on the map. “mainPanel” XML should look like the following;

<panel>
  <tableLayout cellSpacing="10">
    <!-- Dummy row to adjust column widths -->
    <row height="0">
      <cell width="60"/>
      <cell width="105"/>
      <cell width="105"/>
      <cell/>
    </row>
    <row height="20">
      <cell>
        <textLabel label="Latitude:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_latitude" domain="DefaultNumber"/>
      </cell>
      <cell rowSpan="7" hAlign="Full" vAlign="Full">
        <map name="map" latitude="46.042736" longitude="14.765625" zoom="5"/>
      </cell>
    </row>
    <row height="20">
      <cell hAlign="Full">
        <textLabel label="Longitude:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_longitude" domain="DefaultNumber"/>
      </cell>
    </row>
    <row height="20">
      <cell hAlign="Full">
        <textLabel label="Zoom:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_zoom" domain="DefaultNumber"/>
      </cell>
    </row>
    <row height="20">
      <cell/>
      <cell hAlign="Full"/>
      <cell hAlign="Full">
        <button label="Put Marker"/>
      </cell>
    </row>
    <row height="100"/>
    <row heightPolicy="Dynamic">
      <cell columnSpan="3" hAlign="Full">
        <textLabel font-style="Bold" font-size="14" label="List of Markers"/>
      </cell>
    </row>
    <row>
      <cell columnSpan="3" hAlign="Full" vAlign="Full">
        <grid dataSource="markerList1">
          <column headerLabel="Latitude">
            <textLabel column="LATITUDE"/>
          </column>
          <column headerLabel="Longitude">
            <textLabel column="LONGITUDE"/>
          </column>
        </grid>
      </cell>
    </row>
  </tableLayout>
</panel>

Expand the “Windows” node and then the “Mainframe” node from the “Containers” tree. Double click to the “mainFrame” node to open it on the editor and set the value of the maximizeOnStartUp attribute to “Y”:

<mainframe title="map" width="500" height="500" maximizeOnStartUp="Y">
  <borderLayout>
    <cell docking="Center">
      <include panelName="mainPanel"/>
    </cell>
  </borderLayout>
</mainframe>

When “Put Marker” button is pressed you will add a new marker to the map using latitude, longitude and zoom values provided through “tf_latitude”, “tf_longitude” and “tf_zoom” textFields. To achieve this, create a Formspider action which will be fired when “Put Marker” button is pressed.

In your datasource schema, create a package called  “map_pkg” and open your newly created “map_pkg” package in your favorite PL/SQL Editor. Add a procedure named “addMarker” and ensure that the procedure is exposed in the package specification.

procedure addMarker is
  v_marker_id     number;
  v_latitude_nr   number;
  v_longitude_nr  number;
  v_zoom_nr       number;
  v_row_id        number;
begin
  -- retrieve marker parameters
  v_latitude_nr  := api_component.getvaluenr('mainPanel.tf_latitude');
  v_longitude_nr := api_component.getvaluenr('mainPanel.tf_longitude');
  v_zoom_nr      := api_component.getvaluenr('mainPanel.tf_zoom');

  -- add the marker to the map
  v_marker_id    := api_map.addmarker('mainPanel.map',v_latitude_nr,v_longitude_nr,v_zoom_nr);

  -- add the marker to the grid
  v_row_id := api_datasource.createrow('markerList1');
  api_datasource.setcolumnvalue('markerList1.markerID', v_marker_id,   v_row_id);
  api_datasource.setcolumnvalue('markerList1.latitude', v_latitude_nr, v_row_id);
  api_datasource.setcolumnvalue('markerList1.longitude',v_longitude_nr,v_row_id);
end;

This procedure uses api_component.getValueNR API to retrieve the values entered in “Latitude”, “Longitude” and “Zoom” textFields and uses api_map.addMarker API to add a new marker to the map with the specified latitude and longitude values. Note that api_map.addMarker API generates and returns an id value for the newly added marker.

When a new marker is added, Formspider automatically centers the map following the new marker’s coordinates. Note that the “Zoom” value used in api_map.addMarker API indicates the new zoom level of the map, if it’s null, the map keeps its current zoom level.

After adding the new marker to the map, this procedure creates a new row in “markerList1” datasource and inserts the marker’s id, latitude and longitude values.

In Formspider IDE expand the “Actions” accordion, select the “Actions” node, click the “+” button to create a new action. Alternatively you may right click the “Actions” node and select “New” from the pop-up menu. The “New Action” dialog shows up. Enter “addMarker” as the action name and “map_pkg.addMarker” as the procedure. Click “OK” to save your “action”.

Creating “addMarker” action

Open the “mainPanel” in the editor. Add a buttonPress event to the “Put Marker” button triggering the “addMarker” action, the panel XML should look like;

<panel>
  <tableLayout cellSpacing="10">
    <!-- Dummy row to adjust column widths -->
    <row height="0">
      <cell width="60"/>
      <cell width="105"/>
      <cell width="105"/>
      <cell/>
    </row>
    <row height="20">
      <cell>
        <textLabel label="Latitude:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_latitude" domain="DefaultNumber"/>
      </cell>
      <cell rowSpan="7" hAlign="Full" vAlign="Full">
        <map name="map" latitude="46.042736" longitude="14.765625" zoom="5"/>
      </cell>
    </row>
    <row height="20">
      <cell hAlign="Full">
        <textLabel label="Longitude:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_longitude" domain="DefaultNumber"/>
      </cell>
    </row>
    <row height="20">
      <cell hAlign="Full">
        <textLabel label="Zoom:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_zoom" domain="DefaultNumber"/>
      </cell>
    </row>
    <row height="20">
      <cell/>
      <cell hAlign="Full"/>
      <cell hAlign="Full">
        <button label="Put Marker">
          <events>
            <buttonPress action="addMarker"/>
          </events>
        </button>
      </cell>
    </row>
    <row height="100"/>
    <row heightPolicy="Dynamic">
      <cell columnSpan="3" hAlign="Full">
        <textLabel font-style="Bold" font-size="14" label="List of Markers"/>
      </cell>
    </row>
    <row>
      <cell columnSpan="3" hAlign="Full" vAlign="Full">
        <grid dataSource="markerList1">
          <column headerLabel="Latitude">
            <textLabel column="LATITUDE"/>
          </column>
          <column headerLabel="Longitude">
            <textLabel column="LONGITUDE"/>
          </column>
        </grid>
      </cell>
    </row>
  </tableLayout>
</panel>

Press “Run on Web” button to run the application. Enter 36.116203 as “Latitude”, -119.681563 as “Longitude” and press “Put Marker” button, note that a new marker is added on California and the map is automatically centered to display the marker. Also, note that the zoom level of the map remains same and a new row holding marker data is added to the “List of Markers” grid.

Map is centered following added marker's coordinates

Enter 52.373056 as “Latitude”, 4.892222 as “Longitude” and 15 as “Zoom”. Press “Put Marker” button again, note that this time, when the marker is added on Amsterdam, the zoom level of the map changes.

Zoom level is changed while adding a new marker

Removing a Marker

Open the “mainPanel” in the editor. Add a button to the “List of Markers” grid, the panel XML should look like;

<panel>
  <tableLayout cellSpacing="10">
    <!-- Dummy row to adjust column widths -->
    <row height="0">
      <cell width="60"/>
      <cell width="105"/>
      <cell width="105"/>
      <cell/>
    </row>
    <row height="20">
      <cell>
        <textLabel label="Latitude:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_latitude" domain="DefaultNumber"/>
      </cell>
      <cell rowSpan="7" hAlign="Full" vAlign="Full">
        <map name="map" latitude="46.042736" longitude="14.765625" zoom="5"/>
      </cell>
    </row>
    <row height="20">
      <cell hAlign="Full">
        <textLabel label="Longitude:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_longitude" domain="DefaultNumber"/>
      </cell>
    </row>
    <row height="20">
      <cell hAlign="Full">
        <textLabel label="Zoom:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_zoom" domain="DefaultNumber"/>
      </cell>
    </row>
    <row height="20">
      <cell/>
      <cell hAlign="Full"/>
      <cell hAlign="Full">
        <button label="Put Marker">
          <events>
            <buttonPress action="addMarker"/>
          </events>
        </button>
      </cell>
    </row>
    <row height="100"/>
    <row heightPolicy="Dynamic">
      <cell columnSpan="3" hAlign="Full">
        <textLabel font-style="Bold" font-size="14" label="List of Markers"/>
      </cell>
    </row>
    <row>
      <cell columnSpan="3" hAlign="Full" vAlign="Full">
        <grid dataSource="markerList1">
          <column headerLabel="Latitude">
            <textLabel column="LATITUDE"/>
          </column>
          <column headerLabel="Longitude">
            <textLabel column="LONGITUDE"/>
          </column>
          <column width="25">
            <button tooltip="Remove Marker" icon="/icons/mainframe/delete.png"/>
          </column>
        </grid>
      </cell>
    </row>
  </tableLayout>
</panel>

When this button is pressed, you will remove the corresponding marker using the marker id value generated when it’s being added. Open “map_pkg” package and create a procedure named “removeMarker” which is fired when “Remove Marker” button is pressed;

procedure removeMarker is
  v_marker_id     number;
begin
  v_marker_id := api_datasource.getcolumnvalueNR('markerList1.markerID');
  -- remove the marker from the map
  api_map.removemarker('mainPanel.map', v_marker_id);

  -- remove the marker from the grid
  api_datasource.deleterow('markerList1');
end;

Note that this procedure retrieves the marker id from the currently selected row of the “markerList1” datasource and removes the marker from the map using api_map.removeMarker API. Then, it removes the datasource row belonging to this marker.

Create a new action, enter “removeMarker” as the action name and “map_pkg.removeMarker” as the procedure. Click “OK” to save your action. Open the “mainPanel” and add a buttonPress event to “Remove Marker” button, triggering “removeMarker” action.

<panel>
  <tableLayout cellSpacing="10">
    <!-- Dummy row to adjust column widths -->
    <row height="0">
      <cell width="60"/>
      <cell width="105"/>
      <cell width="105"/>
      <cell/>
    </row>
    <row height="20">
      <cell>
        <textLabel label="Latitude:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_latitude" domain="DefaultNumber"/>
      </cell>
      <cell rowSpan="7" hAlign="Full" vAlign="Full">
        <map name="map" latitude="46.042736" longitude="14.765625" zoom="5"/>
      </cell>
    </row>
    <row height="20">
      <cell hAlign="Full">
        <textLabel label="Longitude:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_longitude" domain="DefaultNumber"/>
      </cell>
    </row>
    <row height="20">
      <cell hAlign="Full">
        <textLabel label="Zoom:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_zoom" domain="DefaultNumber"/>
      </cell>
    </row>
    <row height="20">
      <cell/>
      <cell hAlign="Full"/>
      <cell hAlign="Full">
        <button label="Put Marker">
          <events>
            <buttonPress action="addMarker"/>
          </events>
        </button>
      </cell>
    </row>
    <row height="100"/>
    <row heightPolicy="Dynamic">
      <cell columnSpan="3" hAlign="Full">
        <textLabel font-style="Bold" font-size="14" label="List of Markers"/>
      </cell>
    </row>
    <row>
      <cell columnSpan="3" hAlign="Full" vAlign="Full">
        <grid dataSource="markerList1">
          <column headerLabel="Latitude">
            <textLabel column="LATITUDE"/>
          </column>
          <column headerLabel="Longitude">
            <textLabel column="LONGITUDE"/>
          </column>
          <column width="25">
            <button tooltip="Remove Marker" icon="/icons/mainframe/delete.png">
              <events>
                <buttonPress action="removeMarker"/>
              </events>
            </button>
          </column>
        </grid>
      </cell>
    </row>
  </tableLayout>
</panel>

Run the application again. Add a marker on Amsterdam by entering 52.373056 as “Latitude” and 4.892222 as “Longitude” and another marker on Prague by entering 50.083333 as “Latitude” and 14.416667 as “Longitude”. Press “Remove Marker” button existing in the first row of the grid, note that the marker on Amsterdam is removed from the map and the corresponding datasource row is deleted.

The marker on Amsterdam is removed

Removing All Markers

Open the “mainPanel” in the editor. Add a button labeled “Remove All Markers” next to the “Put Marker” button, the panel XML should look like;

<panel>
  <tableLayout cellSpacing="10">
    <!-- Dummy row to adjust column widths -->
    <row height="0">
      <cell width="60"/>
      <cell width="105"/>
      <cell width="105"/>
      <cell/>
    </row>
    <row height="20">
      <cell>
        <textLabel label="Latitude:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_latitude" domain="DefaultNumber"/>
      </cell>
      <cell rowSpan="7" hAlign="Full" vAlign="Full">
        <map name="map" latitude="46.042736" longitude="14.765625" zoom="5"/>
      </cell>
    </row>
    <row height="20">
      <cell hAlign="Full">
        <textLabel label="Longitude:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_longitude" domain="DefaultNumber"/>
      </cell>
    </row>
    <row height="20">
      <cell hAlign="Full">
        <textLabel label="Zoom:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_zoom" domain="DefaultNumber"/>
      </cell>
    </row>
    <row height="20">
      <cell/>
      <cell hAlign="Full">
        <button label="Remove All Markers"/>
      </cell>
      <cell hAlign="Full">
        <button label="Put Marker">
          <events>
            <buttonPress action="addMarker"/>
          </events>
        </button>
      </cell>
    </row>
    <row height="100"/>
    <row heightPolicy="Dynamic">
      <cell columnSpan="3" hAlign="Full">
        <textLabel font-style="Bold" font-size="14" label="List of Markers"/>
      </cell>
    </row>
    <row>
      <cell columnSpan="3" hAlign="Full" vAlign="Full">
        <grid dataSource="markerList1">
          <column headerLabel="Latitude">
            <textLabel column="LATITUDE"/>
          </column>
          <column headerLabel="Longitude">
            <textLabel column="LONGITUDE"/>
          </column>
          <column width="25">
            <button tooltip="Remove Marker" icon="/icons/mainframe/delete.png">
              <events>
                <buttonPress action="removeMarker"/>
              </events>
            </button>
          </column>
        </grid>
      </cell>
    </row>
  </tableLayout>
</panel>

When “Remove All Markers” button is pressed, you will remove all markers existing on the map using api_map.removeMarkers API and delete all rows existing in “List of Markers” grid. Open “map_pkg” package and create a procedure named “removeAllMarkers” as;

procedure removeAllMarkers is
begin
  -- remove all markers from the map
  api_map.removemarkers('mainPanel.map');

  -- remove all markers from the grid
  api_datasource.deleterow('markerList1', api_datasource.ALL_ROWS);
end;

Create a new action, enter “removeAllMarkers” as the action name and “map_pkg.removeAllMarkers” as the procedure. Click “OK” to save your action. Open the “mainPanel” and add a buttonPress event to “Remove All Markers” button triggering the “removeAllMarkers” action:

<panel>
  <tableLayout cellSpacing="10">
    <!-- Dummy row to adjust column widths -->
    <row height="0">
      <cell width="60"/>
      <cell width="105"/>
      <cell width="105"/>
      <cell/>
    </row>
    <row height="20">
      <cell>
        <textLabel label="Latitude:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_latitude" domain="DefaultNumber"/>
      </cell>
      <cell rowSpan="7" hAlign="Full" vAlign="Full">
        <map name="map" latitude="46.042736" longitude="14.765625" zoom="5"/>
      </cell>
    </row>
    <row height="20">
      <cell hAlign="Full">
        <textLabel label="Longitude:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_longitude" domain="DefaultNumber"/>
      </cell>
    </row>
    <row height="20">
      <cell hAlign="Full">
        <textLabel label="Zoom:"/>
      </cell>
      <cell columnSpan="2" hAlign="Full" vAlign="Full">
        <textField name="tf_zoom" domain="DefaultNumber"/>
      </cell>
    </row>
    <row height="20">
      <cell/>
      <cell hAlign="Full">
        <button label="Remove All Markers">
          <events>
            <buttonPress action="removeAllMarkers"/>
          </events>
        </button>
      </cell>
      <cell hAlign="Full">
        <button label="Put Marker">
          <events>
            <buttonPress action="addMarker"/>
          </events>
        </button>
      </cell>
    </row>
    <row height="100"/>
    <row heightPolicy="Dynamic">
      <cell columnSpan="3" hAlign="Full">
        <textLabel font-style="Bold" font-size="14" label="List of Markers"/>
      </cell>
    </row>
    <row>
      <cell columnSpan="3" hAlign="Full" vAlign="Full">
        <grid dataSource="markerList1">
          <column headerLabel="Latitude">
            <textLabel column="LATITUDE"/>
          </column>
          <column headerLabel="Longitude">
            <textLabel column="LONGITUDE"/>
          </column>
          <column width="25">
            <button tooltip="Remove Marker" icon="/icons/mainframe/delete.png">
              <events>
                <buttonPress action="removeMarker"/>
              </events>
            </button>
          </column>
        </grid>
      </cell>
    </row>
  </tableLayout>
</panel>

Run the application, add two markers and press “Remove All Markers” button. Note that when this button is pressed, all markers existing on the map are removed and all grid rows are deleted.

You may click here to run the application.

All markers are removed

  • XY

    Is there any possibility to use a different graphic for the marker?
    Suppose there are different class objects that need to be represented in a different symbol on the same map.

    • http://www.gerger.co Yalim K. Gerger

      Not right now. But it sure can be done.