# Common List UI Patterns

Reference for the standard structural patterns used in list screens.
All patterns are drawn from real files in `src/`.

---

## 1. Standard List Page Skeleton

A list screen is a `SingleSectionPage` with one `SingleElementArea` containing a `GroupedList`.

```xml
<UIDescription name="<Module>::<Screen>UI" schemaVersion="0.0.0.5">
  <Page pagePattern="SingleSectionPage" cachable="false">
    <PageHeader>
      <Bindings>
        <Resource target="title" type="Label" id="<screenTitleId>" defaultLabel="<Screen Title>" />
      </Bindings>
    </PageHeader>
    <HeaderLine name="Header" />
    <Section sectionName="masterSection" sectionPattern="SingleAreaSection">
      <Area areaName="mainArea" areaPattern="SingleElementArea">
        <GroupedList name="<entity>List"
                     dataSource="ProcessContext::<ListDeclaration>.items[]"
                     searchBarPlacement="HeaderLine"
                     searchable="true">
          <Items name="Items" itemPattern="<PatternName>">
            <ItemListLayout>
              <Default>
                <!-- Column layout — see section 2 -->
              </Default>
            </ItemListLayout>
            <Bindings>
              <!-- Field bindings — see section 3 -->
            </Bindings>
          </Items>
          <Events>
            <ItemSelectedEvent event="itemSelected">
              <Params>
                <Param name="pKey" value=".pKey" />
              </Params>
            </ItemSelectedEvent>
          </Events>
          <SearchAttributes>
            <!-- See section 4 -->
          </SearchAttributes>
        </GroupedList>
      </Area>
    </Section>
  </Page>
</UIDescription>
```

Real anchor: `src/Tour/PR/Tour_TourOverview/Tour_TourOverviewUI.userinterface.xml`

Key attributes on `GroupedList`:

-   `dataSource` — always `ProcessContext::<DeclarationName>.items[]` (lowercase `items`, no capital I for list UI — contrast with CockpitList which uses `Items[]`)
-   `searchBarPlacement="HeaderLine"` — places the search bar at the top
-   `searchable="true"` — enables the client-side search bar
-   `cachable="false"` on `<Page>` — prevents stale data on return

---

## 2. Column Layout Patterns

### Two-column (primary + secondary info)

```xml
<Default>
  <Col width="7.25em">
    <Row layoutType="itemIdentifier" bindingId="<primaryField>" />
    <Row layoutType="itemSecondary" bindingId="<secondaryField>" />
  </Col>
  <Col width="4.5em">
    <Row layoutType="itemSecondary" bindingId="<countOrStatus>" />
  </Col>
</Default>
```

### Three-column (name + date + status with icon)

```xml
<Default>
  <Col width="7.25em">
    <Row layoutType="itemIdentifier" bindingId="Name" />
    <Row layoutType="itemSecondary" bindingId="StartDate" />
  </Col>
  <Col width="4.5em">
    <Row layoutType="itemSecondary" bindingId="Count" />
  </Col>
  <Col width="7.25em">
    <Row>
      <Col layoutType="Image" bindingId="StatusIcon" />
      <Col layoutType="itemNameSecondary" bindingId="StatusText" />
    </Row>
  </Col>
</Default>
```

Real anchor: `src/Tour/PR/Tour_TourOverview/Tour_TourOverviewUI.userinterface.xml`

### Responsive variant (Tablet + Phone breakpoints)

```xml
<ItemListLayout>
  <Tablet>
    <Default>
      <Col width="3em" height="3em" layoutType="Image" bindingId="MediaPath" />
      <Col width="16em">
        <Row layoutType="itemIdentifier" bindingId="PrimaryText" />
        <Row layoutType="itemSecondary" bindingId="MetaText" />
      </Col>
      <Col width="5em">
        <Row layoutType="itemValue" bindingId="DateField" />
      </Col>
    </Default>
  </Tablet>
  <Phone>
    <Default>
      <Col width="2em" height="2em" layoutType="Image" bindingId="MediaPath" />
      <Col width="6.7em">
        <Row layoutType="itemIdentifier" bindingId="PrimaryText" />
        <Row layoutType="itemSecondary" bindingId="MetaText" />
      </Col>
      <Col width="4.8em">
        <Row layoutType="itemValue" bindingId="DateField" />
      </Col>
    </Default>
  </Phone>
</ItemListLayout>
```

