Power App Portals Custom Entity list: improved View selector with liquid code

Last updated on 16/02/2020

This blog post about “Power App Portals custom Entity List view selector” will show you step-by-step how improve your custom entity list in your Power App Portal to show the name of the current view instead of just “views” at the list header. Why is this important? It let your user know what view they are currently looking at.


The result will look like this:

This image has an empty alt attribute; its file name is image-37-1024x313.png

Some context:

So we got our custom entity list created in liquid code snatched right out of the Microsoft Portals documentation page. If this doesn’t ring any bells take a look at this blog post https://ulrikke.akerbak.com/2019/09/28/portals-custom-entity-list/ and to the simple steps to get your custom entity list web template up and running. It will look something like this straight out of the box with simple branding:

Now, notice what happens if you have more then one view set up in the portal entity list configuration. The list view selectior always sais “Views”.

You click it, choose the view you want, the page reloads and the label still say “Views”.

How can the user see what records they’re looking at? I want it to say the name if the view i chose, and I want it now!

Let’s go..

Short Cut

You just wanna go for the source code directly and use it as your own I will save you the trouble of scrolling down to the bottom of this blog post, you can just jump right to the bottom and copy the whole entity form right here.

The source code at the bottom of this blog post include the whole web template, but I’m only going to explain the view selector part of the code. You’ll probably find the rest explained in future blog posts.

Making the view selector great again

I start by adding a reference to the “Layout 1 Column” web template. This will add the html structure and logic from the original template (line 1). The template contain blocks, and by defining the “block main” in my template I replace the block content of “Layout 1 Column” (line 2). Look at Create a custom web template from Microsoft Portals documentation for more detailed step-by-stem instructions.

On line 4 the original liquid code get the entity list set on the web page.

Then I go down to line 74 and cut the start tag for entity view and paste it in on line 5. This will make entity view parameters and variables available to us in the header. This enable us to get the number of records in each view and print it next to the view name. You’ll see..

Then an important step; wrap the whole entity list in a div with the class=”Unify-entitylist” to make sure the styling I apply to this entity list doesn’t affect the look and feel of the original entity lists (line 6).

M

Make sure you close the new div wrapper, the entity list and entity view tag, as well as close the liquid block tag at the bottom of the code.

Now locate the text “Views” on line 25:

Replace it with this code:

{% unless params.view %}
  {{ entitylist.views[0].name }} ({{entityview.total_records}})
{% endunless %}

{% for view in entitylist.views -%}
  {% if params.view == view.id %}{{view.name}} ({{entityview.total_records}}){% endif -%}
{% endfor -%}Code language: PHP (php)

Your code look like this now:

The end.. 😉 Now your Custom Entity List should look something like this:

You can click on the view to trigger the drop down menu to select another view, and the name of the active view will always be visible to the user.

As you can see the number of records in the view is visible to the user too; a nice bonus.

The whole web template

If you wanna try this for yourself copy this code (below) and paste it info a web template and try it out. There are two ways to go about it:

  1. You choose to save the web template as a pure entity list template and include it into other templates when needed.
  2. Or you can surround this liquid code with some HTML blocks and make it into a complete web template for a page template (like the code below).

Confused? This might help you get it sorted:
Microsoft Portals Docs: How to create custom template
Microsoft Portals Docs: Store content in web templates

