Skip to main content
Ctrl+K
Syside - Home Syside - Home

Syside

  • About
  • Editor
  • Modeler
  • Automator
  • API
    • Licensing
    • Offline installation
    • Troubleshooting
    • Forum
    • Changelog
preview0.11.0-rc.1latest0.10.30.100.10.30.90.9.10.80.8.80.70.7.20.60.6.4
You are reading the documentation for Syside 0.11.0-rc.1, a pre-release. What it describes can still change before 0.11.0. The current release is 0.10.3. Go to the 0.10.3 documentation
  • About
  • Editor
  • Modeler
  • Automator
  • API
  • Licensing
  • Offline installation
  • Troubleshooting
  • Forum
  • Changelog

Section Navigation

Get started

  • Install Modeler
  • Write your model
  • Visualize your model

Views

  • Diagram views Labs
    • Open a diagram
    • Use diagram panels New
    • Select what a diagram shows
    • Configure diagram views
  • Grid views Labs
    • Use grid views
    • Foundations
    • Configure table views
      • Table view structure
      • Navigation chains
      • Representations
      • Common patterns
      • Examples
      • Migrating from column types
    • Configure matrix views
    • Troubleshooting

Command line

  • Modeler CLI
    • Install Modeler CLI
    • Quickstart
    • Diagram generation Labs
    • CLI commands
    • Configuration

Configuration

  • Configure Modeler
  • Settings in syside.toml
  • Settings in the editor
  • Modeler
  • Grid views
  • Configure table views
  • Navigation chains

Navigation chains

A cell often needs to show something that lives near the row element rather than on it: the subject of a requirement, the value of a named attribute, the definition typing a usage. Navigation chains are how a column reaches such related elements. This page covers the steps chains are built from, naming a chain so that several columns can reuse it, and fanning out, where a chain splits a row into sub-rows.

A column’s columnFeature holds a navigation chain: a small expression that consists of navigation steps. Evaluated once per row, it results in the element the column represents.

A chain starts from baseViewElement, the default feature a cell represents: the row’s own element. To make a cell about something related to the row element, wrap baseViewElement in navigation steps: calculations that take an element and navigate to elements related to it, such as Owner(…) for the owning element or NamedUsage(…, "mass") for a feature by name. The first argument of a step is what it navigates from; the remaining arguments are parameters:

// the "torque" attribute of each row element, looked up by name
:>> columnFeature = NamedUsage(baseViewElement, "torque");

Navigation calculations are declarative: they are interpreted by the Modeler, not evaluated as KerML. Only three things may appear in a chain: navigation steps from the SysideViews library, references to navigations named at view level, and literal or enumeration arguments. A column with an invalid chain degrades to empty read-only cells and explains itself in a banner above the table; the rest of the view keeps working (see Troubleshooting).

Navigation steps

Each step answers two independent questions:

  • What does it navigate to? This is the step’s family: an element’s owner, its heritage, its usage features, and so on.

  • How do the targets it finds reach the table? This is the step’s kind.

Step kinds

There are three kinds. They differ in whether their targets can be navigated further, and in what they do to the row:

Kind

What it does with the targets it finds

Single

Yields at most one target, so further steps can chain onto it. Renders one cell, and the table keeps its rows. In a step family this kind is spelled First (see below).

List

Renders every target together in one read-only cell. Terminal: a list of elements cannot be navigated onwards, so a List call may only be a chain’s last step.

Fan

Splits the column cells into one sub-row per target, changing the shape of the table rather than one cell. Must be given a name at view level (an anchor), and further steps chain from that name. See Fanning out rows.

Some navigations can only ever find one element: an element’s owner, a requirement’s subject, a feature looked up by name. Those are Singles outright and come as a single step with no variants.

A navigation that may find several targets instead comes as a family of three steps, one per kind, with the kind appended to the family name. The Heritage family provides HeritageList, HeritageFan, and HeritageFirst. All three navigate identically and take the same parameters; only the handling of their targets differs.

List takes all the elements of the navigation and lists them in a single cell. Since it returns multiple elements to a single cell it cannot be used as an intermediate step - a List navigation is always the last in the chain.

Fan takes the elements of the navigation and splits them up into subrows. This allows further navigation from this step, though some constraints apply (more in Fanning out rows)

First is the Single member of such a family - it assumes the navigation step will have one and only one output. This allows further navigation, however when navigation results in multiple elements the cell becomes read-only with a warning note rather than quietly picking one (the truncated outcome).

A navigation chain is composed of nested navigation steps and is read from the inside out. The example chain below uses DefinitionsFirst to hop from each part usage to the definition typing it, and NamedUsage navigates on from there to that definition’s torque:

// the "torque" attribute of the definition typing each row element
:>> columnFeature = NamedUsage(DefinitionsFirst(baseViewElement), "torque");

Below is the full list of available navigation steps, their variants and their descriptions:

Step catalogue

Step

Variants

Navigates to

Owner

Single

The element’s owner (parent namespace). Applicable to namespaces.

Subject

Single

The requirement’s subject. Applicable to requirements; on any other row the cell is not applicable.

