16. GPS Capturing

Let's look at further requirements for our punch List app:

App Design: Construction Punch List

Construction sites can be big, so having GPS coordinates of exactly where the punch was captured will be useful for finding and fixing the punch later. We'll extend our app to capture the GPS coordinates of punch list items when they are added.

Add GPS Location to Data Model

The first step towards capturing GPS locations is to add a new attribute to our Data Model to store the locations. Click on the Data Model Workspace of the Punch List app in OXIDE. Then, in the schema.xml inside of our item model, add another field by typing field and inserting the auto-complete suggestion, then populate the field as shown below. Note the type="location", which indicates that our new field will store a GPS location:

<model name="item" label="Item">
    <field name="comments" label="Comments" type="text" />
    <field name="photo" label="Photo" type="photo" />
    <field name="status" label="Status" type="single-choice">
        <option key="Open">Open</option>
        <option key="Closed">Closed</option>
    </field>
    <field name="gps_location" label="Gps Location" type="location" />
    
    <display>{status} - {comments}</display>
</model> 

Add GPS Component to View

Now head back to the Views Workspace of the Punch List app, and click on the Add New view. Then, add a GPS coordinates capturing component to the add_new.view.xml by typing coordinates and inserting the auto-complete suggestion, and then fill it in as follows, binding it to the gps_location field that we've just defined in our Data Model:

<?xml version="1.0" encoding="UTF-8"?>
<view title="Add New Punch List Item">
    <!-- Parameters go here: -->

    <!-- Variables go here: -->
    <var name="item" type="item" />

    <!-- Components go here: -->

    <columns>
        <column>
            <capture-photo bind="item.photo" required="true" />
        </column>
        <column>
            <text-input bind="item.comments" required="true" />
            <button label="Save Item" on-press="saveItem" validate="true" style="solid" />
        </column>
    </columns>
    <capture-coordinates bind="item.gps_location" />
</view>

Test on Device

Refresh your mobile app — you should see a map like below. It might take a while to load the map tiles. A blue circle with a dot will appear when a GPS fix is achieved. The circle indicates the accuracy. Normally, we recommend advising users to wait until the circle is at it's smallest to ensure that accurate GPS locations are captured, but it is also possible to validate the accuracy in JS by evaluating the horizontal_accuracy of the captured coordinates before allowing the user to navigate away. For more information please see the GPS Capturing reference.

Add a Timestamp

We also want to capture and store the date and time when the user created the punch item. To do this we first need to update the Data Model to allow us to store a datetime field on the item model, and then we need to capture the timestamp of when the user created the item.

So, this time, instead of going back to the Data Model workspace, we are going to add the new timestamp field to our item model on the fly from our Views workspace by using the Data Model Panel on the right of the screen. Open the Data Model Panel by clicking on it (click it again to close it), then right click on 'Item' and select 'Add data model field', then select the type as 'DateTime' and enter the label as 'Created At'.

This will add a new field to the item model, that should look like this.

<field name="created_at" label="Created At" type="datetime" />

Now let's populate it when the user creates the punch item. One option would be to allow the user to manually enter a date and time, but I would rather just capture the current system/device date and time when the user creates the new punch item. To do that, we just update our add_new.js file to capture the current date and time when the item is created in the init() function. Like this.

// This function is called when the app navigates to this view (using a link)
function init() {
    // initialize any data here that should be available when the view is shown
    view.item = DB.item.create();
    view.item.status = "Open";
    view.item.created_at = new Date();
}

Next up we are going to further augment the data we capture with every punch item by adding some relationships.

So head over to Section 17 of the tutorial: Relationships

Last updated