💧 Power Pages Liquid Templates

Terminal-Style Quick Reference • Input → Output Examples • Pro Tips Included

if / elsif / else
Basic
Conditional logic - execute code based on conditions
Syntax
{% if user.authenticated %}
  Welcome, {{ user.fullname }}
{% elsif user.email %}
  Hi, {{ user.email }}
{% else %}
  Welcome, Guest
{% endif %}
Output (authenticated user)
Welcome, Dave Bowman
💡 Pro Tip: Use elsif for multiple conditions instead of nested if statements for better readability
for loop
Basic
Iterate over arrays or ranges
Syntax (Array)
{% for item in entityview.records %}
  {{ item.fullname }}
{% endfor %}
Syntax (Range with limit)
{% for i in (1..5) limit:3 %}
  Item {{ i }}
{% endfor %}
💡 Pro Tip: Use forloop.first, forloop.last, forloop.index for special handling in loops
⚠️ Performance: Avoid nested loops on large datasets - use filters like batch or group_by instead
assign
Basic
Create and assign variables
Syntax
{% assign my_variable = "Hello World" %}
{% assign total = price | times: 2 %}
{{ my_variable }} - Total: {{ total }}
💡 Pro Tip: Variables assigned in loops are scoped to that loop - use capture for multi-line content
date
Filter
Format dates and times
Syntax
{{ entity.createdon | date: "dd MMM yyyy" }}
{{ "now" | date: "yyyy-MM-dd HH:mm:ss" }}
Output
15 Jan 2025 2025-01-15 14:30:45
💡 Pro Tip: Use "now" or "today" as input for current date/time
upcase / downcase
Filter
Convert strings to upper or lower case
Syntax
{{ "power pages" | upcase }}
{{ "HELLO" | downcase }}
Output
POWER PAGES hello
join
Filter
Join array elements with a separator
Syntax
{% assign names = "John,Mary,Tom" | split: "," %}
{{ names | join: " | " }}
Output
John | Mary | Tom
where
Filter
Filter array by attribute value
Syntax
{% assign active_users = entityview.records | where: 'statecode', 0 %}
{% for user in active_users %}
  {{ user.fullname }}
{% endfor %}
💡 Pro Tip: Use except filter for inverse filtering (all items NOT matching value)
order_by
Filter
Sort array by attribute (ascending or descending)
Syntax

{{ entityview.records | order_by: 'fullname' | join: ', ' }}


{{ entityview.records | order_by: 'fullname', 'desc' }}
Output
Alice, Bob, Charlie Charlie, Bob, Alice
page
Object
Access current page properties
Syntax
{{ page.title }}
{{ page.url }}
{{ page.description }}
{{ page.id }}
💡 Pro Tip: Use page.url for canonical links and breadcrumbs
user
Object
Access current user/contact properties
Syntax
{% if user %}
  {{ user.fullname }}
  {{ user.email }}
  {{ user.id }}
{% endif %}
⚠️ Security: Always check if user exists before accessing properties to avoid errors for anonymous users
request
Object
Access HTTP request data (URL, query params, etc.)
Syntax
{{ request.url }}
{{ request.path }}
{{ request.params.id }}
{{ request.query }}
Example (URL: /page?id=123&name=test)
request.params.id → 123 request.params.name → test
💡 Pro Tip: Use request.params to build dynamic pages based on URL parameters
entitylist
Dataverse
Load Dataverse records via Entity List configuration
Syntax
{% entitylist name: "Active Contacts" %}
  {% for item in entitylist.records %}
    {{ item.fullname }} - {{ item.emailaddress1 }}
  {% endfor %}
{% endentitylist %}
💡 Pro Tip: Entity Lists respect Table Permissions - perfect for secure data access
⚠️ Performance: Entity Lists are cached - use for read-heavy scenarios
entityview
Dataverse
Load Dataverse records via saved View
Syntax
{% entityview logical_name:'contact', name:'Active Contacts' %}
  Total: {{ entityview.total_records }}
  {% for contact in entityview.records %}
    {{ contact.fullname }}
  {% endfor %}
{% endentityview %}
💡 Pro Tip: Combine with filters like where, order_by for client-side manipulation
fetchxml
Dataverse
Execute FetchXML query for advanced Dataverse queries
Syntax
{% fetchxml query %}
<fetch>
  <entity name="contact">
    <attribute name="fullname"/>
    <filter>
      <condition attribute="statecode" operator="eq" value="0"/>
    </filter>
  </entity>
