Liquid Templates
Complete guide to using Liquid expressions in FluidForms
FluidForms uses Liquid templating to create dynamic, intelligent forms. This guide covers everything you need to know about using Liquid expressions.
What is Liquid?
Liquid is a templating language that lets you insert dynamic content, perform calculations, and create conditional logic in your forms. Think of it as a simple programming language embedded in your form.
Where Can You Use Liquid?
Liquid expressions work in most string values throughout your form:
- Field values (pre-fill or calculate)
- Field visibility (hidden property)
- Field validation (min/max properties)
- Section navigation (go to section name)
- Button labels
- Field options (in some cases)
Important: Liquid does not work in field names or section names - these must be static strings.
Liquid Basics
Liquid has two types of markup:
Output Expressions {{ }}
Display or insert values. The result is rendered to users.
{{ firstName }}
Total: ${{ price | times: quantity }}
Tags {% %}
Control flow and logic. These don't directly render output.
{% if age >= 18 %}
Adult content
{% endif %}
{% assign total = price | times: quantity %}
Accessing Form Data
Field values are available directly by their Field Name.
{{ firstName }}
{{ email }}
Note: Ensure your field names are unique and do not conflict with built-in variables.
Built-in Variables
FluidForms provides helpful built-in variables:
{{ now }} // Current date and time in ISO format
{{ today }} // Current date in YYYY-MM-DD format
Examples
Application Date: {{ today }}
Expires: {{ today | add_time: 30, 'day' | format_date: 'YYYY-MM-DD' }}
Submitted at: {{ now }}
Control Flow
if / elsif / else / endif
Conditional logic for making decisions:
{% if membership == 'Gold' %}
You receive 20% off
{% elsif membership == 'Silver' %}
You receive 10% off
{% else %}
No discount available
{% endif %}
unless / endunless
The opposite of if - executes when condition is false:
{% unless subscribed %}
Sign up for our newsletter!
{% endunless %}
for / endfor
Loop over arrays:
{% for item in cart %}
- {{ item.name }}: ${{ item.price }}
{% endfor %}
Loop parameters:
{% for item in items limit:3 %} // First 3 items
{% for item in items offset:2 %} // Skip first 2
{% for item in items reversed %} // Reverse order
{% for i in (1..5) %} // Range from 1 to 5
liquid tag
Write multiple statements without repeating delimiters:
{% liquid
assign price = 100
assign tax = price | times: 0.1
assign total = price | plus: tax
echo total
%}
Filters
Filters modify values using the pipe | operator:
{{ "hello" | capitalize }} // Hello
{{ 4.6 | round }} // 5
{{ items | size }} // Number of items
Math Filters
{{ 10 | plus: 5 }} // 15
{{ 10 | minus: 3 }} // 7
{{ 10 | times: 2 }} // 20
{{ 10 | divided_by: 2 }} // 5
{{ 10 | modulo: 3 }} // 1
{{ 4.6 | round }} // 5
{{ 4.2 | ceil }} // 5
{{ 4.9 | floor }} // 4
{{ -5 | abs }} // 5
{{ 3 | at_least: 5 }} // 5 (minimum)
{{ 10 | at_most: 5 }} // 5 (maximum)
String Filters
{{ "hello" | capitalize }} // Hello
{{ "hello" | upcase }} // HELLO
{{ "HELLO" | downcase }} // hello
{{ " hello " | strip }} // hello
{{ "Long text here" | truncate: 8 }} // Long ...
{{ "One two three" | truncatewords: 2 }}// One two...
{{ "hello" | replace: "h", "j" }} // jello
{{ "a,b,c" | split: "," }} // ['a','b','c']
{{ tags | join: ", " }} // tag1, tag2, tag3
{{ "hello" | size }} // 5
Array Filters
{{ items | first }} // First item
{{ items | last }} // Last item
{{ items | size }} // Number of items
{{ items | join: ", " }} // Join array to string
{{ products | map: "name" }} // Extract property
{{ products | where: "available", true }} // Filter by property
{{ items | sort }} // Sort (case-sensitive)
{{ items | sort_natural }} // Sort (case-insensitive)
{{ tags | uniq }} // Remove duplicates
{{ arr1 | concat: arr2 }} // Combine arrays
{{ items | compact }} // Remove nil values
Essential Filters
{{ name | default: "Guest" }} // Fallback for empty values
{{ "42" | plus: 0 }} // Convert string to number
{{ object | json }} // Convert to JSON string
{{ object | json: 2 }} // JSON with indentation
Date/Time Filters (Custom)
// Add time to a date
{{ someDate | add_time: 7, "day" }}
{{ today | add_time: 1, "year" }}
// Subtract time from a date
{{ someDate | subtract_time: 18, "year" }}
{{ now | subtract_time: 30, "minute" }}
// Format a date
{{ someDate | format_date: "YYYY-MM-DD" }}
{{ now | format_date: "MMM DD, YYYY" }}
// Get start of time period
{{ now | start_of: "day" }}
{{ someDate | start_of: "month" }}
// Compare dates
{{ date1 | is_before: date2 }} // true/false
{{ date1 | is_after }} // true/false (compares to now)
{{ date | is_between: start, end }} // true/false
// Calculate difference
{{ birthDate | diff_time: today, "year" }} // Age in years
{{ deadline | diff_time: now, "day" }} // Days until deadline
// Human-readable relative time
{{ someDate | time_from }} // "2 hours ago"
{{ futureDate | time_from }} // "in 3 days"
Time units: "year", "month", "week", "day", "hour", "minute", "second"
Practical Examples
Example 1: Age Calculation
{% assign age = birthDate | diff_time: today, "year" %}
Age: {{ age }}
{% if age >= 18 %}
You are eligible to vote
{% else %}
You will be eligible in {{ 18 | minus: age }} years
{% endif %}
Example 2: Discount Calculation
{% liquid
assign basePrice = price | default: 0
assign quantity = quantity | default: 1
assign subtotal = basePrice | times: quantity
if membershipType == "gold"
assign discount = 0.2
elsif membershipType == "silver"
assign discount = 0.1
else
assign discount = 0
endif
assign discountAmount = subtotal | times: discount
assign total = subtotal | minus: discountAmount
%}
Subtotal: ${{ subtotal }}
Discount: ${{ discountAmount }}
Total: ${{ total }}
Example 3: Conditional Navigation
{% liquid
assign age = birthDate | diff_time: today, "year"
assign hasGuardian = hasGuardian | default: "no"
if age < 18 and hasGuardian != "yes"
echo "guardian-required"
elsif age < 18
echo "minor-section"
else
echo "adult-section"
endif
%}
Example 4: Dynamic Validation
Field: Event Date
Minimum: {{ today | add_time: 1, "day" | format_date: "YYYY-MM-DD" }}
Maximum: {{ today | add_time: 1, "year" | format_date: "YYYY-MM-DD" }}
Example 5: Multi-field Summary
{% liquid
assign items = selectedItems
assign itemNames = items | map: "name" | join: ", "
assign itemCount = items | size
assign totalPrice = 0
for item in items
assign totalPrice = totalPrice | plus: item.price
endfor
%}
You selected {{ itemCount }} items: {{ itemNames }}
Total: ${{ totalPrice }}
Example 6: Conditional Field Display
Field: Additional Information
Hidden:
{% if needsMoreInfo == "yes" %}
false
{% else %}
true
{% endif %}
Advanced Patterns
Pattern 1: Complex Calculations with Variables
{% liquid
assign income = annual_income | plus: 0
assign expenses = monthly_expenses | plus: 0 | times: 12
assign netIncome = income | minus: expenses
assign savingsRate = netIncome | divided_by: income | times: 100
if savingsRate >= 20
assign savingsLevel = "Excellent"
elsif savingsRate >= 10
assign savingsLevel = "Good"
else
assign savingsLevel = "Needs Improvement"
endif
%}
Your savings rate: {{ savingsRate | round: 1 }}%
Level: {{ savingsLevel }}
Pattern 2: Date Range Validation
{% liquid
assign start = start_date
assign end = end_date
assign duration = end | diff_time: start, "day"
if duration < 0
echo "End date must be after start date"
elsif duration > 365
echo "Duration cannot exceed 1 year"
else
echo "Duration: " | append: duration | append: " days"
endif
%}
Pattern 3: Scoring System
{% liquid
assign score = 0
if experience == "5+ years"
assign score = score | plus: 30
elsif experience == "3-5 years"
assign score = score | plus: 20
elsif experience == "1-3 years"
assign score = score | plus: 10
endif
if education == "Masters"
assign score = score | plus: 20
elsif education == "Bachelors"
assign score = score | plus: 10
endif
if certifications | size > 0
assign certCount = certifications | size
assign certPoints = certCount | times: 5 | at_most: 20
assign score = score | plus: certPoints
endif
%}
Your qualification score: {{ score }}/100
Best Practices
1. Use Variables for Clarity
❌ Bad:
{{ price | times: quantity | times: 1.1 | plus: 5 }}
✅ Good:
{% liquid
assign subtotal = price | times: quantity
assign withTax = subtotal | times: 1.1
assign total = withTax | plus: 5
%}
Total: ${{ total }}
2. Provide Fallbacks
❌ Bad:
{{ price | times: quantity }}
✅ Good:
{{ price | default: 0 | times: quantity | default: 1 }}
3. Validate with Static Field Names
❌ Bad:
// Field label: "Customer's Email"
{{ values['Customer\'s Email'] }}
✅ Good:
// Field label: "Customer's Email"
// Field name: email
{{ email }}
4. Keep Expressions Simple
❌ Bad:
{% if a and b or c and not d or e %}
✅ Good:
{% liquid
assign conditionA = false
if a and b
assign conditionA = true
endif
assign conditionB = false
if c and d != true
assign conditionB = true
endif
if conditionA or conditionB or e
echo "condition-met"
endif
%}
Common Pitfalls
1. Using Output Instead of Tag
❌ {{ if age >= 18 }}
✅ {% if age >= 18 %}
2. Forgetting to Close Tags
❌ {% if condition %} content
✅ {% if condition %} content {% endif %}
3. Wrong Variable Access
❌ {{ values.firstName }}
✅ {{ firstName }}
4. String Concatenation
❌ {{ "Hello " + name }}
✅ {{ "Hello " | append: name }}
5. Missing Default Values
❌ {{ price | times: quantity }}
✅ {{ price | default: 0 | times: quantity | default: 1 }}
Next Steps
- Logic & Branching - Apply Liquid to create dynamic forms
- Fields - See where Liquid can be used
- Advanced Logic - Advanced customization options
- Troubleshooting Guide - Solutions for common issues
