# Cro::WebApp The [Cro::HTTP](http://cro.services/) distribution provides a convenient way to implement HTTP services, which may be providing an API and/or serving as the backend to a Single Page Applications. Sometimes, however, one wishes to build a server-side web application, with pages being rendered and data processing performed on the server. This distribution provides a templating engine to aid that, and in the future will contain further features for building such web applications. ## Templates Templates are typically used to render some data into HTML. The template engine is designed with HTML in mind, and takes care to escape data as it should be escaped in HTML. A template is compiled once into Raku code, and then may be used many times by passing it different input. The input data can be any Raku object, including a `Hash` or `Array`. ### Using a template To use templates, add a `use Cro::WebApp::Template;` at the top of the file containing the routes where they are to be used. To render a template as the result of a route, use `template`: ``` route -> 'product', Int $id { my $product = $repository.lookup-product($id); template 'templates/product.crotmp', $product; } ``` This is short for: ``` route -> 'product', Int $id { my $product = $repository.lookup-product($id); content 'text/html', render-template 'templates/product.crotmp', $product; } ``` Where `render-template` renders the template and returns the result of doing so, and `content` is from `Cro::HTTP::Router` and sets the content type of the response along with the body. Note that by default `template` is setting a content type of `text/html`; to have it not do so, pass `content-type`: ``` route -> 'product', Int $id { my $product = $repository.lookup-product($id); template 'templates/product.crotmp', $product, content-type => 'text/plain'; } ``` The `$product` will become the topic of the template to render (see below for more on the template language). ### Template locations and compilation By default, templates will be looked for in the current working directory, and `<:use '...'>` directives in templates do the same. Templates will also be compiled lazily on first use. Call the `template-location` function in order to specify a directory where templates can be located. These calls prepend to the search path, so the latest call to `template-location` will take precedence. Doing: ``` template-location 'templates/'; ``` Means that templates underneath the `templates/` directory will be found without needing to be qualified with that path. Optionally passing `:compile-all` will immediately compile all of the templates and die if there are any errors. This could be put into a test case: ``` use Cro::WebApp::Template; use Test; lives-ok { template-location 'templates/', :compile-all }, 'All templates have valid syntax'; done-testing; ``` ### Template language The template language is designed to feel natural to Raku developers, taking syntactic and semantic inspiration from Raku. #### Generalities A template starts out in content mode, meaning that a template file consisting of plain HTML: ```
I've been expecting you...
``` Will result in that HTML being produced. Syntax significant to the templating engine consists of a HTML-like tag that begins with a non-alphabetic character. Some stand alone, such as `<.foo>` and `<$foo>`, while others have a closer, like `<@foo>...@>` The closers do not require one to write out the full opener again, just to match the "sigil". One may repeat the opening alphabetic characters of an opener in the closer if desired, however (so `<@foo>` could be closed with `@foo>`). As with Raku, there is a notion of current topic, like the Raku `$_`. #### Unpacking hash and object properties The `<.name>` form can be used to access object properties of the current topic. If the current topic does the `Associative` role, then this form will prefer to take the value under the `name` hash key, falling back to looking for a method `name` if there is no such key. Failure to find the method is a soft failure in the case of an `Associative` (e.g. it just produces `Nil`), and an exception otherwise. For example, given a template: ```Hello, <.name>. The weather today is <.weather>.
``` Rendered with a hash: ``` { name => 'Dave', weather => 'rain' } ``` The result will be: ```Hello, Dave. The weather today is rain.
``` The hash fallback is to ease the transition from using a `Hash` at first, and then refactoring towards a model object later on. Various other forms are available: * `<.elems()>` will always be a method call, even if used on an `Associative` (so can be used to overcome the key fallback) * `<.Hello, <$person.name>. The weather is <$weather.description>, with a low of <$weather.low>C and a high of <$weather.high>C.
``` Would render something like: ```Hello, Darya. The weather is sunny, with a low of 14C and a high of 25C.
``` #### Iteration The `@` tag sigil is used for iteration. It may be used with any `Iterable` source of data, and must have a closing tag `@>`. The region between the two will be evaluated for each value in the iteration, and by default the current target will be set to the current value. For example, given the template: ``` ``` And the data: ``` { countries => [ { name => 'Argentina', alpha2 => 'AR' }, { name => 'Bhutan', alpha2 => 'BT' }, { name => 'Czech Republic', alpha2 => 'CZ' }, ] } ``` The result would be: ``` ``` The `<@foo>` form is short for `<@.foo>`, and follows the same rules as `<.foo>` for resolution. It is also possible to write `<@$foo>` to iterate over a variable. To specify a variable to declare and populate with the current iteration value instead, place a `:` afterward the iteration target and name the variable. For example, the earlier template could be written as: ``` ``` Which leaves the current default target in place. Should the current target itself be `Iterable`, it is permissible to write simply `<@_>...@>`. If the opening and closing iteration tags are the only thing on the line, then no output will be generated for those lines, making the output more pleasant. #### Conditionals The `$foo>...?>` ("if") and `...!>` ("unless") may be used for conditional execution. These perform a boolean test on the specified variable. It is also allowed to use them with the topic deference syntax, such as `.is-admin>...?>`, or variables and dereferences together, such as `$user.is-admin>...?>`. For more complex conditions, a subset of Raku expressions is accepted, using the syntax `{ $a eq $b }>...?>`. The only thing notably different from Raku is that `{ .answer == 42 }>...?>` will have the same hash/object semantics as in `<.answer>`, for consistency with the rest of the templating language. The following constructs are allowed: * Variables (`$foo`) * Use of the topic, method calls, and indexing, to the degree supported by the `<.foo>` tag syntax * Parentheses for grouping * The comparison operations `==`, `!=`, `<`, `<=`, `>=`, `>`, `eq`, `ne`, `lt`, `gt`, `===`, and `!===` * The `&&`, `||`, `and` and `or` short-circuit logic operators * The `+`, `-`, `*`, `/`, and `%` math operations * The `~` and `x` string operations * Numeric literals (integer, floating point, and rational) * String literals (single quoted, without interpolation) Those wishing for more are encouraged to consider writing their logic outside of the template. If the opening and closing condition tags are the only thing on the line, then no output will be generated for those lines, making the output more pleasant. #### Subroutines and macros It is possible to declare template subroutines that may be re-used, in order to factor out common elements. A simple template subroutine declaration looks like this: ``` <:sub header>