How to use Mojolicious's "template"

I would like to explain about templates . Until now, I've only output simple text, but since it's a web application, I want to output HTML. You can output HTML by using a function called template of Mojolicious.

use Mojolicious::Lite;

get'/' => sub {
  my $self = shift;
  
  #Specify template
  $self->render('index');
};;

get'/ company / info' => sub {
  my $self = shift;

  #Specify template
  $self->render('company / info');
};;

app->start;

__DATA__

@@index.html.ep
<html>
  <head>
    <title> Index </title>
  </head>
  <body>
    <h1> Index </h1>
  </body>
</html>

@@company / info.html.ep
<html>
  <head>
    <title> Company Information </title>
  </head>
  <body>
    Company Information
  </body>
</html>

Try launching the application and accessing "/" and "/ company / info". "Index" and "Company Informatiomn" are displayed in bold, respectively.

How to specify a template

First, let's look at the specified part of the template. Templates can be specified with the render method.

#Specify template
$self->render('index');
$self->render('company / info');

You can also use " / " to represent the directory hierarchy, as in the second example.

How to write a template

Next, let's see how to write a template.

__DATA__

@@index.html.ep
<html>
  <head>
    <title> Index </title>
  </head>
  <body>
    <h1> Index </h1>
  </body>
</html>

@@company / info.html.ep
<html>
  <head>
    <title> Company Information </title>
  </head>
  <body>
    <h1> Company Information </h1>
  </body>
</html>

The template should be written below the line that says __DATA__ . This part is called the data section.

Next, describe the template name in the following expression.

@@Template name.html.ep

Please note that a half-width space is required after " @@". The extension of the Mojolicious template name will be " html.ep " unless you do something special.

In this sample, there are two templates, but each has the following description.

@@index.html.ep
@@company / info.html.ep

Then write HTML after the template name.

@@index.html.ep
<html>
  <head>
    <title> Index </title>
  </head>
  <body>
    <h1> Index </h1>
  </body>
</html>

This will be what you see.

Perl can be written in the template

You can write Perl in Mojolicious templates. It's convenient if you learn a little notation because you don't have to learn any special grammar.

To write Perl, write "%" at the beginning.

%my $name ='kimoto';

You can also use the notation " & lt; %%& gt; " when writing multiple Perls.

<%
  my $title ='kimoto';
  my $age = 19;
%>

Embedding values ​​

You can also use "%= " or " <%=%> " to embed the value directly in the HTML.

%= $title;
<%= $title%>

Sample using Perl description

Now, let's actually write a sample using Perl in the template. In the sample, if statement and for statement are used.

use Mojolicious::Lite;

get'/' => sub {
  my $self = shift;
  
  $self->render('index');
};;

app->start;

__DATA__

@@index.html.ep
<%
  my $name ='kimoto';
  my $age = 19;
  my @nums = (1, 2, 3);
%>
<html>
  <head>
    <title> Index </title>
  </head>
  <body>
    <h1> Index </h1>
    %if ($name eq'kimoto') {
      Kimoto
    %} else {
      Other Other
    %}
    <br>
    He is <%= $age%> years old. <br>
    
    %for my $num (@nums) {
      <%= $num%> <br>
    %}
  </body>
</html>

It's convenient because you can write Perl in the template like this.

Values ​​are automatically HTML escaped

%= Value
<%= value%>

The values ​​embedded in the above description are automatically XML escaped. XML escaping is the process of replacing dangerous strings with safe characters in HTML. The following conversions are done:

& => & amp;
<=> & lt;
> => & gt;
"=> & quot;
'=> & # 39;

If "& lt;" etc. cannot be replaced, there is a risk that javascript will be executed if a string such as "" is sent from the user. increase. Therefore, Mojolicious uses XML escaping by default to reduce this risk.

If you don't want to do XML escaping, use the notation " <%== " or " <%==%> ".

%== Value
<%== value%>

Data is passed using a variable called stash

The controller and template share a variable called a stash. If you want to pass the data to the template side, you can set the value using the stash method.

# Setting the stash value on the controller
$c->stash('name' =>'Kimoto');

#Get stash value with controller
my $name = $c->stash('name')

You can also use the stash helper in the template to set and get values. Keep in mind that the functions available in the template are called helpers.

#Setting stash values ​​in templates
stash ('name' =>'Kimoto');

#Get stash value in template
my $name = stash ('name');

It is also convenient to use the second and subsequent arguments of the render method to set the stash value. You can write it short, so let's use this.

#render method
$c->render($template,'name' =>'Kimoto','age' => 19);

# Same as this
$c->stash('name' =>'Kimoto');
$c->stash('age' => 19);
$c->render($template);

Stash reserved words

As stash keys, the following are reserved words, so don't use them if you want to save the value. If you use it, it will cause unexpected behavior and the correct processing will not be performed, so please be careful.

action app cb controller data extends format handler json layout
namespace partial path status template text variant

Sample using stash

I will write a sample using stash.

use Mojolicious::Lite;

#Controller
get'/' => sub {
  my $self = shift;
  
  # Set a value for stash and draw index
  $self->render('index','name' =>'Kimoto', age => 19);
};;

app->start;

__DATA__

@@index.html.ep
<%
  #Get value from stash
  my $name = stash ('name');
  my $age = stash ('age');
%>
<html>
  <head>
    <title> Index </title>
  </head>
  <body>
    <h1> <%= $name%>: <%= $age%> </h1>
  </body>
</html>

I'm using the render method in my controller to set the stash.

# Set a value for stash and draw index
$self->render('index','name' =>'Kimoto', age => 19);

I'm using the stash helper in the template to get the stash value.