{% extends 'Layout 1 Column' %}
{% block main %}
<div class="Unify_entitylist">
{% entitylist id:page.adx_entitylist.id %}
{% entityview id:params.view, search:params.search, order:params.order, page:params.page, pagesize:params.pagesize, metafilter:params.mf %}
    <div class="navbar navbar-default">
      <div class="container-fluid">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle"
            data-toggle="collapse"
            data-target="#entitylist-navbar-{{ entitylist.id }}">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="{{ page.url }}">{{ entitylist.adx_name }}</a>
        </div>
        <div class="collapse navbar-collapse" id="entitylist-navbar-{{ entitylist.id }}">

          {% if entitylist.views.size > 1 %}
            <ul class="nav navbar-nav">
              <li class="dropdown">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                  <i class="fa fa-list"></i> 
                  {% unless params.view %}
                    {{ entitylist.views[0].name }} ({{entityview.total_records}})
                  {% endunless %}

                  {% for view in entitylist.views -%}
                    {% if params.view == view.id %}{{view.name}} ({{entityview.total_records}}){% endif -%}
                  {% endfor -%} 
                  <span class="caret"></span>
                </a>
                <ul class="dropdown-menu" role="menu">
                  {% for view in entitylist.views -%}
                    <li{% if params.view == view.id %} class="active"{% endif %}>
                      <a href="{{ request.path | add_query:'view', view.id }}">{{view.name}}</a>
                    </li>
                  {% endfor -%}
                </ul>
              </li>
            </ul>
          {% endif %}
        
          {% if entitylist.search_enabled %}
            <form class="navbar-form navbar-left" method="get">
              <div class="input-group">
                {% if params.search.size > 0 %}
                  <div class="input-group-btn">
                    <a class="btn btn-default"
                      href="{{ request.path_and_query | remove_query:'search' }}">×</a>
                  </div>
                {% endif %}
                <input name="search" class="form-control"
                  value="{{ params.search }}"
                  placeholder="{{ entitylist.search_placeholder | default: 'Search' }}"
                  type="text" />
                <div class="input-group-btn">
                  <button type="submit" class="btn btn-default"
                    title="{{ entitylist.search_tooltip }}">
                    <i class="fa fa-search"> </i>
                  </button>
                </div>
              </div>
            </form>
          {% endif %}
          
          {% if entitylist.create_enabled %}
            <ul class="nav navbar-nav navbar-right">
              <li>
                <a href="{{ entitylist.create_url }}">
                  <i class="fa fa-plus"></i> {{ entitylist.create_label | default: 'Create' }}
                </a>
              </li>
            </ul>
          {% endif %}
          
        </div>
      </div>
    </div>
    
    
      {% assign order = params.order | default: entityview.sort_expression %}
      <table class="table" data-order="{{ order }}">
        <thead>
          <tr>
            {% for c in entityview.columns -%}
              <th width="{{ c.width }}" data-logicalname="{{ c.logical_name }}">
                {% if c.sort_enabled %}
                  {% assign current_sort = order | current_sort:c.logical_name %}
                  {% case current_sort %}
                  {% when 'ASC' %}
                    <a href="{{ request.path_and_query | add_query:'order', c.sort_descending }}">
                      {{ c.name }} <i class="fa fa-sort-asc"></i>
                    </a>
                  {% when 'DESC' %}
                    <a href="{{ request.path_and_query | add_query:'order', c.sort_ascending }}">
                      {{ c.name }} <i class="fa fa-sort-desc"></i>
                    </a>
                  {% else %}
                    <a href="{{ request.path_and_query | add_query:'order', c.sort_ascending }}">
                      {{ c.name }} <i class="fa fa-unsorted"></i>
                    </a>
                  {% endcase %}
                {% else %}
                  {{ c.name }}
                {% endif %}
              </th>
            {% endfor -%}
            <th width="1"></th>
          </tr>
        </thead>

        <tbody>
          {% for e in entityview.records -%}
            <tr>

              {% for c in entityview.columns -%}
                {% assign attr = e[c.logical_name] %}
                {% assign attr_type = c.attribute_type | downcase %}

                <td data-logicalname="{{ c.logical_name }}">
                  {% if attr.is_entity_reference -%}
                    {{ attr.name }}
                  {% elsif attr_type == 'datetime' %}
                    {% if attr %}
                      <time datetime="{{ attr | date_to_iso8601 }}">
                        {{ attr }}
                      </time>
                    {% endif %}
                  {% elsif attr_type == 'picklist' %}
                    {{ attr.label }}
                  {% else %}
                    {{ attr }}
                  {% endif -%}
                </th>
              {% endfor -%}

              <td>
                {% if entitylist.detail_enabled -%}
                  <a class="btn btn-default btn-xs"
                    href="{{ entitylist.detail_url}}?{{ entitylist.detail_id_parameter }}={{ e.id }}"
                    title="{{ entitylist.detail_label }}">
                    <i class="fa fa-external-link"></i>
                  </a>
                {% endif -%}
              </td>

            <tr>
          {% endfor -%}
        </tbody>
      </table>
      
      {% if entityview.pages.size > 0 %}
        {% assign first_page = entityview.first_page %}
        {% assign last_page = entityview.last_page %}
        {% assign page_offset = entityview.page | minus:1 | divided_by:10 | times:10 %}
        {% assign page_slice_first_page = page_offset | plus:1 %}
        {% assign page_slice_last_page = page_offset | plus:10 %}

        <ul class="pagination">
          <li {% unless first_page and entityview.page > 1 %}class="disabled"{% endunless %}>
            <a
              {% if first_page and entityview.page > 1 %}
                href="{{ request.url | add_query:'page', first_page | path_and_query }}"
              {% endif %}>
              «
            </a>
          </li>

          <li {% unless entityview.previous_page %}class="disabled"{% endunless %}>
            <a
              {% if entityview.previous_page %}
                href="{{ request.url | add_query:'page', entityview.previous_page | path_and_query }}"
              {% endif %}>
              ‹
            </a>
          </li>

          {% if page_slice_first_page > 1 %}
            {% assign previous_slice_last_page = page_slice_first_page | minus:1 %}
            <li>
              <a href="{{ request.url | add_query:'page', previous_slice_last_page | path_and_query }}">
                …
              </a>
            </li>
          {% endif %}

          {% for page in entityview.pages offset:page_offset limit:10 -%}
            <li{% if page == entityview.page %} class="active"{% endif %}>
              <a href="{{ request.url | add_query:'page', page | path_and_query }}">
                {{ page }}
              </a>
            </li>
          {% endfor -%}

          {% if page_slice_last_page < entityview.pages.size %}
            {% assign next_slice_first_page = page_slice_last_page | plus:1 %}
            <li>
              <a href="{{ request.url | add_query:'page', next_slice_first_page | path_and_query }}">
                …
              </a>
            </li>
          {% endif %}

          <li {% unless entityview.next_page %}class="disabled"{% endunless %}>
            <a
              {% if entityview.next_page %}
                href="{{ request.url | add_query:'page', entityview.next_page | path_and_query }}"
              {% endif %}>
              ›
            </a>
          </li>

          <li {% unless last_page and entityview.page < last_page %}class="disabled"{% endunless %}>
            <a
              {% if last_page and entityview.page < last_page %}
                href="{{ request.url | add_query:'page', last_page | path_and_query }}"
              {% endif %}>
              »
            </a>
          </li>
        </ul>

      {% endif %}

      </div>
    {% endentityview %}
  {% endentitylist %}

