Skip to content

Expressions

An expression is a line of JavaScript the overlay evaluates for you against the live match data. Rive graphics use expressions for every data binding. A code graphic uses them in the userExpressions array of its manifest, and receives the results in userExpressionValues. The overlay evaluates every expression again on every data change.

A user expression
$d.1.score > $d.2.score ? $d.1.name : $d.2.name

An expression is JavaScript. The overlay evaluates it in a sandbox with the references and helpers on this page, and nothing else.

  • One expression or many statements. A single expression returns its value. A script of several statements returns the value of the last statement, with no return. var, if, for, while and function expressions all work.
  • No browser globals. window, document, fetch, Date, RegExp, Promise, Symbol, Intl, Error and timers are not in scope. Each one resolves to undefined. A call such as new Date() throws, and the binding falls back to its default. There is no clock in an expression. Send a time value through the match data or a theme variable instead.
  • Regular expression literals work. The RegExp constructor is absent, but /live/i.test(x) and x.match(/\d+/) both work, because a literal is syntax and not a global.
  • The NaN and Infinity globals are absent. Use Number.NaN and Number.POSITIVE_INFINITY, or test with isNaN(x).
  • No logical assignment. ||=, &&= and ??= do not work on match data. The left side is read before the missing-data rules apply, so the assignment never happens. Write x = x || 'fallback' instead.
  • No side effects. An expression cannot change the match data, the variables or the graphic.
  • Numeric keys with dot notation. $d.1.score is rewritten to $d['1'].score before evaluation. Bracket notation works too.
ReferenceHoldsKeyed by
$dThe live match data for the sport. The same shape as sportData in Data bindingSport field names
$vThe control variables of the graphic. Each one is { value, data }Variable name
$tThe theme variables: colours, labels, sponsor namesVariable name
$uThe other user expressions of the graphic, by name, already evaluatedExpression name
$xThe latest snapshot of each external data source of the themeData source alias

$d is the sport data of the match. $d.1 is the home team and $d.2 is the away team in every team sport. Read the schema for the field list: GET /v2/schemas/sports/{sport} over REST.

$d.1.abbreviation // "MUN"
$d.clock // "43:30"
$d.1.startingLineup[0].lastName // The first starter of the home team
$d.1.scorers?.[0]?.player.lastName ?? '' // Optional chaining works

A control variable is { value, data }. value is what the operator set. data is the resolved entity for an entity-typed variable: the team, the player, the fact or the statistic.

$v.Title.value // "LINEUP"
!$v.hide.value // true while the graphic is on air
$v.Team.value // 1, the team id
$v.Team.data.name // "Manchester United"
$v.StatOne.data.names.plural // "Shots"
$v.StatOne.data[1] // The home team value of the statistic
Number($v.Rows.value) >= 3 // An enum value is a string

A theme variable resolves to its value. A per-graphic override wins over the theme value, and the theme value wins over the default.

$t.primaryColor // "#0000ff"
$d.isLive ? $t.liveLabel : $t.idleLabel

A user expression can read another user expression by name. The overlay evaluates them in dependency order. An expression in a cycle, or one that throws, resolves to null.

$u.leader + ' leads by ' + $u.margin

An external data source is a JSON or CSV snapshot the theme declares and a write key fills over REST. Read it by alias. See External data sources.

$x.results.rows[0].Home ?? ''
$x.results.rows.length

Inside a list binding of a Rive graphic, two more names are in scope.

NameValue
indexThe position of the current item, from 0
lengthThe number of items in the list
HelperReturns
startsWith(str, prefix)true when str starts with prefix. false for a missing string
endsWith(str, suffix)true when str ends with suffix. false for a missing string
contains(strOrArray, item)true when the string or array holds item. false for a missing value
find(array, fn)The first item for which fn returns true
findIndex(array, fn)The index of that item, or -1
filter(array, fn)The items for which fn returns true
map(array, fn)A new array of fn(item)
reduce(array, fn, initial)The folded value