Layout

Next, I will explain the function called layout . Let's take a look at the first sample again.

@@index.html.ep
<html>
  <head>
    <title> Index </title>
  </head>
  <body>
    <h1> Index </h1>
  </body>
</html>

@@company / info.html.ep
<html>
  <head>
    <title> Company Information </title>
  </head>
  <body>
    Company Information
  </body>
</html>

The html tag and body tag are common to the two templates. The contents of the body are different, but the html tags and body tags that form the skeleton are the same. In such cases, you can avoid repeating the description by using a function called layout.

Let's rewrite the first sample with a layout.

@@layouts / common.html.ep
<html>
  <head>
    <title> <%= stash ('title')%> </title>
  </head>
  <body>
    %= content;
  </body>
</html>

@@index.html.ep
%layout'common', title =>'Index';
  <h1> Index </h1>

@@company / info.html.ep
%layout'common', title =>'Company Information';
  <h1> Company Information </h1>

Layout name

Let's define the layout first. Look at the template name first.

layouts / common.html.ep

It starts with "layouts /". This is the rule when creating a layout. It is followed by the layout name "common". And the extension is ".html.ep" which is the same as the template.

Layout contents

Next, let's take a look at the contents of the layout.

<html>
  <head>
    <title> <%= stash ('title')%> </title>
  </head>
  <body>
    %= content;
  </body>
</html>

Describe the part shared by all templates in the layout. I am writing an html tag and a body tag. The content to be embedded in the layout can be obtained with the content helper . The content helper part replaces the actual content.

You can use stash in the layout, so you can pass data from the template to the layout through stash. With this, it's easy to change just the title.

Call layout

Next, let's take a look at the description that calls the layout in the actual template.

@@index.html.ep
%layout'common', title =>'Index';
  <h1> Index </h1>

You can call the layout using the layout helper . Specify the layout name in the first argument. The values ​​after the second argument are set as stash values.

Actually this will be expanded to HTML like below.

<html>
  <head>
    <title> Index </title>
  </head>
  <body>
      <h1> Index </h1>
  </body>
</html>

Make sure that "& lt; h1 & gt; Index & lt; / h1 & gt;" is embedded in the layout you called. I think that layout is an essential function to use. Please remember.

Include other templates

Next, I will introduce the function that can "include" other templates. You can create and load common parts such as "headers" and "footers".

Use the include function to include other templates . It can be used to define and load components used in multiple parts as common parts.

Description of included template

Describes the template to be included. Name it component.html.ep.

component
%= $name

Notice the part called $name. This way, when you include the template, you can change only part of it.

Template inclusion

Use the include function to include the template.

%= include'component', name =>'Ken';

The first argument is the template name you want to include. ".Html.ep" can be omitted. After the second argument, you can specify the data you want to pass to the included template with a hash.

Template externalization

In the Mojolicious::Lite sample, the template was written inside a file, but it can also be placed as a "file". If it grows larger, you can save it externally as a file for better visibility.

Create a "templates" directory, place it in it, and Mojolicious will load it for you.

templates / index.html.ep
          / list.html.ep

Techniques used in templates

Here are some techniques you often use in templates.

Protect text from HTML escaping

To protect the text from HTML escaping, convert the string to a Mojo::ByteStream object and then pass it to the template.

<%= Mojo::ByteStream->new('<p> test </p>')%>

If you don't want to HTML escape tags etc., convert it to a Mojo::ByteStream object and pass it to the template.

There is also a helper called b , which can be used for a short time.

<%= b ('<p> test </p>')%>

Get controller object

To get the controller object in the template, access the variable $self .

%my $controller = $self;

$self is a variable that is implicitly declared in the template. This is the Mojolicious::Controller object.

You can call methods of the controller class from this object.

#Call a method of the controller class
my $req = $self->req;

Create a template block

You can create a "template block" in a template. Template blocks can be used as part of a reusable template.

#Template block
<%my $div = begin%>
  %my ($id, $text) = @_;
  <div id = "<%= $id%>">
    %= $text
  </div>
<%end%>

The template block is essentially a subroutine reference, but the point is that you can write the HTML content as you would in a template. Template blocks start with begin and end with end.

Template blocks can be used as a reference for Perl subroutines.

<%= $div->('foo','Hello')%>

Below is a sample from Mojolicious::Lite.

use Mojolicious::Lite;
get'/' =>'index';
app->start;

__DATA__

@@index.html.ep
<%my $div = begin%>
  %my ($id, $text) = @_;
  <div id = "<%= $id%>">
    %= $text
  </div>
<%end%>

<%= $div->('foo','Hello')%>

Remove blanks before and after tags

When using Mojolicious templates, you may want to remove the white space before and after the tag. If you want to remove the leading and trailing spaces, use the following special tags.

<%= Content =%>

In the case of a normal tag, it is "<%= content%>". The point is that = is attached before the%at the back.

Templates share function namespaces

You are free to write Perl code in Mojolicious templates, but there is one caveat. That is, all templates share the namespace of the function.

#Template A
use Encode'encode';
#Template B
encode ('UTF-8', $str);

Template B does not import the encode function, but template A imports it, so it can be used in template B. This is because Mojolicious creates all the templates in one namespace.

So if you don't want to get confused, it's safe to use the fully qualified name instead of importing the function in the template.

use Encode ();
Encode::encode ('UTF-8', $str);

Summary

It's great that you can use Perl for Mojolicious templates! Neither "if" nor "for" need to remember the syntax for templates. You can share the header and footer descriptions by using the "layout" and "include" descriptions. It's convenient because you don't have to copy and paste.

Associated Information