---
title: "Relationships"
description: "Group issues by category and record who created them."
permalink: /docs/get-started/tutorial-build-your-first-app/advanced-topics/location-relationships-and-roles/relationships/
---
# Relationships

Organize issues into categories and record who created each one. Then add a view that browses issues by category.

## 1. Define the relationships

### 1.1. Add categories

In **Data Model**, add this model inside `<data-model>` in `schema.xml`:

```diff-xml
+<model name="category" label="Category">
+    <field name="name" label="Name" type="text" />
+    <has-many model="item" name="items" />
+    <display>{name}</display>
+</model>
```

Add the other side of the relationship to the `item` model, after its fields and before `<display>`:

```diff-xml
     <field name="gps_location" label="GPS Location" type="location" />
     <field name="created_at" label="Created At" type="datetime" />
+    <belongs-to model="category" />
     <display>{status} - {comments}</display>
```

A category **has many** items; each item **belongs to** a category. In code, `category.items` returns its related items, and `item.category()` gets the item's category.

### 1.2. Record the creator

Add a second relationship to `item`:

```diff-xml
     <belongs-to model="category" />
+    <belongs-to model="user" name="created_by" />
     <display>{status} - {comments}</display>
```

Add its inverse to the existing `user` model, before `<display>`:

```diff-xml
+<has-many model="item" name="items" />
```

The explicit name `created_by` distinguishes the creator relationship in code. Keep the existing fields and other models.

![Category and User relationships to Item in the OXIDE diagram](media/relationships-diagram.png){:.medium}

## 2. Create test categories

Deploy to Testing. Open **Browse Data**, select **Category**, and create records with names such as "Plumbing" and "Electrical".

<Gallery>
<GalleryItem caption={"Creating the Plumbing category in Browse Data"}>

![Creating the Plumbing category in Browse Data](media/create-category.png)

</GalleryItem>
<GalleryItem caption={"Plumbing and Electrical saved in the Testing database"}>

![Plumbing and Electrical saved in the Testing database](media/category-records.png)

</GalleryItem>
</Gallery>

## 3. Set relationships when adding an issue

In `add_new.view.xml`, add a query variable alongside `item`:

```diff-xml
     <var name="item" type="item" />
+    <var name="all_categories" type="query:category" />
```

Place a category selector above the comments input:

```diff-xml
+            <object-dropdown query="all_categories" bind="item.category" label="Category"
+                empty-message="No categories available" required="false" />
             <text-input bind="item.comments" required="true" />
```

Update `init()` in `add_new.js` to load the choices and set the creator:

```diff-javascript
 function init() {
+    view.all_categories = DB.category.all().orderBy("name");
     view.item = DB.item.create();
     view.item.status = "Open";
     view.item.created_at = new Date();
+    view.item.created_by(user);
 }
```

The dropdown sets `item.category`. `created_by(user)` assigns the current app user through the named relationship.


## 4. Display the category

In the main view's `<list-item>`, fill the empty content and footer:

```diff-xml
-<content></content>
-<footer></footer>
+<content>{category}</content>
+<footer>{created_at}</footer>
```

Add a category row to the detail view's `<info-table>`:

```diff-xml
                 <row label="Item Comments" bind="item.comments" />
                 <row label="Item Status" bind="item.status" />
+                <row label="Category" bind="item.category" />
                 <row label="Current Time" value="{$:showTime()}" />
```

Deploy and create an issue with a category. Check that the category appears in both screens and that the saved record's `created_by` relationship points to your app user. In **Browse Data**, assign categories to any older test issues you want to use below.

## 5. Browse issues by category

### 5.1. Add the view

Create a view named "browse_items" with the title "Browse Issues by Category". Add this button to the main view's `<button-group>`:

```diff-xml
+<button label="Browse by Category" on-press="$:navigate.link('browse_items')"
+    icon="fa-filter" validate="false" style="solid" />
```

Replace `browse_items.view.xml` with:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<view title="Browse Issues by Category">
    <!-- Parameters go here: -->

    <!-- Variables go here: -->
    <var name="all_categories" type="query:category" />
    <var name="selected_category" type="category" />
    <var name="filtered_items" type="query:item" />

    <!-- Components go here: -->
    <object-list on-change="filterCategories" hide-if="selected_category" query="all_categories" bind="selected_category" label="Please select a category to view related issues" empty-message="Your items will appear here" required="false" />

    <heading show-if="selected_category">{selected_category.name}: Issues</heading>
    <list show-if="selected_category" empty-message="Your items will appear here">
        <list-item query="filtered_items">
            <header>{comments}</header>
            <content>{category}</content>
            <footer>{created_at}</footer>
            <accent label="{status}" color="info" />
            <asset src="{photo}" />
            <action on-press="$:selectItem($selection)" />
        </list-item>
    </list>

    <button-group>
        <button label="Back" on-press="dismiss" icon="fa-arrow-left" validate="false" style="outline" />
        <button show-if="selected_category" label="Clear Selection" on-press="clearSelection" icon="fa-times" validate="false" style="solid" />
    </button-group>
</view>
```

`hide-if` hides the category selector after a selection. `show-if` reveals the related issues and the **Clear Selection** button. The selector's `on-change` handler updates the query whenever the category changes.

### 5.2. Load the related issues

In `browse_items.js`, replace `init()` and add the other handlers below. The **Back** button calls the built-in `dismiss` action.

```javascript
function init() {
    view.all_categories = DB.category.all().orderBy("name");
}

function filterCategories(selectedCategory) {
    if (selectedCategory) {
        view.filtered_items = selectedCategory.items;
    }
}

function clearSelection() {
    view.selected_category = null;
}

function selectItem(selectedItem) {
    var userOptions = ["View Item Details", "Delete Selected Item"];
    var userSelection = optionList(userOptions);
    if (userSelection === 0) {
        viewItem(selectedItem);
    } else if (userSelection === 1) {
        deleteItem(selectedItem);
    }
}

function viewItem(item) {
    navigate.link('view_item', item);
}

function deleteItem(item) {
    if (confirmDialog("Delete Item?", "Are you sure?", "YES", "NO")) {
        item.destroy();
    }
}
```

`selectedCategory.items` returns the category's related records, including closed issues. The null check handles clearing the selection. The view and delete actions use the same behavior as the main list.


## 6. Test the category workflow

Deploy to Testing and open **Browse by Category**. Choose a category and check that only its issues appear. Open an issue, return, clear the selection, and choose a different category. A category with no issues should show the empty message.

<DocsReference href="/docs/get-started/tutorial-build-your-first-app/advanced-topics/location-relationships-and-roles/user-roles/" variant="next" />