</fetch>
{% endfetchxml %}
{% for contact in query.results.entities %}
  {{ contact.fullname }}
{% endfor %}
💡 Pro Tip: Use for complex queries not supported by entityview
chart
Dataverse
Embed Power Apps model-driven app chart
Syntax
{% chart id:"EE3C733D-5693-DE11-97D4-00155DA3B01E" viewid:"00000000-0000-0000-00AA-000010001006" %}
powerbi
Dataverse
Embed Power BI reports or dashboards
Syntax
{% powerbi authentication_type:"powerbiembedded" path:"https://app.powerbi.com/groups/.../reports/..." %}
⚠️ Note: Requires Power BI integration enabled in admin center
editable
Dataverse
Render CMS object as editable for content editors
Syntax
{% editable page 'adx_copy' type: 'html', title: 'Page Copy' %}
{% editable snippets 'Header' type: 'html' %}
entityform
Dataverse
Render Basic Form (Entity Form) by name or ID
Syntax
{% entityform name: 'Contact Form' %}
searchindex
Dataverse
Query Power Pages search index
Syntax
{% searchindex query: request.params.q, page: request.params.page %}
  {% if searchindex.results.size > 0 %}
    {% for result in searchindex.results %}
      {{ result.title }}
    {% endfor %}
  {% endif %}
{% endsearchindex %}
case / when
Basic
Switch statement - match against multiple conditions
Syntax
{% case page.title %}
  {% when 'Home' %}
    Welcome home!
  {% when 'About', 'Contact' %}
    Info page
  {% else %}
    Other page
{% endcase %}
💡 Pro Tip: Use case/when for cleaner code when you have 3+ conditions
unless
Basic
Negative conditional - execute if false
Syntax
{% unless user.authenticated %}
  Please sign in to continue
{% endunless %}
Output (unauthenticated)
Please sign in to continue
💡 Pro Tip: unless is equivalent to if not - use what reads better
capture
Basic
Capture template output into a variable
Syntax
{% capture greeting %}
  Hello {{ user.firstname }}, welcome!
{% endcapture %}

