Custom Filters¶
Add your own filters to transform values in templates. miki-template's filter API mirrors Django's — filters are simply functions that receive a value and optional argument, and return the transformed value.
Table of Contents¶
Register a Simple Filter¶
Use it in templates:
Filters with Arguments¶
Filters can accept arguments after a colon:
Usage:
Multiple Arguments¶
Pass multiple arguments separated by commas:
Usage:
Real-World Example: Dynamic Currency Filter¶
Template usage:
<!-- €1,234.56 -->
{{ 1234.5|currency_dynamic:"EUR", "de-DE" }}
<!-- $1,234.56 -->
{{ 1234.5|currency_dynamic:"USD" }}
Context-Aware Filters¶
Filters receive the rendering context as the third argument, enabling context-aware transformations:
Usage:
Real-world locale-aware formatter:
registerFilter('datetime', (val, format, ctx) => {
const locale = ctx.locale || 'en-US';
const d = new Date(val);
return new Intl.DateTimeFormat(locale, {
dateStyle: format === 'short' ? 'short' : 'full',
timeStyle: format === 'short' ? 'short' : undefined
}).format(d);
});
SafeString Filters¶
Filters can return SafeString to prevent escaping — useful when generating HTML:
Usage:
Async Filters¶
Filters can be async by returning a Promise. Use asyncRender() to render templates with async filters:
Usage:
Note: Async filters only work with
asyncRender()orcompiled.asyncRender(). Using them withrender()orcompiled.render()will throw.
Filter Registration Best Practices¶
-
Handle null/undefined gracefully — Return empty string or a fallback value.
-
Return strings — Filters should generally return string representations for template output.
-
Don't mutate the input — Treat values as immutable.
-
Use
markSafe()for HTML output — Prevent auto-escaping when returning HTML. -
Validate arguments — Coerce numeric arguments with
Number()and handleNaN.
Chaining Custom Filters¶
Custom filters chain the same way as built-in filters:
registerFilter('trim', (val) => String(val || '').trim());
registerFilter('highlight', (val, term) => {
const re = new RegExp(`(${term})`, 'gi');
return markSafe(String(val).replace(re, '<mark>$1</mark>'));
});