1Mojolicious::Guides::ReUnsdeerriCnogn(t3r)ibuted Perl DoMcoujmoelnitcaitoiuosn::Guides::Rendering(3)
2
3
4

NAME

6       Mojolicious::Guides::Rendering - Rendering content
7

OVERVIEW

9       This document explains content generation with the Mojolicious
10       renderer.
11

CONCEPTS

13       Essentials every Mojolicious developer should know.
14
15   Renderer
16       The renderer is a tiny black box turning stash data into actual
17       responses utilizing multiple template systems and data encoding
18       modules.
19
20         {text => 'Hello.'}                 -> 200 OK, text/html, 'Hello.'
21         {json => {x => 3}}                 -> 200 OK, application/json, '{"x":3}'
22         {text => 'Oops.', status => '410'} -> 410 Gone, text/html, 'Oops.'
23
24       Templates can be automatically detected if enough information is
25       provided by the developer or routes. Template names are expected to
26       follow the "template.format.handler" scheme, with "template" defaulting
27       to "controller/action" or the route name, "format" defaulting to "html"
28       and "handler" to "ep".
29
30         {controller => 'users', action => 'list'} -> 'users/list.html.ep'
31         {template => 'foo', format => 'txt'}      -> 'foo.txt.ep'
32         {template => 'foo', handler => 'epl'}     -> 'foo.html.epl'
33
34       The "controller" value gets converted from "CamelCase" to "snake_case"
35       using "decamelize" in Mojo::Util and "-" characters replaced with "/".
36
37         {controller => 'My::Users', action => 'add'} -> 'my/users/add.html.ep'
38         {controller => 'my-users', action => 'show'} -> 'my/users/show.html.ep'
39
40       All templates should be in the "templates" directories of the
41       application, which can be customized with "paths" in
42       Mojolicious::Renderer, or one of the the "DATA" sections from "classes"
43       in Mojolicious::Renderer.
44
45         __DATA__
46
47         @@ time.html.ep
48         % use Time::Piece;
49         % my $now = localtime;
50         <!DOCTYPE html>
51         <html>
52           <head><title>Time</title></head>
53           <body>The time is <%= $now->hms %>.</body>
54         </html>
55
56         @@ hello.txt.ep
57         ...
58
59       The renderer can be easily extended to support additional template
60       systems with plugins, but more about that later.
61
62   Embedded Perl
63       Mojolicious includes a minimalistic but very powerful template system
64       out of the box called Embedded Perl or "ep" for short. It is based on
65       Mojo::Template and allows the embedding of Perl code right into actual
66       content using a small set of special tags and line start characters.
67       For all templates strict, warnings, utf8 and Perl 5.16 features are
68       automatically enabled.
69
70         <% Perl code %>
71         <%= Perl expression, replaced with XML escaped result %>
72         <%== Perl expression, replaced with result %>
73         <%# Comment, useful for debugging %>
74         <%% Replaced with "<%", useful for generating templates %>
75         % Perl code line, treated as "<% line =%>" (explained later)
76         %= Perl expression line, treated as "<%= line %>"
77         %== Perl expression line, treated as "<%== line %>"
78         %# Comment line, useful for debugging
79         %% Replaced with "%", useful for generating templates
80
81       Tags and lines work pretty much the same, but depending on context one
82       will usually look a bit better. Semicolons get automatically appended
83       to all expressions.
84
85         <% my $i = 10; %>
86         <ul>
87           <% for my $j (1 .. $i) { %>
88             <li>
89               <%= $j %>
90             </li>
91           <% } %>
92         </ul>
93
94         % my $i = 10;
95         <ul>
96           % for my $j (1 .. $i) {
97             <li>
98               %= $j
99             </li>
100           % }
101         </ul>
102
103       Aside from differences in whitespace handling, both examples generate
104       similar Perl code, a naive translation could look like this.
105
106         my $output = '';
107         my $i = 10;
108         $output .= '<ul>';
109         for my $j (1 .. $i) {
110           $output .= '<li>';
111           $output .= xml_escape scalar + $j;
112           $output .= '</li>';
113         }
114         $output .= '</ul>';
115         return $output;
116
117       An additional equal sign can be used to disable escaping of the
118       characters "<", ">", "&", "'" and """ in results from Perl expressions,
119       which is the default to prevent XSS attacks against your application.
120
121         <%= 'I ♥ Mojolicious!' %>
122         <%== '<p>I ♥ Mojolicious!</p>' %>
123
124       Only Mojo::ByteStream objects are excluded from automatic escaping.
125
126         <%= b('<p>I ♥ Mojolicious!</p>') %>
127
128       Whitespace characters around tags can be trimmed by adding an
129       additional equal sign to the end of a tag.
130
131         <% for (1 .. 3) { %>
132           <%= 'Trim all whitespace characters around this expression' =%>
133         <% } %>
134
135       Newline characters can be escaped with a backslash.
136
137         This is <%= 1 + 1 %> a\
138         single line
139
140       And a backslash in front of a newline character can be escaped with
141       another backslash.
142
143         This will <%= 1 + 1 %> result\\
144         in multiple\\
145         lines
146
147       A newline character gets appended automatically to every template,
148       unless the last character is a backslash. And empty lines at the end of
149       a template are ignored.
150
151         There is <%= 1 + 1 %> no newline at the end here\
152
153       At the beginning of the template, stash values that don't have invalid
154       characters in their name get automatically initialized as normal
155       variables, and the controller object as both $self and $c.
156
157         $c->stash(name => 'tester');
158
159         Hello <%= $name %> from <%= $c->tx->remote_address %>.
160
161       A prefix like "myapp.*" is commonly used for stash values that you
162       don't want to expose in templates.
163
164         $c->stash('myapp.name' => 'tester');
165
166       There are also many helper functions available, but more about that
167       later.
168
169         <%= dumper {foo => 'bar'} %>
170

BASICS

172       Most commonly used features every Mojolicious developer should know
173       about.
174
175   Automatic rendering
176       The renderer can be manually started by calling the method "render" in
177       Mojolicious::Controller, but that's usually not necessary, because it
178       will get automatically called if nothing has been rendered after the
179       router finished its work.  This also means you can have routes pointing
180       only to templates without actual actions.
181
182         $c->render;
183
184       There is one big difference though, by calling it manually you can make
185       sure that templates use the current controller object, and not the
186       default controller specified with the attribute "controller_class" in
187       Mojolicious.
188
189         $c->render_later;
190
191       You can also disable automatic rendering with the method "render_later"
192       in Mojolicious::Controller, which can be very useful to delay rendering
193       when a non-blocking operation has to be performed first.
194
195   Rendering templates
196       The renderer will always try to detect the right template, but you can
197       also use the "template" stash value to render a specific one.
198       Everything before the last slash will be interpreted as the
199       subdirectory path in which to find the template.
200
201         # foo/bar/baz.*.*
202         $c->render(template => 'foo/bar/baz');
203
204       Choosing a specific "format" and "handler" is just as easy.
205
206         # foo/bar/baz.txt.epl
207         $c->render(template => 'foo/bar/baz', format => 'txt', handler => 'epl');
208
209       Because rendering a specific template is the most common task it also
210       has a shortcut.
211
212         $c->render('foo/bar/baz');
213
214       If you're not sure in advance if a template actually exists, you can
215       also use the method "render_maybe" in Mojolicious::Controller to try
216       multiple alternatives.
217
218         $c->render_maybe('localized/baz') or $c->render('foo/bar/baz');
219
220   Rendering to strings
221       Sometimes you might want to use the rendered result directly instead of
222       generating a response, for example, to send emails, this can be done
223       with "render_to_string" in Mojolicious::Controller.
224
225         my $html = $c->render_to_string('mail');
226
227       No encoding will be performed, making it easy to reuse the result in
228       other templates or to generate binary data.
229
230         my $pdf = $c->render_to_string('invoice', format => 'pdf');
231         $c->render(data => $pdf, format => 'pdf');
232
233       All arguments passed will get localized automatically and are only
234       available during this render operation.
235
236   Template variants
237       To make your application look great on many different devices you can
238       also use the "variant" stash value to choose between different variants
239       of your templates.
240
241         # foo/bar/baz.html+phone.ep
242         # foo/bar/baz.html.ep
243         $c->render('foo/bar/baz', variant => 'phone');
244
245       This can be done very liberally since it only applies when a template
246       with the correct name actually exists and falls back to the generic one
247       otherwise.
248
249   Rendering inline templates
250       Some renderers such as "ep" allow templates to be passed "inline".
251
252         $c->render(inline => 'The result is <%= 1 + 1 %>.');
253
254       Since auto-detection depends on a path you might have to supply a
255       "handler" too.
256
257         $c->render(inline => "<%= shift->param('foo') %>", handler => 'epl');
258
259   Rendering text
260       Characters can be rendered to bytes with the "text" stash value, the
261       given content will be automatically encoded with "encoding" in
262       Mojolicious::Renderer.
263
264         $c->render(text => 'I ♥ Mojolicious!');
265
266   Rendering data
267       Bytes can be rendered with the "data" stash value, no encoding will be
268       performed.
269
270         $c->render(data => $bytes);
271
272   Rendering JSON
273       The "json" stash value allows you to pass Perl data structures to the
274       renderer which get directly encoded to JSON with Mojo::JSON.
275
276         $c->render(json => {foo => [1, 'test', 3]});
277
278   Status code
279       Response status codes can be changed with the "status" stash value.
280
281         $c->render(text => 'Oops.', status => 500);
282
283   Content type
284       The "Content-Type" header of the response is actually based on the MIME
285       type mapping of the "format" stash value.
286
287         # Content-Type: text/plain
288         $c->render(text => 'Hello.', format => 'txt');
289
290         # Content-Type: image/png
291         $c->render(data => $bytes, format => 'png');
292
293       These mappings can be easily extended or changed with "types" in
294       Mojolicious.
295
296         # Add new MIME type
297         $app->types->type(md => 'text/markdown');
298
299   Stash data
300       Any of the native Perl data types can be passed to templates as
301       references through the "stash" in Mojolicious::Controller.
302
303         $c->stash(description => 'web framework');
304         $c->stash(frameworks  => ['Catalyst', 'Mojolicious', 'mojo.js']);
305         $c->stash(spinoffs    => {minion => 'job queue'});
306
307         %= $description
308         %= $frameworks->[1]
309         %= $spinoffs->{minion}
310
311       Since everything is just Perl normal control structures just work.
312
313         % for my $framework (@$frameworks) {
314           <%= $framework %> is a <%= $description %>.
315         % }
316
317         % if (my $description = $spinoffs->{minion}) {
318           Minion is a <%= $description %>.
319         % }
320
321       For templates that might get rendered in different ways and where
322       you're not sure if a stash value will actually be set, you can just use
323       the helper "stash" in Mojolicious::Plugin::DefaultHelpers.
324
325         % if (my $spinoffs = stash 'spinoffs') {
326           Minion is a <%= $spinoffs->{minion} %>.
327         % }
328
329   Helpers
330       Helpers are little functions you can use in templates as well as
331       application and controller code.
332
333         # Template
334         %= dumper [1, 2, 3]
335
336         # Application
337         my $serialized = $app->dumper([1, 2, 3]);
338
339         # Controller
340         my $serialized = $c->dumper([1, 2, 3]);
341
342       We differentiate between default helpers, which are more general
343       purpose like "dumper" in Mojolicious::Plugin::DefaultHelpers, and tag
344       helpers like "link_to" in Mojolicious::Plugin::TagHelpers, which are
345       template specific and mostly used to generate HTML tags.
346
347         %= link_to Mojolicious => 'https://mojolicious.org'
348
349       In controllers you can also use the method "helpers" in
350       Mojolicious::Controller to fully qualify helper calls and ensure that
351       they don't conflict with existing methods you may already have.
352
353         my $serialized = $c->helpers->dumper([1, 2, 3]);
354
355       A list of all built-in helpers can be found in
356       Mojolicious::Plugin::DefaultHelpers and
357       Mojolicious::Plugin::TagHelpers.
358
359   Static files
360       Static files are automatically served from the "public" directories of
361       the application, which can be customized with "paths" in
362       Mojolicious::Static, or one of the "DATA" sections from "classes" in
363       Mojolicious::Static. And if that's not enough you can also serve them
364       manually with "reply->static" in Mojolicious::Plugin::DefaultHelpers
365       and "reply->file" in Mojolicious::Plugin::DefaultHelpers.
366
367         use Mojolicious::Lite -signatures;
368
369         get '/' => sub ($c) {
370           $c->reply->static('index.html');
371         };
372
373         get '/some_download' => sub ($c) {
374           $c->res->headers->content_disposition('attachment; filename=bar.png;');
375           $c->reply->static('foo/bar.png');
376         };
377
378         get '/leak' => sub ($c) {
379           $c->reply->file('/etc/passwd');
380         };
381
382         app->start;
383
384       By default static files do not use a prefix and are simply served with
385       a higher precedence than routes. This can be changed with "prefix" in
386       Mojolicious::Static.
387
388         # Serve static files only with a "/static" prefix
389         $app->static->prefix('/static');
390
391       To allow for the prefix to be configured dynamically, you can use
392       "url_for_file" in Mojolicious::Controller to generate URLs with it.
393       Many tag helpers will also use the prefix automatically when it makes
394       sense.
395
396   Static assets
397       While Mojolicious does not have any special support for frontend
398       frameworks like Vue.js <https://vuejs.org> and React
399       <https://reactjs.org>, the "public/assets" directory is reserved for
400       static assets created by bundlers like Webpack <https://webpack.js.org>
401       and Rollup.js <https://rollupjs.org> ahead of time. Asset files can be
402       of any type, they just have to follow the
403       "[name].[checksum].[extensions]" naming scheme, like
404       "myapp.ab1234cd5678ef.js". You can then use "url_for_asset" in
405       Mojolicious::Controller or "asset_tag" in
406       Mojolicious::Plugin::TagHelpers to generate URLs without having to know
407       the checksum.
408
409         # "/assets/myapp.ab1234cd5678ef.js"
410         $c->url_for_asset('/myapp.js');
411
412         # "<script src="/assets/myapp.ab1234cd5678ef.js"></script>"
413         $c->asset_tag('/myapp.js');
414
415       If your application runs in "development" mode, all assets will be
416       served with a "Cache-Control: no-cache" header, to speed up development
417       by preventing browser caching. Additionally all assets following the
418       "[name].development.[extensions]" naming scheme, like
419       "myapp.development.js", have a higher precedence than assets with
420       checksums. That way you can just overwrite your assets during
421       development, instead of having to manually delete them each time they
422       are rebuilt with a different checksum.
423
424         # "/assets/foo/bar.development.js"
425         $c->url_for_asset('/foo/bar.js');
426
427       Webpack configuration <https://webpack.js.org/configuration/> example
428       ("webpack.config.js"):
429
430         import Path from '@mojojs/path';
431
432         const isDev = process.env.MOJO_MODE === 'development';
433
434         export default {
435           output: {
436             filename: isDev ? '[name].development.js' : '[name].[chunkhash].js',
437             path: Path.currentFile().sibling('public', 'assets').toString(),
438             publicPath: ''
439           },
440
441           // Add your own rules and entry point here
442         };
443
444       Rollup configuration <https://rollupjs.org/guide/en/#configuration-
445       files> example ("rollup.config.js"):
446
447         import Path from '@mojojs/path';
448
449         const isDev = process.env.MOJO_MODE === 'development';
450
451         export default {
452           output: {
453             entryFileNames: isDev ? '[name].development.[ext]' : '[name].[hash].[ext]',
454             dir: Path.currentFile().sibling('public', 'assets').toString(),
455             format: 'iife'
456           },
457
458           // Add your own rules and entry point here
459         };
460
461       Everything else is up to your bundler of choice, so you need to consult
462       its documentation for further information. And where you keep your
463       asset sources, such as ".vue" and ".jsx" files, is not important, as
464       long as your bundler can find them. Using a directory named "assets" or
465       "frontend" in your application root directory is a good best practice
466       though.
467
468   Content negotiation
469       For resources with different representations and that require truly
470       RESTful content negotiation you can also use "respond_to" in
471       Mojolicious::Plugin::DefaultHelpers instead of "render" in
472       Mojolicious::Controller.
473
474         # /hello (Accept: application/json) -> "json"
475         # /hello (Accept: application/xml)  -> "xml"
476         # /hello.json                       -> "json"
477         # /hello.xml                        -> "xml"
478         # /hello?_format=json               -> "json"
479         # /hello?_format=xml                -> "xml"
480         $c->respond_to(
481           json => {json => {hello => 'world'}},
482           xml  => {text => '<hello>world</hello>'}
483         );
484
485       The best possible representation will be automatically selected from
486       the "_format" "GET"/"POST" parameter, "format" stash value or "Accept"
487       request header and stored in the "format" stash value. To change MIME
488       type mappings for the "Accept" request header or the "Content-Type"
489       response header you can use "types" in Mojolicious.
490
491         $c->respond_to(
492           json => {json => {hello => 'world'}},
493           html => sub {
494             $c->content_for(head => '<meta name="author" content="sri">');
495             $c->render(template => 'hello', message => 'world')
496           }
497         );
498
499       Callbacks can be used for representations that are too complex to fit
500       into a single render call.
501
502         # /hello (Accept: application/json) -> "json"
503         # /hello (Accept: text/html)        -> "html"
504         # /hello (Accept: image/png)        -> "any"
505         # /hello.json                       -> "json"
506         # /hello.html                       -> "html"
507         # /hello.png                        -> "any"
508         # /hello?_format=json                -> "json"
509         # /hello?_format=html                -> "html"
510         # /hello?_format=png                 -> "any"
511         $c->respond_to(
512           json => {json => {hello => 'world'}},
513           html => {template => 'hello', message => 'world'},
514           any  => {text => '', status => 204}
515         );
516
517       And if no viable representation could be found, the "any" fallback will
518       be used or an empty 204 response rendered automatically.
519
520         # /hello                      -> "html"
521         # /hello (Accept: text/html)  -> "html"
522         # /hello (Accept: text/xml)   -> "xml"
523         # /hello (Accept: text/plain) -> undef
524         # /hello.html                 -> "html"
525         # /hello.xml                  -> "xml"
526         # /hello.txt                  -> undef
527         # /hello?_format=html          -> "html"
528         # /hello?_format=xml           -> "xml"
529         # /hello?_format=txt           -> undef
530         if (my $format = $c->accepts('html', 'xml')) {
531           ...
532         }
533
534       For even more advanced negotiation logic you can also use the helper
535       "accepts" in Mojolicious::Plugin::DefaultHelpers.
536
537   Rendering "exception" and "not_found" pages
538       By now you've probably already encountered the built-in 404 (Not Found)
539       and 500 (Server Error) pages, that get rendered automatically when you
540       make a mistake. Those are fallbacks for when your own exception
541       handling fails, which can be especially helpful during development. You
542       can also render them manually with the helpers "reply->exception" in
543       Mojolicious::Plugin::DefaultHelpers and "reply->not_found" in
544       Mojolicious::Plugin::DefaultHelpers.
545
546         use Mojolicious::Lite -signatures;
547         use Scalar::Util qw(looks_like_number);
548
549         get '/divide/:dividend/by/:divisor' => sub ($c) {
550
551           my $dividend = $c->param('dividend');
552           my $divisor  = $c->param('divisor');
553
554           # 404
555           return $c->reply->not_found unless looks_like_number $dividend && looks_like_number $divisor;
556
557           # 500
558           return $c->reply->exception('Division by zero!') if $divisor == 0;
559
560           # 200
561           $c->render(text => $dividend / $divisor);
562         };
563
564         app->start;
565
566       To change the HTTP status code of the exception, you can use "rendered"
567       in Mojolicious::Controller.
568
569         return $c->reply->exception('Division by zero!')->rendered(400) if $divisor == 0;
570
571       You can also change the templates of those pages, since you most likely
572       want to show your users something more closely related to your
573       application in production. The renderer will always try to find
574       "exception.$mode.$format.*" or "not_found.$mode.$format.*" before
575       falling back to the built-in default templates.
576
577         use Mojolicious::Lite;
578
579         get '/dies' => sub { die 'Intentional error' };
580
581         app->start;
582         __DATA__
583
584         @@ exception.production.html.ep
585         <!DOCTYPE html>
586         <html>
587           <head><title>Server error</title></head>
588           <body>
589             <h1>Exception</h1>
590             <p><%= $exception->message %></p>
591             <h1>Stash</h1>
592             <pre><%= dumper $snapshot %></pre>
593           </body>
594         </html>
595
596       The default exception format is "html", but that can be changed at
597       application and controller level. By default there are handlers for
598       "html", "txt" and "json" available. There are also various exception
599       helpers in Mojolicious::Plugin::DefaultHelpers for you to overload to
600       change the default behavior.
601
602         use Mojolicious::Lite -signatures;
603
604         app->exception_format('json');
605
606         get '/json' => sub ($c) {
607           die 'Just a test';
608         };
609
610         get '/txt' => sub ($c) {
611           $c->exception_format('txt');
612           die 'Just a test';
613         };
614
615         app->start;
616
617       The hook "before_render" in Mojolicious makes even more advanced
618       customizations possible by allowing you to intercept and modify the
619       arguments passed to the renderer.
620
621         use Mojolicious::Lite -signatures;
622
623         hook before_render => sub ($c, $args) {
624
625           # Make sure we are rendering the exception template
626           return unless my $template = $args->{template};
627           return unless $template eq 'exception';
628
629           # Switch to JSON rendering if content negotiation allows it
630           return unless $c->accepts('json');
631           $args->{json} = {exception => $c->stash('exception')};
632         };
633
634         get '/' => sub { die "This sho...ALL GLORY TO THE HYPNOTOAD!\n" };
635
636         app->start;
637
638   Layouts
639       Most of the time when using "ep" templates you will want to wrap your
640       generated content in an HTML skeleton, thanks to layouts that's
641       absolutely trivial.
642
643         use Mojolicious::Lite;
644
645         get '/' => {template => 'foo/bar'};
646
647         app->start;
648         __DATA__
649
650         @@ foo/bar.html.ep
651         % layout 'mylayout';
652         Hello World!
653
654         @@ layouts/mylayout.html.ep
655         <!DOCTYPE html>
656         <html>
657           <head><title>MyApp</title></head>
658           <body><%= content %></body>
659         </html>
660
661       You just select the right layout template with the helper "layout" in
662       Mojolicious::Plugin::DefaultHelpers and place the result of the current
663       template with the helper "content" in
664       Mojolicious::Plugin::DefaultHelpers. You can also pass along normal
665       stash values to the "layout" helper.
666
667         use Mojolicious::Lite;
668
669         get '/' => {template => 'foo/bar'};
670
671         app->start;
672         __DATA__
673
674         @@ foo/bar.html.ep
675         % layout 'mylayout', title => 'Hi there';
676         Hello World!
677
678         @@ layouts/mylayout.html.ep
679         <!DOCTYPE html>
680         <html>
681           <head><title><%= $title %></title></head>
682           <body><%= content %></body>
683         </html>
684
685       Instead of the "layout" helper you could also just use the "layout"
686       stash value, or call "render" in Mojolicious::Controller with the
687       "layout" argument.
688
689         $c->render(template => 'mytemplate', layout => 'mylayout');
690
691       To set a "layout" stash value application-wide you can use "defaults"
692       in Mojolicious.
693
694         $app->defaults(layout => 'mylayout');
695
696       Layouts can also be used with "render_to_string" in
697       Mojolicious::Controller, but the "layout" value needs to be passed as a
698       render argument (not a stash value).
699
700         my $html = $c->render_to_string('reminder', layout => 'mail');
701
702   Partial templates
703       You can break up bigger templates into smaller, more manageable chunks.
704       These partial templates can also be shared with other templates. Just
705       use the helper "include" in Mojolicious::Plugin::DefaultHelpers to
706       include one template into another.
707
708         use Mojolicious::Lite;
709
710         get '/' => {template => 'foo/bar'};
711
712         app->start;
713         __DATA__
714
715         @@ foo/bar.html.ep
716         <!DOCTYPE html>
717         <html>
718           %= include '_header', title => 'Howdy'
719           <body>Bar</body>
720         </html>
721
722         @@ _header.html.ep
723         <head><title><%= $title %></title></head>
724
725       You can name partial templates however you like, but a leading
726       underscore is a commonly used naming convention.
727
728   Reusable template blocks
729       It's never fun to repeat yourself, that's why you can build reusable
730       template blocks in "ep" that work very similar to normal Perl
731       functions, with the "begin" and "end" keywords. Just be aware that both
732       keywords are part of the surrounding tag and not actual Perl code, so
733       there can only be whitespace after "begin" and before "end".
734
735         use Mojolicious::Lite;
736
737         get '/' => 'welcome';
738
739         app->start;
740         __DATA__
741
742         @@ welcome.html.ep
743         <% my $block = begin %>
744           % my $name = shift;
745           Hello <%= $name %>.
746         <% end %>
747         <%= $block->('Wolfgang') %>
748         <%= $block->('Baerbel') %>
749
750       A naive translation of the template to Perl code could look like this.
751
752         my $output = '';
753         my $block  = sub ($name) {
754           my $output = '';
755           $output .= 'Hello ';
756           $output .= xml_escape scalar + $name;
757           $output .= '.';
758           return Mojo::ByteStream->new($output);
759         };
760         $output .= xml_escape scalar + $block->('Wolfgang');
761         $output .= xml_escape scalar + $block->('Baerbel');
762         return $output;
763
764       While template blocks cannot be shared between templates, they are most
765       commonly used to pass parts of a template to helpers.
766
767   Adding helpers
768       You should always try to keep your actions small and reuse as much code
769       as possible. Helpers make this very easy, they get passed the current
770       controller object as first argument, and you can use them to do pretty
771       much anything an action could do.
772
773         use Mojolicious::Lite -signatures;
774
775         helper debug => sub ($c, $str) {
776           $c->app->log->debug($str);
777         };
778
779         get '/' => sub ($c) {
780           $c->debug('Hello from an action!');
781         } => 'index';
782
783         app->start;
784         __DATA__
785
786         @@ index.html.ep
787         % debug 'Hello from a template!';
788
789       Helpers can also accept template blocks as last argument, this for
790       example, allows very pleasant to use tag helpers and filters. Wrapping
791       the helper result into a Mojo::ByteStream object can prevent accidental
792       double escaping.
793
794         use Mojolicious::Lite -signatures;
795         use Mojo::ByteStream;
796
797         helper trim_newline => sub ($c, $block) {
798           my $result = $block->();
799           $result =~ s/\n//g;
800           return Mojo::ByteStream->new($result);
801         };
802
803         get '/' => 'index';
804
805         app->start;
806         __DATA__
807
808         @@ index.html.ep
809         %= trim_newline begin
810           Some text.
811           %= 1 + 1
812           More text.
813         % end
814
815       Similar to stash values, you can use a prefix like "myapp.*" to keep
816       helpers from getting exposed in templates as functions, and to organize
817       them into namespaces as your application grows. Every prefix
818       automatically becomes a helper that returns a proxy object containing
819       the current controller object and on which you can call the nested
820       helpers.
821
822         use Mojolicious::Lite -signatures;
823
824         helper 'cache_control.no_caching'   => sub ($c) { $c->res->headers->cache_control('private, max-age=0, no-cache') };
825         helper 'cache_control.five_minutes' => sub ($c) { $c->res->headers->cache_control('public, max-age=300') };
826
827         get '/news' => sub ($c) {
828           $c->cache_control->no_caching;
829           $c->render(text => 'Always up to date.');
830         };
831
832         get '/some_older_story' => sub ($c) {
833           $c->cache_control->five_minutes;
834           $c->render(text => 'This one can be cached for a bit.');
835         };
836
837         app->start;
838
839       While helpers can also be redefined, this should only be done very
840       carefully to avoid conflicts.
841
842   Content blocks
843       The helper "content_for" in Mojolicious::Plugin::DefaultHelpers allows
844       you to pass whole blocks of content from one template to another. This
845       can be very useful when your layout has distinct sections, such as
846       sidebars, where content should be inserted by the template.
847
848         use Mojolicious::Lite;
849
850         get '/' => 'foo';
851
852         app->start;
853         __DATA__
854
855         @@ foo.html.ep
856         % layout 'mylayout';
857         % content_for header => begin
858           <meta http-equiv="Content-Type" content="text/html">
859         % end
860         <div>Hello World!</div>
861         % content_for header => begin
862           <meta http-equiv="Pragma" content="no-cache">
863         % end
864
865         @@ layouts/mylayout.html.ep
866         <!DOCTYPE html>
867         <html>
868           <head><%= content 'header' %></head>
869           <body><%= content %></body>
870         </html>
871
872   Forms
873       To build HTML forms more efficiently you can use tag helpers like
874       "form_for" in Mojolicious::Plugin::TagHelpers, which can automatically
875       select a request method for you if a route name is provided. And since
876       most browsers only allow forms to be submitted with "GET" and "POST",
877       but not request methods like "PUT" or "DELETE", they are spoofed with
878       an "_method" query parameter.
879
880         use Mojolicious::Lite -signatures;
881
882         get '/' => 'form';
883
884         # PUT  /nothing
885         # POST /nothing?_method=PUT
886         put '/nothing' => sub ($c) {
887
888           # Prevent double form submission with redirect
889           my $value = $c->param('whatever');
890           $c->flash(confirmation => "We did nothing with your value ($value).");
891           $c->redirect_to('form');
892         };
893
894         app->start;
895         __DATA__
896
897         @@ form.html.ep
898         <!DOCTYPE html>
899         <html>
900           <body>
901             % if (my $confirmation = flash 'confirmation') {
902               <p><%= $confirmation %></p>
903             % }
904             %= form_for nothing => begin
905               %= text_field whatever => 'I ♥ Mojolicious!'
906               %= submit_button
907             % end
908           </body>
909         </html>
910
911       The helpers "flash" in Mojolicious::Plugin::DefaultHelpers and
912       "redirect_to" in Mojolicious::Plugin::DefaultHelpers are often used
913       together to prevent double form submission, allowing users to receive a
914       confirmation message that will vanish if they decide to reload the page
915       they've been redirected to.
916
917   Form validation
918       You can use "validation" in Mojolicious::Plugin::DefaultHelpers to
919       validate "GET" and "POST" parameters submitted to your application. All
920       unknown fields will be ignored by default, so you have to decide which
921       should be required or optional before you can perform checks on their
922       values. Every check is performed right away, so you can use the results
923       immediately to build more advanced validation logic with methods like
924       "is_valid" in Mojolicious::Validator::Validation.
925
926         use Mojolicious::Lite -signatures;
927
928         get '/' => sub ($c) {
929
930           # Check if parameters have been submitted
931           my $v = $c->validation;
932           return $c->render('index') unless $v->has_data;
933
934           # Validate parameters ("pass_again" depends on "pass")
935           $v->required('user')->size(1, 20)->like(qr/^[a-z0-9]+$/);
936           $v->required('pass_again')->equal_to('pass') if $v->optional('pass')->size(7, 500)->is_valid;
937
938           # Check if validation failed
939           return $c->render('index') if $v->has_error;
940
941           # Render confirmation
942           $c->render('thanks');
943         };
944
945         app->start;
946         __DATA__
947
948         @@ index.html.ep
949         <!DOCTYPE html>
950         <html>
951           <head>
952             <style>
953               label.field-with-error { color: #dd7e5e }
954               input.field-with-error { background-color: #fd9e7e }
955             </style>
956           </head>
957           <body>
958             %= form_for index => begin
959               %= label_for user => 'Username (required, 1-20 characters, a-z/0-9)'
960               <br>
961               %= text_field 'user', id => 'user'
962               %= submit_button
963               <br>
964               %= label_for pass => 'Password (optional, 7-500 characters)'
965               <br>
966               %= password_field 'pass', id => 'pass'
967               <br>
968               %= label_for pass_again => 'Password again (equal to the value above)'
969               <br>
970               %= password_field 'pass_again', id => 'pass_again'
971             % end
972           </body>
973         </html>
974
975         @@ thanks.html.ep
976         <!DOCTYPE html>
977         <html><body>Thank you <%= validation->param('user') %>.</body></html>
978
979       Form elements generated with tag helpers from
980       Mojolicious::Plugin::TagHelpers will automatically remember their
981       previous values and add the class "field-with-error" for fields that
982       failed validation to make styling with CSS easier.
983
984         <label class="field-with-error" for="user">
985           Username (required, only characters e-t)
986         </label>
987         <input class="field-with-error" type="text" name="user" value="sri">
988
989       For a full list of available checks see also "CHECKS" in
990       Mojolicious::Validator.
991
992   Adding form validation checks
993       Validation checks can be registered with "add_check" in
994       Mojolicious::Validator and return a false value if they were
995       successful. A true value may be used to pass along additional
996       information which can then be retrieved with "error" in
997       Mojolicious::Validator::Validation.
998
999         use Mojolicious::Lite -signatures;
1000
1001         # Add "range" check
1002         app->validator->add_check(range => sub ($v, $name, $value, $min, $max) {
1003           return $value < $min || $value > $max;
1004         });
1005
1006         get '/' => 'form';
1007
1008         post '/test' => sub ($c) {
1009
1010           # Validate parameters with custom check
1011           my $v = $c->validation;
1012           $v->required('number')->range(3, 23);
1013
1014           # Render form again if validation failed
1015           return $c->render('form') if $v->has_error;
1016
1017           # Prevent double form submission with redirect
1018           $c->flash(number => $v->param('number'));
1019           $c->redirect_to('form');
1020         };
1021
1022         app->start;
1023         __DATA__
1024
1025         @@ form.html.ep
1026         <!DOCTYPE html>
1027         <html>
1028           <body>
1029             % if (my $number = flash 'number') {
1030               <p>Thanks, the number <%= $number %> was valid.</p>
1031             % }
1032             %= form_for test => begin
1033               % if (my $err = validation->error('number')) {
1034                 <p>
1035                   %= 'Value is required.' if $err->[0] eq 'required'
1036                   %= 'Value needs to be between 3 and 23.' if $err->[0] eq 'range'
1037                 </p>
1038               % }
1039               %= text_field 'number'
1040               %= submit_button
1041             % end
1042           </body>
1043         </html>
1044
1045   Cross-site request forgery
1046       CSRF is a very common attack on web applications that trick your logged
1047       in users to submit forms they did not intend to send, with something as
1048       mundane as a link. All you have to do, to protect your users from this,
1049       is to add an additional hidden field to your forms with "csrf_field" in
1050       Mojolicious::Plugin::TagHelpers, and validate it with "csrf_protect" in
1051       Mojolicious::Validator::Validation.
1052
1053         use Mojolicious::Lite -signatures;
1054
1055         get '/' => {template => 'target'};
1056
1057         post '/' => sub ($c) {
1058
1059           # Check CSRF token
1060           my $v = $c->validation;
1061           return $c->render(text => 'Bad CSRF token!', status => 403) if $v->csrf_protect->has_error('csrf_token');
1062
1063           my $city = $v->required('city')->param('city');
1064           $c->render(text => "Low orbit ion cannon pointed at $city!") unless $v->has_error;
1065         } => 'target';
1066
1067         app->start;
1068         __DATA__
1069
1070         @@ target.html.ep
1071         <!DOCTYPE html>
1072         <html>
1073           <body>
1074             %= form_for target => begin
1075               %= csrf_field
1076               %= label_for city => 'Which city to point low orbit ion cannon at?'
1077               %= text_field 'city', id => 'city'
1078               %= submit_button
1079             %= end
1080           </body>
1081         </html>
1082
1083       For Ajax requests and the like, you can also generate a token directly
1084       with the helper "csrf_token" in Mojolicious::Plugin::DefaultHelpers,
1085       and then pass it along with the "X-CSRF-Token" request header.
1086

ADVANCED

1088       Less commonly used and more powerful features.
1089
1090   Template inheritance
1091       Inheritance takes the layout concept above one step further, the
1092       helpers "content" in Mojolicious::Plugin::DefaultHelpers and "extends"
1093       in Mojolicious::Plugin::DefaultHelpers allow you to build skeleton
1094       templates with named blocks that child templates can override.
1095
1096         use Mojolicious::Lite;
1097
1098         # first > mylayout
1099         get '/first' => {template => 'first', layout => 'mylayout'};
1100
1101         # third > second > first > mylayout
1102         get '/third' => {template => 'third', layout => 'mylayout'};
1103
1104         app->start;
1105         __DATA__
1106
1107         @@ layouts/mylayout.html.ep
1108         <!DOCTYPE html>
1109         <html>
1110           <head><title>Hello</title></head>
1111           <body><%= content %></body>
1112         </html>
1113
1114         @@ first.html.ep
1115         %= content header => begin
1116           Default header
1117         % end
1118         <div>Hello World!</div>
1119         %= content footer => begin
1120           Default footer
1121         % end
1122
1123         @@ second.html.ep
1124         % extends 'first';
1125         % content header => begin
1126           New header
1127         % end
1128
1129         @@ third.html.ep
1130         % extends 'second';
1131         % content footer => begin
1132           New footer
1133         % end
1134
1135       This chain could go on and on to allow a very high level of template
1136       reuse.
1137
1138   Custom responses
1139       Most response content, static as well as dynamic, gets served through
1140       Mojo::Asset::File and Mojo::Asset::Memory objects. For somewhat static
1141       content, like cached JSON data or temporary files, you can create your
1142       own and use the helper "reply->asset" in
1143       Mojolicious::Plugin::DefaultHelpers to serve them while allowing
1144       content negotiation to be performed with "Range", "If-Modified-Since"
1145       and "If-None-Match" headers.
1146
1147         use Mojolicious::Lite -signatures;
1148         use Mojo::Asset::File;
1149
1150         get '/leak' => sub ($c) {
1151           $c->res->headers->content_type('text/plain');
1152           $c->reply->asset(Mojo::Asset::File->new(path => '/etc/passwd'));
1153         };
1154
1155         app->start;
1156
1157       For even more control you can also just skip the helper and use
1158       "rendered" in Mojolicious::Controller to tell the renderer when you're
1159       done generating a response.
1160
1161         use Mojolicious::Lite -signatures;
1162         use Mojo::Asset::File;
1163
1164         get '/leak' => sub ($c) {
1165           $c->res->headers->content_type('text/plain');
1166           $c->res->content->asset(Mojo::Asset::File->new(path => '/etc/passwd'));
1167           $c->rendered(200);
1168         };
1169
1170         app->start;
1171
1172   Helper plugins
1173       Some helpers might be useful enough for you to share them between
1174       multiple applications, plugins make that very simple.
1175
1176         package Mojolicious::Plugin::DebugHelper;
1177         use Mojo::Base 'Mojolicious::Plugin', -signatures;
1178
1179         sub register ($self, $app, $conf) {
1180           $app->helper(debug => sub ($c, $str) {
1181             $c->app->log->debug($str);
1182           });
1183         }
1184
1185         1;
1186
1187       The "register" method will be called when you load the plugin. And to
1188       add your helper to the application, you can use "helper" in
1189       Mojolicious.
1190
1191         use Mojolicious::Lite -signatures;
1192
1193         plugin 'DebugHelper';
1194
1195         get '/' => sub ($c) {
1196           $c->debug('It works!');
1197           $c->render(text => 'Hello!');
1198         };
1199
1200         app->start;
1201
1202       A skeleton for a full CPAN compatible plugin distribution can be
1203       automatically generated.
1204
1205         $ mojo generate plugin DebugHelper
1206
1207       And if you have a "PAUSE" account (which can be requested at
1208       <http://pause.perl.org>), you are only a few commands away from
1209       releasing it to CPAN.
1210
1211         $ perl Makefile.PL
1212         $ make test
1213         $ make manifest
1214         $ make dist
1215         $ mojo cpanify -u USER -p PASS Mojolicious-Plugin-DebugHelper-0.01.tar.gz
1216
1217   Bundling assets with plugins
1218       Assets such as templates and static files can be easily bundled with
1219       your plugins, even if you plan to release them to CPAN.
1220
1221         $ mojo generate plugin AlertAssets
1222         $ mkdir Mojolicious-Plugin-AlertAssets/lib/Mojolicious/Plugin/AlertAssets
1223         $ cd Mojolicious-Plugin-AlertAssets/lib/Mojolicious/Plugin/AlertAssets
1224         $ mkdir public
1225         $ echo 'alert("Hello World!");' > public/alertassets.js
1226         $ mkdir templates
1227         $ echo '%= javascript "/alertassets.js"' > templates/alertassets.html.ep
1228
1229       Just give them reasonably unique names, ideally based on the name of
1230       your plugin, and append their respective directories to the list of
1231       search paths when "register" is called.
1232
1233         package Mojolicious::Plugin::AlertAssets;
1234         use Mojo::Base 'Mojolicious::Plugin', -signatures;
1235
1236         use Mojo::File qw(curfile);
1237
1238         sub register ($self, $app, $conf) {
1239
1240           # Append "templates" and "public" directories
1241           my $base = curfile->sibling('AlertAssets');
1242           push @{$app->renderer->paths}, $base->child('templates')->to_string;
1243           push @{$app->static->paths},   $base->child('public')->to_string;
1244         }
1245
1246         1;
1247
1248       Both will work just like normal "templates" and "public" directories
1249       once you've installed and loaded the plugin, with slightly lower
1250       precedence.
1251
1252         use Mojolicious::Lite;
1253
1254         plugin 'AlertAssets';
1255
1256         get '/alert_me';
1257
1258         app->start;
1259         __DATA__
1260
1261         @@ alert_me.html.ep
1262         <!DOCTYPE html>
1263         <html>
1264           <head>
1265             <title>Alert me!</title>
1266             %= include 'alertassets'
1267           </head>
1268           <body>You've been alerted.</body>
1269         </html>
1270
1271       And it works just the same for assets bundled in the "DATA" section of
1272       your plugin.
1273
1274         package Mojolicious::Plugin::AlertAssets;
1275         use Mojo::Base 'Mojolicious::Plugin', -signatures;
1276
1277         sub register ($self, $app, $conf) {
1278
1279           # Append class
1280           push @{$app->renderer->classes}, __PACKAGE__;
1281           push @{$app->static->classes},   __PACKAGE__;
1282         }
1283
1284         1;
1285         __DATA__
1286
1287         @@ alertassets.js
1288         alert("Hello World!");
1289
1290         @@ alertassets.html.ep
1291         %= javascript "/alertassets.js"
1292
1293   Post-processing dynamic content
1294       While post-processing tasks are generally very easy with the hook
1295       "after_dispatch" in Mojolicious, for content generated by the renderer
1296       it is a lot more efficient to use "after_render" in Mojolicious.
1297
1298         use Mojolicious::Lite -signatures;
1299         use IO::Compress::Gzip qw(gzip);
1300
1301         hook after_render => sub ($c, $output, $format) {
1302
1303           # Check if "gzip => 1" has been set in the stash
1304           return unless $c->stash->{gzip};
1305
1306           # Check if user agent accepts gzip compression
1307           return unless ($c->req->headers->accept_encoding // '') =~ /gzip/i;
1308           $c->res->headers->append(Vary => 'Accept-Encoding');
1309
1310           # Compress content with gzip
1311           $c->res->headers->content_encoding('gzip');
1312           gzip $output, \my $compressed;
1313           $$output = $compressed;
1314         };
1315
1316         get '/' => {template => 'hello', title => 'Hello', gzip => 1};
1317
1318         app->start;
1319         __DATA__
1320
1321         @@ hello.html.ep
1322         <!DOCTYPE html>
1323         <html>
1324           <head><title><%= title %></title></head>
1325           <body>Compressed content.</body>
1326         </html>
1327
1328       If you want to compress all dynamically generated content you can also
1329       activate "compress" in Mojolicious::Renderer.
1330
1331   Streaming
1332       You don't have to render all content at once, the method "write" in
1333       Mojolicious::Controller can also be used to stream a series of smaller
1334       chunks.
1335
1336         use Mojolicious::Lite -signatures;
1337
1338         get '/' => sub ($c) {
1339
1340           # Prepare body
1341           my $body = 'Hello World!';
1342           $c->res->headers->content_length(length $body);
1343
1344           # Start writing directly with a drain callback
1345           my $drain = sub ($c) {
1346             my $chunk = substr $body, 0, 1, '';
1347             $c->write($chunk, length $body ? __SUB__ : undef);
1348           };
1349           $c->$drain;
1350         };
1351
1352         app->start;
1353
1354       The drain callback will be executed whenever the entire previous chunk
1355       of data has actually been written.
1356
1357         HTTP/1.1 200 OK
1358         Date: Sat, 13 Sep 2014 16:48:29 GMT
1359         Content-Length: 12
1360         Server: Mojolicious (Perl)
1361
1362         Hello World!
1363
1364       Instead of providing a "Content-Length" header you can also call
1365       "finish" in Mojolicious::Controller and close the connection manually
1366       once you are done.
1367
1368         use Mojolicious::Lite -signatures;
1369
1370         get '/' => sub ($c) {
1371
1372           # Prepare body
1373           my $body = 'Hello World!';
1374
1375           # Start writing directly with a drain callback
1376           my $drain = sub ($c) {
1377             my $chunk = substr $body, 0, 1, '';
1378             length $chunk ? $c->write($chunk, __SUB__) : $c->finish;
1379           };
1380           $c->$drain;
1381         };
1382
1383         app->start;
1384
1385       While this is rather inefficient, as it prevents keep-alive, it is
1386       sometimes necessary for EventSource and similar applications.
1387
1388         HTTP/1.1 200 OK
1389         Date: Sat, 13 Sep 2014 16:48:29 GMT
1390         Connection: close
1391         Server: Mojolicious (Perl)
1392
1393         Hello World!
1394
1395   Chunked transfer encoding
1396       For very dynamic content you might not know the response content length
1397       in advance, that's where the chunked transfer encoding and
1398       "write_chunk" in Mojolicious::Controller come in handy. A common use
1399       would be to send the "head" section of an HTML document to the browser
1400       in advance and speed up preloading of referenced images and
1401       stylesheets.
1402
1403         use Mojolicious::Lite -signatures;
1404
1405         get '/' => sub ($c) {
1406           $c->write_chunk('<html><head><title>Example</title></head>' => sub ($c) {
1407             $c->finish('<body>Example</body></html>');
1408           });
1409         };
1410
1411         app->start;
1412
1413       The optional drain callback ensures that all previous chunks have been
1414       written before processing continues. To end the stream you can call
1415       "finish" in Mojolicious::Controller or write an empty chunk of data.
1416
1417         HTTP/1.1 200 OK
1418         Date: Sat, 13 Sep 2014 16:48:29 GMT
1419         Transfer-Encoding: chunked
1420         Server: Mojolicious (Perl)
1421
1422         29
1423         <html><head><title>Example</title></head>
1424         1b
1425         <body>Example</body></html>
1426         0
1427
1428       Especially in combination with long inactivity timeouts this can be
1429       very useful for Comet (long polling). Due to limitations in some web
1430       servers this might not work perfectly in all deployment environments.
1431
1432   Encoding
1433       Templates stored in files are expected to be "UTF-8" by default, but
1434       that can be easily changed with "encoding" in Mojolicious::Renderer.
1435
1436         $app->renderer->encoding('koi8-r');
1437
1438       All templates from the "DATA" section are bound to the encoding of the
1439       Perl script.
1440
1441         use Mojolicious::Lite;
1442
1443         get '/heart';
1444
1445         app->start;
1446         __DATA__
1447
1448         @@ heart.html.ep
1449         I ♥ Mojolicious!
1450
1451   Base64 encoded DATA files
1452       Base64 encoded static files such as images can be easily stored in the
1453       "DATA" section of your application, similar to templates.
1454
1455         use Mojolicious::Lite;
1456
1457         get '/' => {text => 'I ♥ Mojolicious!'};
1458
1459         app->start;
1460         __DATA__
1461
1462         @@ favicon.ico (base64)
1463         ...base64 encoded image...
1464
1465   Inflating DATA templates
1466       Templates stored in files get preferred over files from the "DATA"
1467       section, this allows you to include a default set of templates in your
1468       application that the user can later customize. The command
1469       Mojolicious::Command::Author::inflate will write all templates and
1470       static files from the "DATA" section into actual files in the
1471       "templates" and "public" directories.
1472
1473         $ ./myapp.pl inflate
1474
1475   Customizing the template syntax
1476       You can easily change the whole template syntax by loading
1477       Mojolicious::Plugin::EPRenderer with a custom configuration.
1478
1479         use Mojolicious::Lite;
1480
1481         plugin EPRenderer => {
1482           name     => 'mustache',
1483           template => {
1484             tag_start => '{{',
1485             tag_end   => '}}'
1486           }
1487         };
1488
1489         get '/:name' => {name => 'Anonymous'} => 'index';
1490
1491         app->start;
1492         __DATA__
1493
1494         @@ index.html.mustache
1495         Hello {{= $name }}.
1496
1497       Mojo::Template contains the whole list of available options.
1498
1499   Adding your favorite template system
1500       Maybe you would prefer a different template system than "ep", which is
1501       provided by Mojolicious::Plugin::EPRenderer, and there is not already a
1502       plugin on CPAN for your favorite one. All you have to do, is to add a
1503       new "handler" with "add_handler" in Mojolicious::Renderer when
1504       "register" is called.
1505
1506         package Mojolicious::Plugin::MyRenderer;
1507         use Mojo::Base 'Mojolicious::Plugin', -signatures;
1508
1509         sub register ($self, $app, $conf) {
1510
1511           # Add "mine" handler
1512           $app->renderer->add_handler(mine => sub ($renderer, $c, $output, $options) {
1513
1514             # Check for one-time use inline template
1515             my $inline_template = $options->{inline};
1516
1517             # Check for appropriate template in "templates" directories
1518             my $template_path = $renderer->template_path($options);
1519
1520             # Check for appropriate template in DATA sections
1521             my $data_template = $renderer->get_data_template($options);
1522
1523             # This part is up to you and your template system :)
1524             ...
1525
1526             # Pass the rendered result back to the renderer
1527             $$output = 'Hello World!';
1528
1529             # Or just die if an error occurs
1530             die 'Something went wrong with the template';
1531           });
1532         }
1533
1534         1;
1535
1536       An "inline" template, if provided by the user, will be passed along
1537       with the options. You can use "template_path" in Mojolicious::Renderer
1538       to search the "templates" directories of the application, and
1539       "get_data_template" in Mojolicious::Renderer to search the "DATA"
1540       sections.
1541
1542         use Mojolicious::Lite;
1543
1544         plugin 'MyRenderer';
1545
1546         # Render an inline template
1547         get '/inline' => {inline => '...', handler => 'mine'};
1548
1549         # Render a template from the DATA section
1550         get '/data' => {template => 'test'};
1551
1552         app->start;
1553         __DATA__
1554
1555         @@ test.html.mine
1556         ...
1557
1558   Adding a handler to generate binary data
1559       By default the renderer assumes that every "handler" generates
1560       characters that need to be automatically encoded, but this can be
1561       easily disabled if you're generating bytes instead.
1562
1563         use Mojolicious::Lite -signatures;
1564         use Storable qw(nfreeze);
1565
1566         # Add "storable" handler
1567         app->renderer->add_handler(storable => sub ($renderer, $c, $output, $options) {
1568
1569           # Disable automatic encoding
1570           delete $options->{encoding};
1571
1572           # Encode data from stash value
1573           $$output = nfreeze delete $c->stash->{storable};
1574         });
1575
1576         # Set "handler" value automatically if "storable" value is set already
1577         app->hook(before_render => sub ($c, $args) {
1578           $args->{handler} = 'storable' if exists $args->{storable} || exists $c->stash->{storable};
1579         });
1580
1581         get '/' => {storable => {i => '♥ mojolicious'}};
1582
1583         app->start;
1584
1585       The hook "before_render" in Mojolicious can be used to make stash
1586       values like "storable" special, so that they no longer require a
1587       "handler" value to be set explicitly.
1588
1589         # Explicit "handler" value
1590         $c->render(storable => {i => '♥ mojolicious'}, handler => 'storable');
1591
1592         # Implicit "handler" value (with "before_render" hook)
1593         $c->render(storable => {i => '♥ mojolicious'});
1594

MORE

1596       You can continue with Mojolicious::Guides now or take a look at the
1597       Mojolicious wiki <https://github.com/mojolicious/mojo/wiki>, which
1598       contains a lot more documentation and examples by many different
1599       authors.
1600

SUPPORT

1602       If you have any questions the documentation might not yet answer, don't
1603       hesitate to ask in the Forum <https://forum.mojolicious.org>, on Matrix
1604       <https://matrix.to/#/#mojo:matrix.org>, or IRC
1605       <https://web.libera.chat/#mojo>.
1606
1607
1608
1609perl v5.38.0                      2023-09-11 Mojolicious::Guides::Rendering(3)
Impressum