Real anchor: `src/Sales Folder/PR/SalesFolder_SalesFolderOverview/SalesFolder_SalesFolderOverviewUI.userinterface.xml`

Common `layoutType` values:
| layoutType | Purpose |
|---|---|
| `itemIdentifier` | Primary/title text (largest, bold) |
| `itemSecondary` | Secondary label text |
| `itemNameSecondary` | Medium-weight secondary |
| `itemValue` | Right-aligned data value |
| `itemValueSmall` | Smaller right-aligned value |
| `itemImportantValue` | Highlighted important value |
| `Image` | Image/icon cell |

---

## 3. Item Binding Patterns

All bindings inside `<Items>` use `bindingMode="ONE_WAY"` (list rows are read-only).

```xml
<Bindings>
  <!-- Text field from LI property -->
  <Binding target="<BindingId>" type="Text" binding=".<liPropertyName>" bindingMode="ONE_WAY" />
  <!-- Date field -->
  <Binding target="<BindingId>" type="Date" binding=".<liDateProperty>" bindingMode="ONE_WAY" />
  <!-- Image field -->
  <Binding target="<BindingId>" type="Image" binding=".<liImageProperty>" bindingMode="ONE_WAY" />
  <!-- Static label (header or spacer) -->
  <Resource target="<BindingId>" type="Label" id="<resourceId>" defaultLabel="<Label Text>" />
</Bindings>
```

The `target` value in each `<Binding>` or `<Resource>` must match the `bindingId` used in `<Col layoutType="..." bindingId="...">`.

Real anchor: `src/Tour/PR/Tour_TourOverview/Tour_TourOverviewUI.userinterface.xml`

---

## 4. Search and Filter Patterns

### Client-side text search (SearchAttribute)

Adds incremental search over LI properties already loaded into memory. No extra DS call.

```xml
<SearchAttributes>
  <SearchAttribute name="<liPropertyName1>" />
  <SearchAttribute name="<liPropertyName2>" />
</SearchAttributes>
```

Real anchor: `src/Sales Folder/PR/SalesFolder_SalesFolderOverview/SalesFolder_SalesFolderOverviewUI.userinterface.xml`

### Header-line filter dropdown (via LU)

For server-side / reload filtering, a `SelectionBox` in the `HeaderLine` passes a value to
the DS's `ConditionalParameters`. This requires a separate LU and a reload action in the process.

Pattern: `HeaderLine` → `SelectionBox` → fires an event → process calls `LOAD` with new parameter.

---

## 5. Empty State

The framework shows an automatic empty-list indicator when `items[]` is empty.
For a custom message, add an `EmptyArea` to the section:

```xml
<Section sectionName="masterSection" sectionPattern="SingleAreaSection">
  <EmptyArea>
    <GroupedList name="EmptyList" dataSource="ProcessContext::<ListDeclaration>.items[]" searchable="false">
      <NoDataMessage name="NoDataMsg">
        <Bindings>
          <Resource target="maintext" type="Label" id="noDataMainTextId" defaultLabel="No records found." />
          <Resource target="subtext" type="Label" id="noDataSubTextId" defaultLabel="Try adjusting your filter." />
        </Bindings>
      </NoDataMessage>
    </GroupedList>
  </EmptyArea>
  <Area areaName="mainArea" ...>
    ...
  </Area>
</Section>
```

---

## 6. Page-Level Action Buttons

Sort buttons or filter toggles sit in the `<PageHeader><MenuItems>` block:

```xml
<PageHeader>
  <MenuItems>
    <MenuItem itemId="SortByName" directlyVisible="false">
      <Bindings>
        <Resource target="Text" type="Label" id="sortByNameId" defaultLabel="Sort by Name" />
        <Resource target="Icon" type="Image" id="StarBlueGrey24Inv" />
      </Bindings>
      <Events>
        <ButtonPressedEvent event="sortByNamePressed" />
      </Events>
    </MenuItem>
  </MenuItems>
</PageHeader>
```

Real anchor: `src/Sales Folder/PR/SalesFolder_SalesFolderOverview/SalesFolder_SalesFolderOverviewUI.userinterface.xml`

The event fires into the process, which calls a BL method (e.g., `lo.setSortOrder(...)`) then
returns to the VIEW action without a full reload.