Definitions

List, Fan, First

The definitions explicitly typing the usage, one hop. Implicit standard-library typing does not count, so an untyped usage yields nothing. Applicable to usages.

Specializations

List, Fan, First

The definitions this definition directly specialises, one hop. Applicable to definitions.

Heritage

List, Fan, First

All supertypes, walked transitively breadth-first, explicitly written specialisations only. An optional depth parameter bounds the walk. Applicable to types.

Usage

List, Fan, First

The element’s usage features, own and inherited, optionally narrowed to a UsageKind. Features inherited from the standard library are dropped. Applicable to definitions and usages.

NamedUsage

Single

The usage feature whose effective name (usually the declared name) matches the name parameter, optionally narrowed to a UsageKind; short names never match. Behaves like the Usage family in every other respect. Applicable to definitions and usages.

RequirementConstraints

List, Fan, First

The requirement’s assume / require constraints, own and inherited. An optional RequirementConstraintKindSV parameter narrows to required or assumed constraints. Applicable to requirements.

MetadataUsageTag

Single

The element’s owned metadata tag (@Tag { … }), selected by the tag definition’s name; the tag usage’s own name never matches. Tags are owned, never inherited. Applicable to namespaces.

UsageHTV

Single

The usage through which the tree reached this row. Only valid in a hierarchical table view, and only applied directly to baseViewElement.

Step parameters

Step parameters bind positionally after the navigation input and must be literals or enumeration references; expressions computing a parameter value are not supported. The steps that take parameters:

Parameter

Steps

What it represents

name

NamedUsage

The name of the usage feature to look up, as a non-empty string literal. Matched against effective names; short names never match.

name

MetadataUsageTag

The name of the tag’s metadata definition, as a non-empty string literal. Which of the definition’s names it matches is chosen by nameType.

nameType

MetadataUsageTag

A NameType member choosing the name to match: name (the effective name, the default) or shortName.

kind

Usage family, NamedUsage

A UsageKind member narrowing which features match: usage (any kind, the default), attributeUsage, itemUsage, partUsage, portUsage, connectionUsage, actionUsage, constraintUsage, assertedConstraintUsage, or requirementUsage.

includeSubtypes

Usage family, NamedUsage

true or false (the default). The kind match is exact by default: UsageKind::itemUsage matches literal item usages only. true widens the kind to everything SysML derives from it, so itemUsage then also admits parts, and partUsage also admits views.

kind

RequirementConstraints family

A RequirementConstraintKindSV member narrowing to the required or assumed constraints; either, the default, accepts both.

depth

Heritage family

An integer literal bounding the heritage walk; -1, the default, is unbounded. HeritageFirst fixes it to 1 and takes no parameter.

// item usages of the row element, subtypes (e.g. parts) included
:>> columnFeature = UsageList(baseViewElement, UsageKind::itemUsage, true);

Two edge cases worth knowing:

  • Exact constraintUsage matches by metaclass, which inside a requirement also includes its assume / require constraints. It does not match assert constraint, which is its own metaclass (assertedConstraintUsage).

  • Enumeration members are variants, not features, so no navigation returns them.

Reusing a navigation

A chain does not have to be written out inside the column that uses it. Declaring a named navigation at view level gives a chain a name that any column can start from:

view enginesTable : TVD::TableView {
    expose DroneProject::Fleet::*;

    engine = NamedUsage(baseViewElement, "engine", UsageKind::partUsage);

    view 'Engine Type' :> columnViews {
        :>> columnFeature = DefinitionsFirst(engine);
        attribute :>> featureRepresentation :> ColRep::declaredName;
    }
    view 'Engine Power' :> columnViews {
        :>> columnFeature = NamedUsage(engine, "power",
        UsageKind::attributeUsage);
        attribute :>> featureRepresentation :> ColRep::featureValue;
    }
    view 'Engine Documentation' :> columnViews {
        :>> columnFeature = engine;
        attribute :>> featureRepresentation :> ColRep::specificDocumentation;
    }
}

All three columns are about the engine, but the step that finds it is written once. A column referencing a named navigation can also chain further steps onto it: Engine Type continues to the definition typing the engine, Engine Power to one of its attributes, while Engine Documentation uses the navigation directly.

A named navigation holds any chain, so it is worth reaching for whenever several columns share a prefix: the shared part is named once, and correcting it later means editing one line rather than every column that repeated it. Referencing one is exactly equivalent to writing its chain out in place, so it changes nothing about the rendered table.

Two restrictions apply:

  • A named navigation must navigate, not merely rename something that already has a name. alias = engine; or root = baseViewElement; is rejected with a hint to reference the original directly.

  • Named navigations may not form a cycle, directly or through one another.

Naming a navigation is required in exactly one case: a fan-out. There the name is more than a convenience, because it also identifies which columns share the split rows, as the next section describes.

Fanning out rows

Every step so far produces at most one cell per row. A Fan step is different: it turns one row into several, one per target it finds. A table whose rows are parts can show one row per port of each part, while still showing each part’s own values alongside.