{% endblock %}

Summary

With a few simple alterations to the code snippet provided by Microsoft docs, you can have a Power App Portals custom entity list view selector that display both the name of the current view and the number of records it contain.

Happy Portaling. All the best, Ulrikke.

Cover Photo by Paul Skorupskas on Unsplash

Get new blog posts right to your inbox

Ulrikke Akerbæk Written by:

User Experience through digital interfaces, interaction, branding and visual design has been her passion and focus since she created her first website at age 14. She is a solution architect for Power Platform, specializing in Power Apps Portals. She is a Business Applications MVP and was named one of the top 50 women in tech in Norway in 2022. Currently working as Low Code Practice Lead at Itera.

4 Comments

  1. […] Notice the view selector at the top bar left side. In the original code from MS docs the name of the Entity List is set as the list header and then the drop-down button for choosing links always says “Views”. The result is that the end user has no way of seeing which view is currently selected. I fixed it in this customized version. Want to know how I did it? See this blog post: https://ulrikke.akerbak.com/2019/09/06/custom-entity-list-view-selector/ […]

  2. Archana
    18/05/2020
    Reply

    Hey , I have a requirement to add a custom button in Entitylist other than provided create , edit , download . Do you have any solution for it ?

  3. […] You can edit the rendering of entity list with your custom CSS and alter the HTML to create a custom experience. This blog post will demonstrate how to create custom filters for your custom entity listhttps://ulrikke.akerbak.com/2019/09/06/custom-entity-list-view-selector/ […]

Leave a Reply

Your email address will not be published. Required fields are marked *