Skip to content

Jinja Macros

What are macros?

Jinja2 macros are reusable template components — think of them as functions that return HTML. Orchid has a large macro library covering modals, file uploaders, date pickers, cards, page headers, and more. Before writing raw HTML for a UI pattern, check the macros first.

Macro files

FileContents
templates/macros.htmlCore macros — modals, uploaders, date pickers, page headers, cards, etc.
templates/macros_admin_sections.htmlAdmin section layout components
templates/macros_profiles.htmlProfile display macros (all four profile types)
templates/macros_form_questions.htmlForm question rendering (all question types)
templates/case_management_macros.htmlCase management UI components
templates/contact_macros.htmlContact display macros
templates/journey_cycle_macros.htmlMedical cycle event display
templates/user/macros.htmlUser portal macros
templates/email_inbox/macros.htmlEmail inbox components

How to use macros

Import and call

{# Import a single macro #}
{% from 'macros.html' import modal, page_header %}
{# Or import all under an alias #}
{% import 'macros.html' as m %}
{# Call it #}
{{ page_header(title='My Page', breadcrumb=[('Home', '/'), ('My Page', None)]) }}

Module-scoped macros

{% import 'user/macros.html' as user_macros %}
{{ user_macros.profile_card(user) }}

Commonly used macros from macros.html

Page headers

{% from 'macros.html' import page_header %}
{{ page_header(
title='Case Overview',
subtitle='John & Jane Doe',
breadcrumb=[
('Cases', url_for('admin_views.cases')),
('Case Overview', None)
]
) }}

Modals

{% from 'macros.html' import modal %}
{# Trigger button #}
<button data-modal="my-modal">Open Modal</button>
{# Modal definition #}
{{ modal(
modal_id='my-modal',
title='Confirm Action',
body='Are you sure you want to do this?',
confirm_text='Yes, do it',
confirm_action='myJsFunction()'
) }}

File uploaders

{% from 'macros.html' import file_uploader %}
{{ file_uploader(
upload_url='/api/admin/case/document/upload',
case_id=case.id,
doc_type='general',
label='Upload Document'
) }}

Cards

{% from 'macros.html' import card %}
{{ card(title='Case Details', collapsible=True) }}
{# card body content here #}
{% endcall %}

Date pickers

{% from 'macros.html' import date_picker %}
{{ date_picker(
name='transfer_date',
label='Transfer Date',
value=transfer.transfer_date,
required=True
) }}

Form question rendering

The macros_form_questions.html macro file renders all form question types:

{% from 'macros_form_questions.html' import render_question %}
{% for question in form.questions %}
{{ render_question(question, answer=answers.get(question.id)) }}
{% endfor %}

This handles text inputs, textareas, multiple choice, checkboxes, date pickers, and file uploads automatically based on question.question_type.

Profile macros

{% from 'macros_profiles.html' import ed_profile_section, gc_profile_section %}
{# Render a specific ED profile section #}
{{ ed_profile_section(profile, section='personal_info') }}

Adding a new macro

When adding a new reusable UI component:

  1. Decide which macro file it belongs in (feature-specific → feature’s macros file; general-purpose → macros.html)
  2. Write the macro with clear parameter names and defaults:
{% macro my_new_component(title, items=[], show_count=True) %}
<div class="my-component">
<h3>{{ title }}{% if show_count %} ({{ items|length }}){% endif %}</h3>
{% for item in items %}
<div class="item">{{ item.name }}</div>
{% endfor %}
</div>
{% endmacro %}
  1. Document the parameters with a comment above the macro
  2. Add it to this page under the relevant section