Because splitting cells affects the whole row rather than one column, a fan-out is the one navigation that cannot sit inline in a column binding. It must be given a name, and a named navigation holding a fan-out is called an anchor. Columns then point at that anchor.

Take a model with a pump whose two ports share a definition, where only inlet sets the maxPressure it declares, and a gauge with no ports at all:

port def FluidPort {
    attribute maxPressure;
}

part def Station {
    part pump {
        port inlet : FluidPort {
            attribute :>> maxPressure = 5.0;
        }
        port outlet : FluidPort;
    }
    part gauge;
}

The view fans each part’s row out over its ports:

ports = UsageFan(baseViewElement, UsageKind::portUsage);

view Part :> columnViews {
    attribute :>> featureRepresentation :> ColRep::declaredName;
}
view Port :> columnViews {
    :>> columnFeature = ports;
    attribute :>> featureRepresentation :> ColRep::declaredName;
}
view 'Max Pressure' :> columnViews {
    :>> columnFeature = NamedUsage(ports, "maxPressure",
    UsageKind::attributeUsage);
    attribute :>> featureRepresentation :> ColRep::featureValue;
    attribute :>> defaultValue = "(unset)";
}

Over that model, the view renders:

Part     Port      Max Pressure
─────────────────────────────────
pump     inlet     5.0
         outlet    (unset)
gauge    N/A       N/A

Three things in that picture are worth naming, because together they are what fanning out means.

The Part cell spans its sub-rows. Part never references the anchor, so it stays one cell per part, covering the run of rows its ports produced. Port and Max Pressure do reference it, so they get one cell per port.

outlet shows a value that is missing, gauge never reached an element that could be represented. outlet exists, so the chain reached it and only the attribute is absent: that is the column’s defaultValue. gauge has no ports at all, so there is no port for either fanned cell to be about: those are notApplicableValue. See Cell outcomes.

gauge still has a row. A fan-out never removes rows. A parent whose fan-out found nothing keeps exactly one row, so nothing silently disappears from the table.

Anchors

An anchor is a named navigation whose outermost call is a Fan step. Unlike an ordinary one, which is pure convenience, an anchor is load-bearing: it is the identity that decides which columns share the rows it produced. The rules that follow are all consequences of rows being a property of the table as a whole:

  • A Fan call must be the outermost call of an anchor, never nested inside another call. A column then references one anchor and applies only non-fanning steps to it.

  • An anchor starts from baseViewElement or from exactly one other anchor, so anchors form a chain, never a tree. Chaining is how a table fans out twice, for example one row per item of each port:

    ports = UsageFan(baseViewElement, UsageKind::portUsage);
    items = UsageFan(ports, UsageKind::itemUsage);
    
  • Two anchors fanning out in parallel is rejected. Rows would be every combination of two unrelated sets, which carries no meaning, so this is the one chain error that disables the whole table instead of degrading a single column.

  • Columns sharing an anchor are aligned by that anchor: on any given row, their cells describe the same target. Two columns fanning over the same feature through separate anchors are not aligned, which is why reusing one anchor is the supported way to put several columns on one fanned target.

  • Fan-out targets appear in declaration order, so row order is stable across reloads.

Column levels

A column’s level is the number of fan-out steps in its chain, and it alone decides how fine-grained that column’s cells are: Part above is level 0, Port and Max Pressure are level 1, and a column chained off items would be level 2.

Level is independent of where a column appears. Reordering columns, whether through columnOrder or by dragging, changes no row and no cell value. A List step also keeps a column at its current level, since it renders all of its targets into a single cell rather than splitting rows.

Merged cells

A cell covering several sub-rows renders once at the start of its run and spans them. Merging is by identity, not by matching text: two ports that happen to share a name are never merged into one, and a repeated value on genuinely different targets stays repeated.

Editing a merged cell edits the one element behind it, so it is a single change rather than one per spanned row. Fanned cells write to their own target: an edit in Max Pressure lands on that row’s port.

Sorting, filtering, and export

Fanned rows change what these operations mean, in ways that keep the table’s structure intact:

  • Sorting is level-scoped. Sorting by a level-1 column reorders the sub-rows inside each parent’s run rather than across the whole table, so rows are never torn out from under the cell spanning them.

  • Filtering applies to the fanned rows. Sub-rows that do not match drop out, and a parent drops too once none of its sub-rows survive. This is distinct from a fan-out that found nothing, which keeps its row.

  • CSV export writes the flattened table: one line per row, with a spanning value repeated on every line it covered, the way a pivot-table export does.

In a hierarchical table a fanned row’s sub-rows are siblings at the same tree position, and the node’s children hang off the last of them. The tree column itself may never fan out.

previous

Table view structure

next

Representations

On this page
  • Navigation steps
    • Step kinds
    • Step catalogue
    • Step parameters
  • Reusing a navigation
  • Fanning out rows
    • Anchors
    • Column levels
    • Merged cells
    • Sorting, filtering, and export

Feedback

Report an issue

Legal

Third Party Licenses

Privacy Policy

Company

Visit Sensmetry

© 2025-2026 Sensmetry. All rights reserved.