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