These JavaScript built-ins are in scope: Math, Number, String, Boolean, Array, Object, JSON, parseInt, parseFloat, isNaN and isFinite. String and array methods work on any value, so $d.1.name.toUpperCase() and $d.1.squad.map(p => p.lastName) both work.

A missing value adapts to how you use it: blank as text, 0 in arithmetic. The same path works in both places, with no guard.

$d.1.aggregateScore // Blank in a text binding
$d.1.aggregateScore + $d.1.score // Adds as 0
`agg ${$d.1.aggregateScore}` // "agg "

Missing means null, or a field this match does not carry. 0, false and '' are real values. They are never treated as missing.

The members of the field’s type work as well, so you do not have to guard before you call a method. A chain never throws, however deep.

$d.1.coachName.toUpperCase() // ''
$d.1.coachName.length // 0
$d.1.squad.map(p => p.lastName) // []
$d.1.squad.length // 0
$d.1.a.b.c // '' — no error

A path outside the schema has no type to adapt to. It reads as an object you can keep reading into, and a method call on it throws, so the binding falls back to its default.

$d.1.coachName.toUpperCase() // '' — the schema knows coachName is a string
$d.1.notInTheSchema.toUpperCase() // Throws — check the field name against the schema

Read the schema before you write a path: GET /v2/schemas/sports/{sport}.

CheckMatches
x == nullnull and absent. 0, false and '' do not match
!xnull and absent, and also 0, false and ''

Use == null when a zero is a real value you must keep on screen. Both || and ?? fall back on a missing value.

A dash only when there is no aggregate score
$d.1.aggregateScore == null ? '-' : $d.1.aggregateScore
A zero is a real score
$d.1.score == null // false — the team has 0, which is a value
!$d.1.score // true — 0 is falsy
$d.1.coachName || 'TBC'

The value your expression returns is not always the value the graphic sees.

Every binding coerces the value to the type of its view model property. This is why a missing number still shows 0 on a number property, even though the expression returned ''.

Property typeCoercion
stringString(value)
numberNumber(value), and 0 when that is not a number
booleanTruthy, except '', '0', 'false' and 0, which are all false
colorA #rgb, #rrggbb or #rrggbbaa string, or a finite number read as ARGB (0xFFFF0000 is opaque red). Any other value, such as '' or 'red', is ignored and the graphic keeps its current color
imageA URL string

An expression that throws never reaches the binding. The binding falls back to the default for its type.

A code graphic has no bindings, so nothing coerces the value. Each result arrives in userExpressionValues exactly as the expression returned it, including '' for a missing number. Handle the type in your own code.

In a code graphic
const agg = Number(values.aggregateScore) || 0

An expression that throws, or one in a dependency cycle, arrives as null.

The overlay logs every expression error. Test each expression against a rehearsal scenario before you publish: GET /v2/scenarios/{sport} returns sample sportData for the sport.

Run it against a scenario with missing data as well as a full one. Most expression bugs only appear when a field is absent.

Score line
$d.1.abbreviation + ' ' + $d.1.score + ' - ' + $d.2.score + ' ' + $d.2.abbreviation
Show a row only when it has data
$d.1.scorers?.[index] ? true : false
Goal minute with penalty and own goal markers
var event = $d.1.scorers?.[0]?.scoreEvents?.[0]
var marker = event?._fact === 'OWN_GOAL' ? ' (OG)' : event?.isPenaltyGoal ? ' (P)' : ''
event ? event.minute + "'" + marker : ''
Red card count for both teams
var cards = $d.1.redCards + $d.2.redCards
cards === 0 ? '' : cards === 1 ? '1 red card' : cards + ' red cards'
Aggregate score, hidden when there is no first leg
$d.1.aggregateScore == null ? '' : '(' + $d.1.aggregateScore + ')'
Squad count that survives an absent squad
($d.1.squad || []).length