Skip to content

Commit

Permalink
Fix #22
Browse files Browse the repository at this point in the history
Signed-off-by: Clement Escoffier <[email protected]>
  • Loading branch information
cescoffier committed Apr 4, 2014
1 parent c4f49fe commit aeac8e8
Show file tree
Hide file tree
Showing 7 changed files with 334 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* #%L
* Wisdom-Framework
* %%
* Copyright (C) 2013 - 2014 Wisdom Framework
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
// tag::controller[]
package controllers.templates;

import org.wisdom.api.DefaultController;
import org.wisdom.api.annotations.Controller;
import org.wisdom.api.annotations.Route;
import org.wisdom.api.annotations.View;
import org.wisdom.api.http.HttpMethod;
import org.wisdom.api.http.Result;
import org.wisdom.api.templates.Template;

@Controller
public class FragmentController extends DefaultController {

@View("page")
Template template;

@Route(method = HttpMethod.GET, uri = "/templates/page")
public Result welcome() {
return ok(render(template, "username", "Clement"));
}
}
// end::controller[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* #%L
* Wisdom-Framework
* %%
* Copyright (C) 2013 - 2014 Wisdom Framework
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
// tag::controller[]
package controllers.templates;

import org.wisdom.api.DefaultController;
import org.wisdom.api.annotations.Controller;
import org.wisdom.api.annotations.Route;
import org.wisdom.api.annotations.View;
import org.wisdom.api.http.HttpMethod;
import org.wisdom.api.http.Result;
import org.wisdom.api.templates.Template;

@Controller
public class WelcomeController extends DefaultController {

@View("welcome") // <1>
Template template; // <2>

@Route(method = HttpMethod.GET, uri = "/templates/welcome")
public Result welcome() {
return ok(render(template, "welcome", "Welcome on the Path to Wisdom")); // <3>
}
}
// end::controller[]
2 changes: 2 additions & 0 deletions documentation/src/main/resources/assets/index.ad
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Version ${project.version}
:description: This document is the documentation of the Wisdom Framework.
:toc: right
:sourcedir: ${project.basedir}/src/main/java
:resourcedir: ${project.basedir}/src/main/resources
:assetdir: ${project.basedir}/src/main/assets
:assetoutdir: ${project.basedir}/target/wisdom/assets
:icons: font
Expand All @@ -21,6 +22,7 @@ include::build-process.ad[]
include::http.ad[]
include::routing.ad[]
include::response.ad[]
include::template.ad[]
include::session-and-scope.ad[]
include::json.ad[]
include::file-upload.ad[]
Expand Down
197 changes: 197 additions & 0 deletions documentation/src/main/resources/assets/template.ad
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
== Using Templates

=== Template as a Service

Just to makes you understand how the template system works, you should read these small paragraphs.

Wisdom allows the integration of any template engine. By default, http://www.thymeleaf.org/[Thymeleaf] is provided.
Each template is exposed as a _service_ and can be injected in a controller using the `@View` annotation. This
pattern is used regardless the template engine you use.

The `View` annotation is looking for a template with the specified name. It is equivalent to a regular `@Requires`
with a filter.

=== The Thymeleaf Template Engine

http://www.thymeleaf.org/[Thymeleaf] is an XML / XHTML / HTML5 template engine (extensible to other formats) that
can work both in web and non-web environments. It is really well suited for serving XHTML/HTML5 at the view layer of
web applications, but it can process any XML file even in offline environments.

The main goal of Thymeleaf is to provide an elegant and well-formed way of creating templates. It allows you to create
powerful natural templates, that can be correctly displayed by browsers and therefore work also as static prototypes.
One of the main interest of Thymeleaf is a smooth collaboration with Web Designer. By using specific attributes on
HTML elements, you never interfere with the work of the web designers. They create the HTML page with whatever
structure, and CSS tricks, and you just identify the parts where you inject the data.

It looks like this. As you can see, it's a pretty straightforward syntax supporting all the features you expect from a
template engine: variables, internationalization, iterations, layouts, fragments, object navigation, and much more.

[source,xml,indent=0]
----
<table>
<thead>
<tr>
<th th:text="#{msgs.headers.name}">Name</th>
<th th:text="#{msgs.headers.price}">Price</th>
</tr>
</thead>
<tbody>
<tr th:each="prod : ${allProducts}">
<td th:text="${prod.name}">Oranges</td>
<td th:text="${#numbers.formatDecimal(prod.price,1,2)}">0.99</td>
</tr>
</tbody>
</table>
----

The complete documentation of Thymeleaf is available http://www.thymeleaf.org/doc/html/Using-Thymeleaf.html[here].

==== My First Template

Thymeleaf templates are HTML files with the `.thl.html` extension, for example: `mytemplate.thl.html`. The
"mytemplate" is referred as the template name. Templates can be placed in:

* `src/main/resources/templates` and are embedded in the application's Jar.
* `src/main/templates` and are in the distribution but not in the application's Jar file.


Whether or not your application is intended to be reused in several 'bigger' application determines the place of your
template files.

