Platform
Learn
Developer docs User guide Quickstart Blog
Company
Services About Contact Links Get started

Template variables

Updated

A Raytha template reads a handful of top-level variables. This page lists all of them, says which template kinds receive which, and documents the members of each object, including the value objects that wrap your custom fields.

How variables reach a template

Raytha renders every public template and every email template against one wrapper object. Its properties are the top-level variables you type in Liquid:

VariableContent detailList viewSite pageAccount pagesError pagesWidgetEmail
Targetitemlistsite pageform modelerror modelnouser model
ContentTypeyesyesnonononono
CurrentOrganizationyesyesyesyesyesnoyes
CurrentUseryesyesyesyesyesnono
PathBaseyesyesyesyesyesnono
QueryParamsyesyesyesyesyesnoempty
RequestVerificationTokenyesyesyesno (use Target.RequestVerificationToken)yesnono
ViewDataemptyemptyemptyemptyemptynono
Raytha functionsyesyesyesyesyesmostyes

A variable marked "no" is not an error. It reads as nothing. In a widget, widget carries everything the widget needs, and get_content_items and the other data functions work (see Widget templates). Base layouts are not a separate kind here: a layout is joined into the child's source, so it sees the child's variables.

Rules that apply to every variable

  • Names are case-sensitive and use the .NET spelling. Target.primaryfield is nothing. Target.PrimaryField is the title.
  • A missing member renders as an empty string. It is not an error, so check the HTML.
  • Output is not escaped. Use | escape for any text a person typed.
  • Ids reach the template as strings. Comparing item.Id == Target.Id works, whichever side came from a related item.
  • Dates are UTC DateTime values. Convert with | organization_time: "format" (see Functions and filters).

Target

Content item detail

One item. Members: Id, PrimaryField, RoutePath, PublishedContent, CreationTime, LastModificationTime, CreatorUser, LastModifierUser, Template and ContentType. They are described under Detail views vs list views. CreatorUser and LastModifierUser have Id, FirstName, LastName, FullName and EmailAddress, or are nothing.

List view

Items, TotalCount, PageNumber, PageSize, TotalPages, PreviousDisabledCss, NextDisabledCss, FirstVisiblePageNumber, LastVisiblePageNumber, Search, Filter, OrderBy, RoutePath, Label, DeveloperName and Description. Each entry in Items has the members of a content item detail Target.

Site page

MemberTypeNotes
Target.Idstring
Target.TitlestringThe page title. There is no PrimaryField on a site page.
Target.RoutePathstringNo leading slash.
Target.IsPublished, Target.IsDraftbooleanBoth can be true while a page has unpublished edits.
Target.WebTemplateId, Target.WebTemplateDeveloperNamestringThe page's template.
Target.CreationTime, Target.LastModificationTimedate (UTC)The second is nothing until the first edit is saved.

The widgets of the page are not on Target. You place them with render_section and get_section, covered in Site pages and sections.

Error pages

The templates raytha_html_error_403 and raytha_html_error_404 get an error model. A raytha_html_error_500 template exists in every theme, but the public site never renders it: a failed render returns a plain 500 response instead.

MemberNotes
Target.ErrorIdA short id when Raytha generates one (an unknown route). Empty otherwise.
Target.ErrorMessageFor example the reason a registration was refused.
Target.StackTraceOnly meaningful in Development mode.
Target.IsDevelopmentModeGuard anything technical with it. Never print StackTrace otherwise.

Account pages

Built-in account templates receive a form model. Every one has these three members:

MemberNotes
Target.RequestVerificationTokenPut it in a hidden input named __RequestVerificationToken in every form.
Target.ValidationFailuresA dictionary of messages keyed by input name, plus __ValidationSummary for general errors. Nothing when there are no errors. Read it with Target.ValidationFailures["EmailAddress"].
Target.SuccessMessageFor example "Profile successfully updated." Nothing otherwise.
Template developer nameExtra Target members
raytha_html_login_emailandpassword, raytha_html_login_magiclinkReturnUrl, HasLoginByEmailAndPassword, HasLoginByMagicLink, HasLoginBySingleSignOn, ShowOrLoginWithSection, EmailAndPassword, MagicLink (each an authentication scheme or nothing), SingleSignOns and AuthenticationSchemes (arrays of schemes)
raytha_html_login_magiclinksentEmailAddress, ReturnUrl
raytha_html_user_registrationEmailAddress, FirstName, LastName (what was typed, to refill the form)
raytha_html_forgotpasswordcompleteToken
raytha_html_changeprofile, raytha_html_changepassword, raytha_html_forgotpasswordnone beyond the three above
raytha_html_user_registration_success, raytha_html_forgotpassword_reset_link_sent, raytha_html_forgotpasswordsuccessAn empty model. Target has no members.

An authentication scheme has Id, Label, DeveloperName, IsBuiltInAuth, IsEnabledForUsers, IsEnabledForAdmins, SignInUrl, LoginButtonText and SignOutUrl. The change-profile template shows the current name through CurrentUser.FirstName and CurrentUser.LastName.

ContentType

Set for content item detail and list templates. It is the content type of the item or view.

MemberNotes
ContentType.Id
ContentType.DeveloperNameFor example posts.
ContentType.LabelSingular, ContentType.LabelPluralFor example "Post" and "Posts".
ContentType.Description

It does not list the fields. For those, call get_content_type_by_developer_name.

CurrentOrganization

