Layouts

GOERP have in-build layout system, so one layout can be re-used on many pages. This feature would be very useful if application have many templates (pages) because with layouts we can encapsulate all general html into one component (e.g. css and js dependencies, general html like header, footer, menu, etc…).

Note

Layouts usage may look similar to the regular partial logic, however, they behave in absolutely different way. The main difference between layout and regular partial is that the former one contains code placeholders that are replaced with actual payload on the related page template, and the latter one doesn’t have any placeholders and contains only code that is related to this specific partial.

In other words:

  • in case of layouts, page template exports go-html content to the layout through block keywords by define‘ing those blocks;
  • in case of partial, page template imports go-html content from the partial through the template notation;
  • both, layout and partial, should be defined inside page by using template keyword, the only difference is that layouts must be defined at very beginning of the page template.
  • both, layout and partial cannot include other partials as dependencies

Under pages topic we already covered briefly layouts feature. Let’s dive into more details now.

Very simple example (layout)

{{ define "simple-layout" }}
<!-- Let's say we want to encapsulate page content that is the same for all pages in our application -->
<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- Default Erply styles -->
  <link rel="stylesheet" href="https://assets.erply.com/bo-prototype/_style.css">
  <!-- Maybe some custom styles -->
  <link rel="stylesheet" href="https://assets.my-company.net/style.css">
  <!-- Regular fonts from google -->
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

  <!-- With this block we are creating placeholder which may be filled from the page template -->
  <!-- Here we may inject page specific css links or static file dependencies -->
  <!-- Please note, all block definition names must have -block suffix at the end -->
  {{ block "css-block" . }} {{ end }}

  <!-- Add page specific title -->
  <title>
    {{ block "title-block" . }} Default title {{ end }}
  </title>
</head>
<body>

<menu class="menu-container">
  <!-- This menu will be included into all dependent pages -->
</menu>

{{ block "content-block" . }}
<main>
  <p>
    Another cool feature of the placeholder blocks is that they may contain default content,
    some kind of fall back in case if dependent page decides to leave this block undefined. So,
    if page that is using this layout doesn't have <code>{{ define "content-block" }} {{ end
    }}</code>
    section then <strong>this message shown by default</strong>.
  </p>
</main>
{{ end }}

<!-- Another sample how to pass some data from templates to the js using inputs -->
<input type="hidden" id="AUT_SESSION" value="{{ toJson .Session }}">
<input type="hidden" id="REQUEST_STATS" value="{{ toJson .Data.RequestStats }}">

<!-- global js dependencies -->
<script src="/assets/js/automat.deps.js" type="application/javascript"></script>
<script src="/assets/js/menu.bundle.js" type="application/javascript"></script>

<!-- placeholder for js dependencies, use static files to import js code -->
{{ block "js-block" . }} {{ end }}

</body>
</html>
{{ end }}

First of all, we are defining name of the layout, which must end with layout suffix. Don’t worry, suffix will be added automatically when creating new template from editor and selecting layout template type. So, for our sample during layout creation we enter simple name and -layout added by default.

Next, we have some regular page content that is, potentially, repeated on every page in our application.

The first block that would be replaced by content from the page that will use this layout is {{ block "css-block" . }} {{ end }}. Then we have title placeholder: {{ block "title-block" . }} Default title {{ end }} and then placeholder for the biggest part of the page, - main section: {{ block "content-block" . }} {{ end }}. Check default (fall back) content of this block in the sample. Finally, we have js placeholder where we can include any js related to the page, please refer to css and js partials for more information on how to include js and css code.

Warning

While defining blocks inside layout, always put -block suffix in names. If name will end with something else then goerp parser will process them as regular partials and mess up template parameters. This may lead to appear some unknown partials and mey produce unexpected behavior.

Very simple example (page)

Now, when we have defined the layout, we may want to use it inside our pages. Let’s say it 10th page of our application:

<!-- Page creation always starting from importing our layout -->
{{ template "simple-layout" . }}

<!-- Title for our 10th page -->
{{ define "title-block" }} 10th page of application {{ end }}

<!-- The biggest part, - content -->
{{ define "content-block" }}

<!-- Display errors -->
{{ range .Data.Errors }}
<div class="error-row">
  <span>{{ . }}</span>
</div>
{{ end }}

<!-- Include partials -->
{{ template "employee-query-form-partial" . }}

<!-- Write regular goerp template code -->
<table>
  <thead>
  <tr>
    <th>Id</th>
    <th>First Name</th>
    <th>Last Name</th>
  </tr>
  </thead>
  <tbody>
  {{ range .Data.AccountAdminApi.EmployeeList }}
  <tr>
    <td>{{ .Id }}</td>
    <td>{{ .FirstName }}</td>
    <td>{{ .LastName }}</td>
  </tr>
  {{ end }}
  </tbody>
</table>

<!-- Include js -->
{{ define "js-block" }}
<script src="{{ staticFileLink "my-cool-js" }}"></script>
{{ end }}

{{ end }}

First of all, we are importing layout to the page.

Tip

Notice dot at the end of layout definition? Yes, we can pass any data to the layout, with the dot we are passing everything that page have. However, we can pass some custom data and, for example, add tabs logic to the layout. Just a tip.

Next, we are defining title of our page with {{ define "title-block" }} 10th page of application {{ end }}. Next, in our template we have css-block, but we don’t need to include any css links/deps here, so we just skip this block. Next goes content of the page, the biggest part. There we can use other templates-partials and goerp templating logic.

Finally, we have js block implementation which includes static file.