CASE: create navigation headers

When creating a set of templates, it can be desirable to have a clear navigation header within the templates, that link to the other templates:

To be clear, this isn’t something that should be done always, as within Silverfin you already have a function that let’s you flow through all the needed templates to complete your workflow:
Screenshot 2020-07-03 at 14.31.09

This lets you go through all the unreconciled templates for example.

So then why choose to have a navigation header? Well, it could be that you want to see which templates are available/starred/… or that you regularly jump from one template to another in a non-logical order, or that you wish to navigate without going to the working screen of the workflow (one extra click).

Whatever the case, here is how you can built a navigation header, taking into account:

  • the name of the template as a link is not an option; we prefer to show an abbreviation or a number;
  • some templates get auto-hided;
  • to avoid duplicate coding in every template, we’ll use shared parts

STEP A: create an array

We can loop over reconciliations and access what we need with this, and order it on something:

{% comment %}loop over reconciliations{% endcomment %}
{% stripnewlines %}
  {% for item in period.reconciliations %}
    {% newline %}
    {% assign recon_handle = item.handle %}
    {% assign recon_name = item.name %}
    {% assign recon_nbr = item.number %}
    
      {% linkto recon_handle %}{{ recon_name }} *({{ recon_handle }})* {{ recon_nbr }}{% endlinkto %}

  {% endfor %}
{% endstripnewlines %} 

This will be ordered on virtual account number, but you can obviously order it differently.
But what if we cannot automate the order, depending on info we have from the reconciliation drop? And what if we need something different than the name of each reconciliation?

In most cases, we’ll need to hard-code an array with the information we need, like this:

{% comment %}create needed array{% endcomment %}
{% assign header_array = "IMVA;vkt_6_1_1|MVA;vkt_6_1_2|FVA;vkt_6_1_3" | split:"|" %}

{% comment %}linkto header{% endcomment %}
{% stripnewlines %}
{% for item in header_array %}
{% assign part = item | split:";" %}
{% assign abb = part[0] %}
{% assign handle = part[1] %}
{% assign recon = period.reconciliations[handle] %}
| {% linkto recon %}{{ abb }}{% endlinkto %}
{% endfor %}
{% newline %}
{% for item in header_array %}
|:----:
{% endfor %}#
{% endstripnewlines %}

showing up like this:

However, there are a few things missing from above coding:

  • check on reconciliations and if they are present in the workflow
  • the reconciliation you are using, shouldn’t have a link
  • the header cells should always be the same width, depending on how many links there are

Let’s change a few things, and create this navigation header in a shared part called nav_header

STEP B: create header in shared part

First, we’ll access the handle of the current reconciliation, by this code:

{% comment %}some needed variables{% endcomment %}
{% assign current_recon = current_reconciliations.handle %} 

We will need that to not display a link in the header.

Then, we will decide on how the header should look like, with an equal width for every cell too:

{% comment %}create needed array{% endcomment %}
{% assign header_array = "BALANCE;vkt_3_1|IMVA;vkt_6_1_1|MVA;vkt_6_1_2|FVA;vkt_6_1_3" | split:"|" %}
{% assign rows = 2 %}

{% comment %}linkto header{% endcomment %}
{% stripnewlines %}
| {% for item in header_array %}
    {% assign part = item | split:";" %}
    {% assign abb = part[0] %}
    {% assign handle = part[1] %}
    {% assign recon = period.reconciliations[handle] %}
    {% if handle == current_recon %}
      **{{ abb }}**
    {% else %}
      {% linkto recon %}{{ abb }}{% endlinkto %}
    {% endif %}
    |
    {% assign modulo = forloop.index | modulo:rows %}
    {% if modulo == 0 %}
      {% unless forloop.last %}
        {% newline %}
      {% endunless %}
    {% endif %}
  {% endfor %}
  
{% newline %}
{% for i in (1..rows) %}
|:--{{ INT(100/rows) }}%--:
{% endfor %}#
{% endstripnewlines %}

The outcome of the modulo var only creates an extra row, when it’s zero. And when the outcome of the var current_recon equals the handle, you know you cannot show a link. So you’ll have something like this:

seeing that the recon MVA is the active template you are working in.

We’re almost finished with the header. One small thing needs to be added: check on hidden templates.

The auto-hide of a template will most of the time depend on the outcome of a result tag. Eg:
Screenshot 2020-07-03 at 15.56.31

If a template is hidden or not, can be accessed through the hidden? method:

      {% if recon.hidden? %}
        {{ abb }}
      {% else %}
        {% linkto recon %}{{ abb }}{% endlinkto %}
      {% endif %} 

You can also add the exists? method, just to be sure if the reconciliation exists or not.

But there’s one thing to watch out for when creating a navigation header with templates that can be auto-hided:
you’re trying to access a result tag (which activates the auto-hide function) that’s made within the same template. And that cannot be done

So you cannot use the hidden? method as it calls upon a local var (the result tag).

How to solve it then?

Well, there’s no other way then to (re)create the logic behind that result tag in the shared part. Let’s say if depends on the outcome of a boolean with a certain default in it.

In the shared part, you can do this:

{% comment %}create local var that will be used in template "vkt_6_1_2" as it gets auto hided{% endcomment %}
{% assign show_vkt_6_1_2 = period.reconciliations.vkt_6_1_2.custom.show.vkt_6_1_2 | default:true %} 

In our linkto header, instead of using the hidden? method, will we use the local var from the shared part called show_vkt_6_1_2:

    {% if handle == current_recon %}
      **{{ abb }}**
    {% else %}
      {% comment %}check if certain templates are hidden or not{% endcomment %}
      {% case handle %}
      {% when "vkt_6_1_2" %}
        {% if show_vkt_6_1_2 %}
          {% linkto recon %}{{ abb }}{% endlinkto %}
        {% else %}
          {{ abb }}
        {% endif %}
      {% else %}
        {% linkto recon %}{{ abb }}{% endlinkto %}
      {% endcase %}
    {% endif %} 

As you can see, we avoid the hidden? method as we need to access the local variable we create in the shared part.
This is not needed if the templates depend on another template for auto-hide if that template is also part of the navigation header!

In the template where we access the shared part and that needs to create the result tag, will we create a just that with the variable that’s made from the shared part:

{% result 'show_vkt_6_1_2' show_vkt_6_1_2 %}