Praktische syntaxis van Mirage Templates voor lay-outbeheer
De grens van de sjabloonlaag
Mirage is bedoeld voor HTML- en tekstpresentatie. U kunt er secties mee verplaatsen, kaarten en koppen aanpassen, decoratieve containers toevoegen, klassen beheren en voorbereide lijsten en gelokaliseerde labels uitvoeren. Een sjabloon mag geen SQL uitvoeren, rechten bepalen, gegevens wijzigen of de routecontrole van een module vervangen. Als een vereist veld niet in de invoercontext aanwezig is, kan een opmaakwijziging alleen het niet betrouwbaar aanmaken.
Openbare sjablonen staan in skins/<Layout>/<Skin>/<Module>/, beheersjablonen in adminskins/... en moderatorsjablonen in moderatorskins/.... Bepaal vóór een wijziging welke Layout en Skin actief zijn. Dezelfde bestandsnaam kan in verschillende bomen voorkomen; een wijziging in een inactieve kopie verandert de pagina niet.
Ontsnapte uitvoer
De primaire en veilige uitvoervorm gebruikt dubbele accolades:
<h1>{{ Context.Table("page").Data("title") }}</h1>
<p>{{ Context.Table("page").Data("summary") }}</p>Tekst wordt voor HTML escaped, zodat tekens uit de gegevens geen tags of attributen worden. Gebruik deze vorm voor koppen, namen, URL's in attributen, labels, zoektermen en alle waarden die een gebruiker kan hebben ingevoerd.
Onbewerkte uitvoer wordt met een uitroepteken aangegeven:
{{! Former.BuildHTML(Context.Table("form").Data("submit_ir")) }}Die is alleen toegestaan voor een bron die zelf al verantwoordelijk is voor veilige HTML, bijvoorbeeld een door Former samengesteld element, een Echelon-zone of vooraf geserialiseerde JSON-LD. Vervang gewone uitvoer niet door raw om een „tag te laten werken” die uit een gebruikersveld komt. Daarmee worden gegevens actieve opmaak.
Benoemde Context-tabellen
Gebruik voor nieuwe sjablonen Context.Table. Eén pagina kan de tabellen meta, page, assets en moduletabellen met het voorvoegsel __ ontvangen. De belangrijkste aanroepen zijn:
Context.HasTable("items")– controleren of een tabel bestaat;Context.Table("items").Data("title")– een veld uit de huidige rij lezen;RowCount()– het aantal rijen ophalen;Rewind()– de cursor naar het begin terugzetten;NextRow()– naar de volgende rij gaan.
De compatibele syntaxis Table.Data(...) blijft in oudere sjablonen met één tabel bestaan, maar moet niet zonder reden met benoemde context worden gemengd.
Voorwaarden, waarden en commentaar
{% if Context.Table("page").Data("status") == "published" %}
<span class="badge badge--live">{{ Boardwords("status_published") | default("Gepubliceerd") }}</span>
{% elif Context.Table("page").Data("status") == "draft" %}
<span class="badge badge--draft">{{ Boardwords("status_draft") | default("Concept") }}</span>
{% else %}
<span class="badge">{{ Boardwords("status_unknown") | default("Onbekend") }}</span>
{% endif %}Vlaggen komen vaak als strings "1" en "0" binnen; vergelijk ze daarom expliciet. Voor een tijdelijke variabele wordt {% set name = value %} gebruikt; commentaar heeft de vorm {# toelichting #} en komt niet in de HTML terecht.
Voor een terugvalwaarde zijn twee vormen beschikbaar:
{{ Context.Table("meta").Data("title") ?? "Zonder titel" }}
{{ Boardwords("catalog_title") | default("Catalogus") }}Een ternaire expressie is handig voor een korte klassewaarde, maar grote blokken kunt u beter met een gewone if schrijven:
{{ Context.Table("page").Data("compact") == "1" ? "card--compact" : "card--wide" }}Veilig door rijen lussen
Een benoemde tabel wordt niet automatisch een array met objecten. Gebruik het volledige cursorpatroon:
{% if Context.Table("products").RowCount() > 0 %}
{% set __ = Context.Table("products").Rewind() %}
<div class="product-grid">
{% for _ in range(0, Context.Table("products").RowCount(), 1) %}
{% if Context.Table("products").NextRow() %}
<article class="product-card{% if loop.even %} product-card--even{% endif %}">
<h3>{{ Context.Table("products").Data("title") }}</h3>
<p>{{ Context.Table("products").Data("summary") }}</p>
</article>
{% endif %}
{% endfor %}
</div>
{% else %}
<p>{{ Boardwords("products_empty") | default("Er is nog niets") }}</p>
{% endif %}De volgorde is verplicht: controleer de rijen, voer Rewind() uit, doorloop het bereik en roep NextRow() aan voordat u Data() leest. In de lus zijn loop.index, loop.first, loop.last, loop.odd en loop.even beschikbaar.
Lokalisatie, formulieren en zones
Voer statische gebruikerslabels via Boardwords uit met een duidelijke fallback. Zo blijft het ontwerp vertaalbaar wanneer het tussen skin-bomen wordt gekopieerd. Als een formulierveld als *_ir binnenkomt, bouw de input dan niet handmatig:
<label>{{ Boardwords("profile_name") | default("Profielnaam") }}</label>
{{! Former.BuildHTML(Context.Table("profile").Data("name_ir"), "class", "profile-form__input") }}Mirage beheert container, raster en klasse; Former beheert het HTML-besturingselement. Inhoud van Echelon Zone wordt eveneens alleen raw uitgevoerd omdat de zone een vertrouwde producent van het fragment is; een willekeurig tabelveld heeft die status niet.
De wijziging controleren
- Breng een gerichte wijziging aan in het actieve sjabloon zonder de volledige shell te kopiëren.
- Controleer de pagina met gegevens, een lege lijst en ontbrekende optionele velden.
- Controleer speciale tekens in tekst en attributen.
- Controleer alle beschikbare talen en de Boardwords-fallbacks.
- Controleer desktop en mobile en bij een beheerformulier ook validatiefouten.
- Controleer of raw alleen wordt gebruikt voor vertrouwde producenten van HTML.
Stop wanneer het sjabloon nieuwe rechten, SQL of een bedrijfsregel nodig blijkt te hebben: de taak valt dan buiten de Mirage-grens. De juiste uitbreiding bereidt eerst gegevens in de module voor, terwijl het sjabloon een voorspelbare presentatielaag blijft.
Paginasamenstelling en dynamische fragmenten
Bewerk de gedeelde shell, het menu en de inhoud van de toepassingsmodule afzonderlijk. Verplaats niet het hele raamwerk naar het sjabloon van één kaart: dat creëert duplicatie en belemmert het wisselen van skin. Gebruik voor een fragment dat door een filter, pager of tab wordt bijgewerkt de afgesproken AJAX-omgeving met Mirage. Laat canonieke openbare tekst die belangrijk is voor de eerste weergave en SEO in de gewone paginarendering staan.
Als het sjabloon een aanvullende namespace uit een callback-pakket gebruikt, bijvoorbeeld voor datumnotatie, controleer dan of het pakket in de doelruntime aanwezig is. Zo'n callback is een afhankelijkheid van dat specifieke sjabloon. Bied waar het ontwerp dit toestaat een duidelijke fallback en probeer een ontbrekende callback niet met ingewikkelde stringexpressies na te bootsen.
Praktijk voor veilige review
Vergelijk de uiteindelijke HTML vóór en na de wijziging, niet alleen de bron van `.mirage`. Controleer de balans van tags, unieke id's, toegankelijkheid van labels, geldigheid van links en het ontbreken van geneste interactieve elementen. Test voor lijsten één en meerdere rijen: cursorfouten zijn bij één record vaak niet zichtbaar. Controleer tabel- en veldnamen opnieuw wanneer u een sjabloon tussen skin-bomen verplaatst, want visueel vergelijkbare modules hoeven niet dezelfde context te krijgen.