MemberTypeNotes
OrganizationNamestringThe site name from the settings.
WebsiteUrlstringThe public base URL. Use it for absolute links in emails and canonical tags.
TimeZonestringThe organization time zone that organization_time converts to.
DateFormatstringThe organization's date format string.
HomePageIdstringThe id of the item, view or site page set as the home page.
SmtpDefaultFromAddress, SmtpDefaultFromNamestringThe default sender. Do not print them on public pages.
EmailAndPasswordIsEnabledForUsers, EmailAndPasswordIsEnabledForAdminsbooleanUse the first to hide the password link when that login is off.
AuthenticationSchemesarrayAll configured schemes, with the members listed under Account pages.

CurrentUser

The signed-in public user. For a visitor who is not signed in, IsAuthenticated is false and the name and email members are empty strings.

MemberTypeNotes
IsAuthenticatedbooleanTest this first.
UserIdstring
FirstName, LastName, FullName, EmailAddressstringFullName is first and last name joined by a space.
IsAdminbooleanTrue when the user is an administrator.
Rolesarray of stringsDeveloper names of the user's roles.
UserGroupsarray of stringsDeveloper names of the user's groups. Test with CurrentUser.UserGroups contains 'members'.
SsoId, AuthenticationSchemestringHow the user signed in.
RemoteIpAddressstringThe address after Raytha's trusted-proxy handling.
LastModificationTimedate or nothing

Warning CurrentUser only changes what the template prints. It does not stop anyone from requesting the page. A members-only snippet hides markup from other visitors, but it is not access control for the content item itself.

PathBase, QueryParams, RequestVerificationToken, ViewData

  • PathBase is a string: empty when Raytha is served at the root, /cms when it is served under that path. Start every internal URL with {{ PathBase }}/. A route path never has a leading slash, so {{ PathBase }}/{{ item.RoutePath }} is right.
  • QueryParams is a dictionary of the request's query string. Read QueryParams.search or QueryParams["search"]. A missing key is nothing. Keys are matched exactly as written in the URL. A repeated key (?a=1&a=2) arrives as one comma-joined string.
  • RequestVerificationToken is the anti-forgery token for the request, on every public kind except the account pages, which carry theirs on Target.
  • ViewData is the ASP.NET view data of the request. No public page puts anything in it, so treat it as empty.

Field value objects

Everything under PublishedContent is keyed by the field's developer name. Every field is a value object with three members: Value, Text and HasValue. Text is the value as a string. A field that was never saved on the item is missing, which is the same as empty in practice.

Field type.ValueNotes
Single line text, Long textstringEscape it.
Wysiwygstring of HTMLOutput raw. .Text is the same string.
Numbernumber or nothingFormat with filters such as round. HasValue is true for 0.
Checkboxtrue, false or nothingHasValue is true even when the box is unchecked. Test .Value to ask "is it ticked".
Datedate or nothingA calendar date with no time zone. Format with | date: "%B %e, %Y", not organization_time, which would shift it a day in time zones behind UTC.
Dropdown, RadiostringThe developer name of the chosen choice, not its label.
Multiple selectarray of stringsDeveloper names of the chosen choices. .Text is them joined by a comma and space. Test membership with .Value contains 'x'.
AttachmentstringThe object key of the stored file. Turn it into a URL with | attachment_url or | attachment_public_url.
Colorstring like #1e293bLowercase, six digits.
Repeaterarray of rowsEach row is an object keyed by sub-field developer name: {% for row in x.Value %}{{ row.question }}{% endfor %}. .Text is the rows as JSON.
One-to-one relationshipnot a value objectWhen set, the field is the related item: .Id, .PrimaryField, .RoutePath, .PublishedContent, .IsPublished. When unset it is an empty string.

Examples of each shape, assuming fields named as in the comments:

{%- comment -%} number "price", checkbox "featured", date "published_on" {%- endcomment -%}
{% if Target.PublishedContent.price.HasValue %}${{ Target.PublishedContent.price.Value | round: 2 }}{% endif %}
{% if Target.PublishedContent.featured.Value %}<span class="badge">Featured</span>{% endif %}
{{ Target.PublishedContent.published_on.Value | date: "%B %e, %Y" }}

{%- comment -%} multiple select "tags" and repeater "links" {%- endcomment -%}
{% for tag in Target.PublishedContent.tags.Value %}<span>{{ tag | escape }}</span>{% endfor %}
{% for row in Target.PublishedContent.links.Value %}
  <a href="{{ row.url | escape }}">{{ row.label | escape }}</a>
{% endfor %}

{%- comment -%} relationship "author" {%- endcomment -%}
{% assign author = Target.PublishedContent.author %}
{% if author.Id %}
  <a href="{{ PathBase }}/{{ author.RoutePath }}">{{ author.PrimaryField | escape }}</a>
{% endif %}

A related item holds its own PublishedContent with field objects. It goes one level deep: a relationship field inside the related item is not expanded into a third item. To follow a chain, look the next item up with get_content_item_by_id.

Gotchas

  • Never write {% if Target.PublishedContent.summary %} to test for content. It is true for a saved empty field. Use .HasValue, or != blank on .Value.
  • {{ field | default: "x" }} does not apply, because the field object is not empty. Use {{ field.Value | default: "x" }}.
  • Dropdown values are developer names. To print the label, look the choice up in get_content_type_by_developer_name(...).ContentTypeFields, or store labels as the developer names.
  • An attachment field stores the key, not a URL. Printing .Value in an img src gives a broken image.
  • Never output {{ Target | json }} or {{ item | json }} from get_content_items in a public page. Items from the functions include DraftContent, which holds unpublished edits.

Next steps