Power App Portals: Custom Entity List

Last updated on 07/05/2022

We use a theme framework that look lightly different from the OOTB (out of the box) experience. I need to add come classes and change the structure somewhat to make lists look like they should. I need a custom entity list. This is how:

Custom Entity List Web Template

Start with creating a new blank Web Template. Call it “Custom Entity List” and paste in this code snippet:

{% extends 'Layout 1 Column' %}
{% block main %} {% include 'Page Copy' %}
<!-- Paste Custom Entity List Code from doc here -->
{% endblock %}

Get the custom entity form code from Microsoft Documentation here:

https://docs.microsoft.com/en-gb/powerapps/maker/portals/liquid/render-entity-list-current-page

Update 
The code in Microsoft Documentation is not working for rendering cases lists as I write this blog post. I added the code I have working in production here instead. Please copy the whole code here and paste it into a Web template. 
{% extends 'Layout 1 Column' %}
{% block main %}  
{% include 'Page Copy' %}

{% entitylist id:page.adx_entitylist.id %}
  <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> Views <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' }}">&times;</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">&nbsp;</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>
  
  {% entityview id:params.view, search:params.search, order:params.order, page:params.page, pagesize:params.pagesize, metafilter:params.mf %}
    {% 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 %}>
            &laquo;
          </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 %}>
            &lsaquo;
          </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 }}">
              &hellip;
            </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 }}">
              &hellip;
            </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 %}>
            &rsaquo;
          </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 %}>
            &raquo;
          </a>
        </li>
      </ul>

    {% endif %}
    
  {% endentityview %}
{% endentitylist %}

{% endblock %}

Copy the code and paste it directly into a new web template.

Page Template and Web Page

Create a new page template to hold this Custom Entity List web template.

Crate a new page and add the page template we just created

Save and click the Entity List and select “new”

Entity List

This shortcut send you directly to a form for creating new entity list. I choose to view cases (incidents) for this list.

Now you can configure this list as you wish; add the views that you want, choose how many items to display, enable search, filtering and so on. Look to this doc for more on how to configure Entity Lists:
https://docs.microsoft.com/en-gb/powerapps/maker/portals/configure/entity-lists

Back to the Web Page we select the “Cases” Entity list:

To make sure the local content page also has the right entity list make sure to click on the associated page in “Localized Content” and verify that it too has the right entity list selected.

Save and open your new web page in the browser.

Result

My list look like this on a web site with some simple theming:

Now I need to go back into my Entity List and setup pages and forms for creating and editing. Use as much standard stuff as possible, but as soon as you need to change something make a copy and keep the original. You’ll need it when your copy breaks 😉

Add CSS classes and rearrange the HTML structure to make this list fit into the theme of your web site. We have used this custom entity form as the primary entity form rendering at the Customer Portal at www.skill.no and it looks like this after I cuddled and polished it a little:

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/

Summary

Use the code for custom entity list from Microsoft documentation to easily create your own entity list. This can come in handy when you need to add classes and elements for it to fit into a theme framework or you just want some more freedom.

Happy Portaling!
Best wishes, Ulrikke

Cover Photo by David Ballew 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.

22 Comments

  1. Himanshu Dhillon
    23/03/2020
    Reply

    I am trying to show child records in an entity list
    The parent entities are shown in another entity list. The “view details” of the parent entity list takes to a page which shows the details of parent.

    I want to add an entity list to the details of page parent. This entity list should only show child records. (the child entity holds a reference to parent.)

    I am unable to filter the records of this child entity list.
    It should be based on the id parameter but there is no configuration to filter on that.

    Any suggestions ? Will i have to create a custom entity list for this ?

    • chandra
      17/01/2022
      Reply

      Hi Himanshu, I am looking for same spolution
      I have 3 entities Entity A (1:N) to Entity B (1:N) to Entity C. I need three entity lists pages with filtered data. Is there any way can you help me how to create custom entity list with id param as filter. I have tried the different articles. Its not working.

        • chandra
          30/01/2022
          Reply

          Thanks Urlikke. Perhaps, I have 3 entities to show. Entity A >> Entity B >> Entity C.
          I want different pages for entity lists, if possible
          If user opens entity A List and select a record new page should open to see B Entity lists then same for C entity Lists.
          Otherwise one page as you showed in the referred article. I havenot tried though, I will try.But my interest would be to have three pages.

  2. Himanshu Dhillon
    30/03/2020
    Reply

    Thanks for the reply.
    But I wanted an entity list of child records. I had to show the details of child records and give the ability to add new records (possible only though entity list)
    Subgrid does not have the option.

    I finally created a custom entity list and added code to filter child records based on the request params. Then created relevant web template / page template / page.
    In the page, I added the entity form to show the parent details and entity list had the filtered child records.

    • 13/04/2020
      Reply

      Great job finding the solution on your own. Will however point out that you have all the same possibilities to configure actions like New, Details, Edit, Delete, Associate, ect. for items in a subgrid on an entity form as you have on an entity list. You configure them on “Entity Form Metadata” for the subgrid. More information to be found here (web forms and entity forms work the same way): https://docs.microsoft.com/en-us/powerapps/maker/portals/configure/configure-web-form-subgrid. Thank you for reading the blog and commenting. Hope to hear from you soon.

    • chandra
      30/01/2022
      Reply

      HI Himanshu, could you help me how you did your things, I have same requirement.

  3. chandra
    17/01/2022
    Reply

    Hi Ulrike, I have done same what you have done above I get
    Liquid error: Object of type ‘Adxstudio.Xrm.Web.Mvc.Liquid.OptionSetValue Drop’ cannot be converted to type ‘System.String’. for option sets. and also page number has same type of conversion issues.
    I have not done anything extra, did same as mehtioned in article

    • 29/01/2022
      Reply

      Hello Chandra. You are absolutely right; the code renders errors when I try using it for a list of cases too. This code is copied directly from Microsoft Documentation, so I have submitted a feedback note about the issue. Thank you for bringing it to my attention. I have looked at my own Custom Entity Lists that are used for a list of Cases and found that it still works! I added the complete Web Template code to this blog post. Try it out! Hope it helps. Good luck. Ulrikke.

  4. Hello Ulrikke, great article, it really helped me a lot.
    Congratulations for the quality of the blog and thanks for your contribution.
    A doubt… could you tell me if it is possible to customize, or create a metadata filter, as we create the list/table? As is the article above?

  5. Vaishali
    04/09/2023
    Reply

    Hi, May I know How can I add Download Button on Custom Entity List?

    • 29/01/2024
      Reply

      Hi. I haven’t tried this myself so I really don’t know. Hope you found a solution and sorry for the late reply.

  6. Vaishali Aghera
    04/09/2023
    Reply

    Hi, It is reloading whole page on Sorting, on Searching & on View selection. Can’t we just refresh the grid instead of refreshing whole page? Refreshing whole page is not a good User Experience.

    • 11/11/2023
      Reply

      Hi. If you want to be able to refresh the grid without refreshing the page then you can use the Web API to fetch the information and JS for sorting, filtering and searching client side. When we use liquid to fetch information like this we only get information from the server side as the page loads and it needs a refresh to get more info. If you make sure that the view you are connecting to contains all the data you need then I suppose you could handle sorting, searching and views client side – but then I would recommend using a vue.js or something like that, and not build it from scratch. Hope it answer your question.

Leave a Reply

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