{{ greeting }}
💡 Pro Tip: Use capture to build complex strings with Liquid logic
cycle
Basic
Loop through group of strings, outputting next one each time
Syntax
{% for item in items %}
  <div class="{% cycle 'red', 'green', 'blue' %}">
    {{ item }}
  </div>
{% endfor %}
💡 Pro Tip: Perfect for zebra-striping table rows or alternating colors
tablerow
Basic
Generate HTML table rows (must be wrapped in <table> tags)
Syntax
<table>
{% tablerow child in page.children cols:2 %}
  {{ child.title }}
{% endtablerow %}
</table>
💡 Pro Tip: Use cols: parameter to control columns per row
comment
Basic
Add comments that won't be rendered in output
Syntax
{% comment %}
  This text will not appear in the output.
  Use for documentation and notes.
{% endcomment %}
raw
Basic
Output Liquid code without processing it
Syntax
{% raw %}
  {{ user.fullname }} will be displayed literally
{% endraw %}
💡 Pro Tip: Use to show Liquid examples in documentation
== (equals)
Operator
Check if two values are equal
Syntax
{% if user.fullname == 'Dave Bowman' %}
  Hello, Dave
{% endif %}
!= (not equals)
Operator
Check if two values are not equal
Syntax
{% if page.title != 'Home' %}
  Not the home page
{% endif %}
> (greater than)
Operator
Check if left value is greater than right value
Syntax
{% if entityview.records.size > 10 %}
  More than 10 records
{% endif %}
< (less than)
Operator
Check if left value is less than right value
Syntax
{% if page.children.size < 5 %}
  Less than 5 children
{% endif %}
>= (greater or equal)
Operator
Check if left value is greater than or equal to right value
Syntax
{% if entityview.page >= 1 %}
  Valid page number
{% endif %}
<= (less or equal)
Operator
Check if left value is less than or equal to right value
Syntax
{% if entityview.page <= entityview.total_pages %}
  Valid page
{% endif %}
and
Operator
Both conditions must be true
Syntax
{% if user.authenticated and user | has_role: 'Admin' %}
  Admin user
{% endif %}
or
Operator
At least one condition must be true
Syntax
{% if page.title == 'Home' or page.title == 'Index' %}
  Home page
{% endif %}
contains
Operator
Test for substring or array membership
Syntax
{% if page.title contains 'Product' %}
  This is a product page
{% endif %}
startswith
Operator
Test if string starts with substring
Syntax
{% if page.title startswith 'Profile' %}
  Profile page
{% endif %}
endswith
Operator
Test if string ends with substring
Syntax
{% if page.title endswith 'Forum' %}
  Forum page
{% endif %}
append
Filter
Append string to end of another string
Syntax
{{ 'filename' | append: '.pdf' }}
Output
filename.pdf
prepend
Filter
Add string to beginning of another string
Syntax
{{ 'Jane Johnson' | prepend: 'Dr. ' }}
Output
Dr. Jane Johnson
capitalize
Filter
Capitalize every word in a string
Syntax
{{ 'power pages rocks' | capitalize }}
Output
Power Pages Rocks
replace
Filter
Replace all occurrences of substring
Syntax
{{ 'Hello Dave, how are you Dave?' | replace: 'Dave', 'John' }}
Output
Hello John, how are you John?
remove
Filter
Remove all occurrences of substring
Syntax
{{ 'Hello, Dave!' | remove: 'Dave' }}
Output
Hello, !
split
Filter
Split string into array using delimiter
Syntax
{% assign words = 'This is a test' | split: ' ' %}
{{ words[0] }} 
{{ words.size }} 
Output
This 4
💡 Pro Tip: Combine with for loop to iterate over split values
truncate
Filter
Truncate string to specified length with ellipsis
Syntax
{{ 'This is a long run of text' | truncate: 10 }}
Output
This is...
💡 Pro Tip: Ellipsis (...) is included in character count
strip_html
Filter
Remove all HTML tags from string
Syntax
{{ '<p>Hello <strong>World</strong></p>' | strip_html }}
Output
Hello World
newline_to_br
Filter
Convert line breaks to <br /> tags
Syntax
{{ note.notetext | newline_to_br }}
💡 Pro Tip: Useful for displaying multi-line user input as HTML
remove_first
Filter
Remove first occurrence of substring
Syntax
{{ 'Hello Dave, how are you Dave?' | remove_first: 'Dave' }}
Output
Hello , how are you Dave?
replace_first
Filter
Replace first occurrence of substring
Syntax
{{ 'Hello Dave, how are you Dave?' | replace_first: 'Dave', 'John' }}
Output
Hello John, how are you Dave?
strip_newlines
Filter
Remove all line breaks from string
Syntax
{% capture text %}
Line 1
Line 2
{% endcapture %}
{{ text | strip_newlines }}
Output
Line 1Line 2
text_to_html
Filter
Format plain text as HTML with paragraphs and links
Syntax
{{ note.notetext | text_to_html }}
💡 Pro Tip: Converts URLs to hyperlinks and wraps paragraphs in <p> tags
truncate_words
Filter
Truncate string to given number of words
Syntax
{{ 'This is a long run of text' | truncate_words: 3 }}
Output
This is a...
batch
Filter
Divide array into multiple arrays of given size
Syntax
{% assign batches = entityview.records | batch: 2 %}
{% for batch in batches %}
  {% for item in batch %}
    {{ item.fullname }}
  {% endfor %}
{% endfor %}
💡 Pro Tip: Perfect for creating multi-column layouts or pagination
concat
Filter
Concatenate two arrays into single new array
Syntax
{{ group1 | concat: group2 | join: ', ' }}
Output
John, Pete, Hannah, Joan, Bill
except
Filter
Select items WHERE attribute does NOT equal value (inverse of where)
Syntax
{% assign not_redmond = entityview.records | except: 'address1_city', 'Redmond' %}
group_by
Filter
Group array items by attribute value
Syntax
{% assign groups = entityview.records | group_by: 'address1_city' %}
{% for group in groups %}
  {{ group.key }}: {{ group.items.size }} items
{% endfor %}
💡 Pro Tip: Returns array of objects with .key and .items properties
select
Filter
Extract single attribute from each array item
Syntax
{% assign names = entityview.records | select: 'fullname' %}
{{ names | join: ', ' }}
first
Filter
Get first element of array
Syntax
{{ entityview.records | first | fullname }}
last
Filter
Get last element of array
Syntax
{{ entityview.records | last | fullname }}
size
Filter
Get number of items in array or characters in string
Syntax
{{ entityview.records | size }}
{{ 'Hello' | size }}
Output
42 5
shuffle
Filter
Return array with items in random order
Syntax
{{ entityview.records | shuffle | join: ', ' }}
💡 Pro Tip: Great for randomizing testimonials or featured items
skip
Filter
Skip N items and return the rest
Syntax
{% assign words = 'This is a test' | split: ' ' %}
{{ words | skip: 2 | join: ', ' }}
Output
a, test
take
Filter
Take first N items from array
Syntax
{% assign words = 'This is a test' | split: ' ' %}
{{ words | take: 2 | join: ', ' }}
Output
This, is
plus
Filter
Add two numbers
Syntax
{{ entityview.page | plus: 1 }}
Output (page = 5)
6
minus
Filter
Subtract one number from another
Syntax
{{ entityview.page | minus: 1 }}
Output (page = 5)
4
times
Filter
Multiply two numbers
Syntax
{{ 10 | times: 2 }}
Output
20
divided_by
Filter
Divide one number by another
Syntax
{{ 10 | divided_by: 2 }}
{{ 10.0 | divided_by: 3 }}
Output
5 3.333333
⚠️ Watch Out: Integer division rounds down. Use decimal for float result.
modulo
Filter
Return remainder of division
Syntax
{{ 12 | modulo: 5 }}
Output
2
💡 Pro Tip: Use modulo for zebra-striping tables (row % 2 == 0)
round
Filter
Round number to nearest integer or N decimals
Syntax
{{ 4.6 | round }}
{{ 4.5612 | round: 2 }}
Output
5 4.56
ceil
Filter
Round up to nearest integer
Syntax
{{ 4.3 | ceil }}
Output
5
floor
Filter
Round down to nearest integer
Syntax
{{ 4.6 | floor }}
Output
4
date_add_days
Filter
Add or subtract days from date
Syntax
{{ now | date_add_days: 7 | date: 'yyyy-MM-dd' }}
{{ now | date_add_days: -30 | date: 'MMMM dd' }}
💡 Pro Tip: Use negative values to subtract days
date_add_hours
Filter
Add or subtract hours from date/time
Syntax
{{ now | date_add_hours: 2 | date: 'HH:mm' }}
date_add_months
Filter
Add or subtract months from date
Syntax
{{ now | date_add_months: 3 | date: 'MMMM yyyy' }}
date_to_iso8601
Filter
Format date as ISO 8601 standard
Syntax
{{ now | date_to_iso8601 }}
Output
2025-11-04T10:30:00Z
💡 Pro Tip: Use for HTML5 <time> element datetime attribute
date_add_minutes
Filter
Add or subtract minutes from date/time
Syntax
{{ now | date_add_minutes: 30 | date: 'HH:mm' }}
date_add_seconds
Filter
Add or subtract seconds from date/time
Syntax
{{ now | date_add_seconds: -10 | date: 'HH:mm:ss' }}
date_add_years
Filter
Add or subtract years from date
Syntax
{{ now | date_add_years: 1 | date: 'yyyy' }}
date_to_rfc822
Filter
Format date according to RFC 822 (for RSS feeds)
Syntax
{{ now | date_to_rfc822 }}
Output
Mon, 04 Nov 2025 10:30:46 Z
html_safe_escape
Filter
Convert HTML string to safe HTML fragment (removes dangerous tags)
Syntax
{{ '<img src="x" onerror="alert(1)">' | html_safe_escape }}
Output
<img src="x">
⚠️ Security: Removes dangerous attributes like onerror, onclick
xml_escape
Filter
XML-escape string for XML output
Syntax
{{ '<product>Widget</product>' | xml_escape }}
boolean
Filter
Convert value to Boolean (true/false)
Syntax
{% assign is_valid = 'true' | boolean %}
{% if is_valid %}Valid!{% endif %}
decimal
Filter
Convert value to decimal number
Syntax
{% assign price = '19.99' | decimal %}
{{ price | times: 1.1 }}
integer
Filter
Convert value to integer
Syntax
{% assign count = '42' | integer %}
{{ count | plus: 8 }}
string
Filter
Convert value to string
Syntax
{% assign num_str = 42 | string %}
{{ num_str | append: ' items' }}
add_query
Filter
Add query string parameter to URL
Syntax
{{ '/page' | add_query: 'id', '123' }}
Output
/page?id=123
base
Filter
Get base URL (scheme + host + port)
Syntax
{{ 'https://example.com/page?id=1' | base }}
Output
https://example.com
host
Filter
Extract hostname from URL
Syntax
{{ request.url | host }}
path
Filter
Extract path from URL
Syntax
{{ 'https://example.com/products/item' | path }}
Output
/products/item
path_and_query
Filter
Extract path and query string from URL
Syntax
{{ 'https://example.com/page?id=1' | path_and_query }}
Output
/page?id=1
port
Filter
Extract port number from URL
Syntax
{{ 'https://example.com:8080/page' | port }}
Output
8080
remove_query
Filter
Remove query string parameter from URL
Syntax
{{ '/page?id=1&name=test' | remove_query: 'id' }}
Output
/page?name=test
scheme
Filter
Extract URL scheme/protocol
Syntax
{{ request.url | scheme }}
Output
https
default
Filter
Return default value if variable is null or empty
Syntax
{{ user.fullname | default: 'Guest' }}
💡 Pro Tip: Perfect for providing fallback values
file_size
Filter
Format number of bytes as human-readable file size
Syntax
{{ 1024 | file_size }}
{{ 1536000 | file_size }}
Output
1 KB 1.46 MB
h
Filter
HTML attribute encode (shorthand for HTML encoding in attributes)
Syntax
<input value="{{ user.fullname | h }}">
has_role
Filter
Check if user has specific web role
Syntax
{% if user | has_role: 'Administrators' %}
  Admin content
{% endif %}
⚠️ Security: Use for role-based access control
liquid
Filter
Process string as Liquid template
Syntax
{% assign template = 'Hello {{ user.firstname }}' %}
{{ template | liquid }}
entities
Object
Load any Dataverse record by table name and ID
Syntax
{% assign account = entities.account['936DA01F-9ABD-4d9d-80C7-02AF85C822A8'] %}
{% if account %}
  {{ account.name }}
{% endif %}
⚠️ Security: Respects Table Permissions - user must have read access
settings
Object
Access Site Settings by name
Syntax
{{ settings['Header/Logo/Image'] }}
{{ settings['Authentication/Registration/Enabled'] }}
💡 Pro Tip: Use settings for configuration values instead of hardcoding
snippets
Object
Load Content Snippets by name
Syntax
{{ snippets['Footer/Copyright'] }}
{{ snippets['Home/Welcome Message'].adx_value }}
💡 Pro Tip: Content Snippets support multi-language via .adx_value
now
Object
Current UTC date/time when template renders
Syntax
{{ now | date: 'MMMM dd, yyyy HH:mm' }}
Output
November 04, 2025 10:30
⚠️ Watch Out: Value is cached - not updated on every render
escape
Filter
HTML-escape string to prevent XSS
Syntax
{{ user.fullname | escape }}
{{ '<script>alert("XSS")</script>' | escape }}
Output
&lt;script&gt;alert("XSS")&lt;/script&gt;
⚠️ Security: ALWAYS use escape filter when displaying untrusted user input
url_escape
Filter
URI-escape string for use in URLs
Syntax
{{ 'Hello World!' | url_escape }}
Output
Hello+World%21