Let's look at the following template, named `welcome.thl.html`:

[source,xml,indent=0]
----
include::{resourcedir}/templates/welcome.thl.html[]
----

The `th:text` attribute instructs the template engine to replace the content of the element by the `welcome`
value. This value is given as parameter to the template engine.

So now in your controller, use the `@View` annotation to inject the template:

[source,java,indent=0]
----
include::{sourcedir}/controllers/templates/WelcomeController.java[tags=controller]
----
<1> Use the `@View` annotation and indicate the template name
<2> The injected field must use the `Template` type
<3> Use the `render(template, ...)` methods to render the template

You can render the template using the `render` methods:

* `render(Template template)` asks the template engine to render the template without input variables
* `render(Template template, Map<String, Object> params)` inserts the given parameters to the template
* `render(Template template, Object... params)` proposes an easier way to pass parameters. However, one parameter
over two must be a string (the parameter name), while the following is the value:

return ok(render(template, "welcome", "hello", "age", 1, "colors", new String[] {"red", "blue"}));

The `render` method is wrapped within a `ok` method indicating the type of response. Obviously, you can use any other
type of result.

Some values are automatically given to the template engine:

* the parameters of the request
* the values stored in the session
* the value stored in the flash scope

==== Some Thymeleaf constructions

Now we have seen how template can be used, let's see some general construction patterns we use in templates:

**Variable:**

<p th:text="${variable}">this will be replace by the variable</p>
<p th:utext="${variable}">this will be replace by the variable (unescape so won't remove the contained HTML elements)
</p>

**Internationalized variable:**

<p th:text="#{variable}">this will be replace by the variable using the request locale</p>

WARNING: Internationalized value are directly retrieved from the internationalization service from Wisdom.

**Iteration:**

You can iterate on collections, arrays, maps...

<!-- Iterate over a list of products -->
<tr th:each="prod : ${prods}">
<td th:text="${prod.name}">Onions</td>
<td th:text="${prod.price}">2.41</td>
<td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>

**Conditionals:**

<td th:text="${prod.inStock}? 'true' : 'false'">
true or false according to the prod.isStock value
</td>

<a href="#" th:if="${not #lists.isEmpty(prod.comments)}">display this link comments if not empty</a>


TIP: Check the http://www.thymeleaf.org/doc/html/Using-Thymeleaf.html[Thymeleaf documentation] to find more.

==== Fragments and Layout

Templates are generally used to create layouts. Thymeleaf allows to create _fragments_, and to include them in the
_main_ template.

Fragments are identified part of a template. For example, the following snippet defined two fragments: `my-content`
and `sub-content`.

[source,xml,indent=0]
----
include::{resourcedir}/templates/content.thl.html[]
----

Fragments can be included either using:

*`th:include`: include the fragment 'under' the element using the directive
*`th:replace`: replace the element using this directive with the fragment content

The value of theses directive is formed by `name_of_the_template_defining_the_fragments :: fragment_name`. For
example, if the previous fragment are defined in `content.thl.html`, including them would look like:

[source,xml,indent=0]
----
include::{resourcedir}/templates/page.thl.html[]
----

TIPS: fragments can use any variable given to the template engine.

==== Using the router from the template

A template can use a special object named `#routes` to retrieve the url of action methods. In the following snippet,
the `action` attribute is assigned to the url of the `upload` method of the current controller (the controller having
requests the template rendering).

[source,xml,indent=0]
----
th:attr="action=${#routes.route('upload')}"
----

You can also ask for the url of an action method receiving parameters:

[source,xml,indent=0]
----
th:attr="action=${#routes.route('upload', 'param', 'value', 'param2', 'value2')}"
----

Finally, you can target method from other controllers with:

[source,xml,indent=0]
----
th:attr="action=${#routes
.route(`org.acme.controller.MyOtherController`, 'upload', 'param', 'value')}"
----

If the route cannot be found, the template rendering fails.






18 changes: 18 additions & 0 deletions documentation/src/main/resources/templates/content.thl.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8"/>
<title>This is a fragment</title>
</head>
<body>

<div th:fragment="my-content">
<h1>Hello <span th:text="${username}">my name</span></h1>
</div>

<div th:fragment="sub-content">
<p>This is the first step to Wisdom, follow us...</p>
</div>

</body>
</html>
20 changes: 20 additions & 0 deletions documentation/src/main/resources/templates/page.thl.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8"/>
<title>My Main Page</title>
</head>
<body>

<!-- th:replace replaces the element with the fragment content -->
<div th:replace="content :: my-content"></div>

<!-- th:include injects the fragment as content of the element (so an element below the 'div') -->
<div th:include="content :: sub-content"></div>

<footer>
&copy; My Copyright....
</footer>

</body>
</html>
13 changes: 13 additions & 0 deletions documentation/src/main/resources/templates/welcome.thl.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Follow the Wisdom Path</title>
</head>

<body>
<h1 th:text="${welcome}">Hello</h1>
</body>

</html>

0 comments on commit aeac8e8

Please sign in to comment.