قالبها
فینچ از پکیج Dart به نام Jinja بهعنوان موتور قالب خود استفاده میکند. فایلهای قالب در دایرکتوریای که توسط FinchConfigs.widgetsPath پیکربندی شده قرار دارند و از پسوندی که در FinchConfigs.widgetsType تنظیم شده استفاده میکنند (پیشفرض: j2.html).
رندر کردن یک قالب
rq.renderView(path: '...') را با مسیری نسبت به widgetsPath، بدون پسوند فایل، فراخوانی کنید:
// Loads: widgetsPath/pages/home.j2.html
return rq.renderView(path: 'pages/home');
پیش از فراخوانی renderView، با استفاده از rq.addParam() یا rq.addParams() داده را به قالب پاس دهید:
rq.addParams({
'title': 'My Page',
'user': user.toJson(),
'items': items.map((i) => i.toJson()).toList(),
});
return rq.renderView(path: 'pages/home');
نحو قالب
فینچ از نحو استاندارد Jinja2 استفاده میکند. جداکنندهها در FinchConfigs قابلتنظیم هستند اما بهصورت پیشفرض به این شکلاند:
| نحو | هدف |
|---|---|
{{ expression }} |
خروجی گرفتن از یک متغیر یا عبارت |
{% tag %} |
جریان کنترل: if، for، block، include و غیره |
{# comment #} |
نظر (رندر نمیشود) |
متغیرها
{{ title }}
{{ user.name }}
{{ user['email'] }}
جریان کنترل
{% if user %}
<p>Hello, {{ user.name }}</p>
{% else %}
<p>Please log in.</p>
{% endif %}
{% for item in items %}
<li>{{ item.title }}</li>
{% endfor %}
گنجاندن (Include)
{% include 'partials/header.j2.html' %}
وارثسازی / بلوکها
{# layout.j2.html #}
<!DOCTYPE html>
<html>
<head><title>{% block title %}{% endblock %}</title></head>
<body>
{% block content %}{% endblock %}
</body>
</html>
{# pages/home.j2.html #}
{% extends 'layout.j2.html' %}
{% block title %}Home{% endblock %}
{% block content %}
<h1>{{ title }}</h1>
{% endblock %}
استفاده از قالبهای بستهبندیشده (Map)
برای باینریهای کامپایلشده، قالبها را نمیتوان در زمان اجرا از روی دیسک خواند. از jinjaMapTemplate در FinchConfigs برای بستهبندی قالبها بهصورت یک Map<String, String> استفاده کنید:
// Generated by: finch build or finch runner
final mapTemplates = {
'pages/home.j2.html': '<h1>{{ title }}</h1>',
// ...
};
FinchConfigs configs = FinchConfigs(
jinjaMapTemplate: mapTemplates,
widgetsType: 'j2.html',
);
واچر finch serve این map را بهصورت خودکار هنگام تغییر فایلهای قالب، دوباره تولید میکند.
توابع سفارشی قالب (localEvents)
توابع سراسریای اضافه کنید که از هر قالبی قابلفراخوانی باشند:
// In app.dart
Request.localEvents.addAll({
'currentYear': () => DateTime.now().year,
'formatDate': (String iso) => iso.substring(0, 10),
});
در قالب (از پیشوند $l. برای local eventها استفاده کنید):
<footer>© {{ $l.currentYear() }}</footer>
<span>{{ $l.formatDate(post.createdAt) }}</span>
فیلترهای سفارشی (localLayoutFilters)
فیلترهای Jinja اضافه کنید:
Request.addLocalLayoutFilters({
'upper': (value) => value.toString().toUpperCase(),
'excerpt': (value) {
var s = value.toString();
return s.length > 100 ? '${s.substring(0, 100)}…' : s;
},
});
در قالب:
{{ post.title | upper }}
{{ post.body | excerpt }}
متغیرهای داخلی قالب فینچ
این متغیرها بهصورت خودکار در هر قالبی در دسترساند:
{{ isLocalDebug }} — true in development mode
{{ data }} — all addParam() data
{{ session }} — current session map
{{ $rq }} — the Request object
برای فهرست کامل کمککنندههای $e.* و $t() به Template Events مراجعه کنید.
مثال کامل
<!DOCTYPE html>
<html lang="{{ $e.ln }}" dir="{{ $t('dir') }}">
<head>
<meta charset="UTF-8">
<title>{{ $t(title) }}</title>
{{ assets.css() }}
</head>
<body>
<nav>
{% if user %}
<a href="/logout">{{ user.name }}</a>
{% else %}
<a href="/login">Login</a>
{% endif %}
</nav>
<main>
{% block content %}{% endblock %}
</main>
{{ assets.js() }}
</body>
</html>