Forms
Crema ships a small set of form helpers that read values from the view data map. Pair them with CSRF middleware and validation on the request side.
<form method="post" action="/posts"> @csrf <input name="title" value="{{ title }}"> <button type="submit">Save</button></form>@csrf renders a hidden _token input. Pass the token as _token or csrf_token in the data map (session middleware typically exposes it):
crema.render( "posts.create", mapOf( "_token" to csrfToken, "title" to "", ),)crema.render( "posts.create", Map.of( "_token", csrfToken, "title", "" ));Output shape:
<input type="hidden" name="_token" value="…">If neither key is present, the value attribute is empty — the form will fail CSRF checks until you pass a real token.
Method spoofing (@method)
Section titled “Method spoofing (@method)”HTML forms in browsers only submit as GET or POST. Crema’s @method directive emits a hidden field so templates can declare the intended verb:
<form method="post" action="/posts/{{ post.id }}"> @csrf @method('PUT') …</form>Emits:
<input type="hidden" name="_method" value="PUT">Common values: PUT, PATCH, DELETE.
Field errors
Section titled “Field errors”<label> Email <input name="email" value="{{ email }}"></label>@error('email') <p class="error">{{ errors.email }}</p>@enderrorThe body renders when the view data contains an errors map with a non-empty value for that field:
errors['email'] value |
@error('email') body |
|---|---|
Missing / null |
Skipped |
| Empty string or empty collection | Skipped |
| Non-empty string / collection | Rendered |
| Any other non-null value | Rendered |
crema.render( "auth.login", mapOf( "_token" to token, "email" to submittedEmail, "errors" to mapOf("email" to "Required"), ),)crema.render( "auth.login", Map.of( "_token", token, "email", submittedEmail, "errors", Map.of("email", "Required") ));When validation returns multiple messages per field, pass a list and print them in a loop:
@error('email') <ul> @foreach(errors.email as message) <li>{{ message }}</li> @endforeach </ul>@enderrorFull form example
Section titled “Full form example”@extends('layouts.app')@section('content') <h1>Edit post</h1> <form method="post" action="/posts/{{ post.id }}"> @csrf @method('PUT')
<label> Title <input name="title" value="{{ post.title }}"> </label> @error('title') <p class="error">{{ errors.title }}</p> @enderror
<label> Body <textarea name="body">{{ post.body }}</textarea> </label> @error('body') <p class="error">{{ errors.body }}</p> @enderror
<button type="submit">Update</button> </form>@endsectionAsset URLs in forms and layouts
Section titled “Asset URLs in forms and layouts”<link rel="stylesheet" href="@asset('css/app.css')" />Resolves to /css/app.css by default, or prefixes asset_url / assetUrl from the view data when set (CDN base). See Rendering.
Language strings
Section titled “Language strings”Labels and messages often use @lang — see Rendering.
Pitfalls and FAQ
Section titled “Pitfalls and FAQ”Why does my @method('PUT') form 405?
The request is still POST. Register a POST route or send a real PUT — see Method spoofing.
Why is the CSRF field empty?
Pass _token or csrf_token in the view data (session middleware usually supplies it).
How do I show old input after validation redirect?
Use flashed old input from the session (request.old("email")) when rendering the form again — Validation.