polymerdom-repeat

Polymer - Show empty state on nested dom-repeat with filter


I have a nested dom-repeat to first iterate employees in company and then iterate projects of the employee, also when iterating projects I'm using a filter to get only success projects. Tried to use renderedItems but it's giving number of employees always. Instead i need a way to know the status when no employee have any succeeded projects. (simply when no items listed)

<!DOCTYPE html>
<html>

<head>
  <script src="https://cdn.rawgit.com/download/polymer-cdn/1.6.0/lib/webcomponentsjs/webcomponents-lite.js"></script>
  <link rel="import" href="https://cdn.rawgit.com/download/polymer-cdn/1.6.0/lib/polymer/polymer.html" />
  <script src="script.js"></script>
</head>

<body>
  <test-element></test-element>
  <dom-module id="test-element">
    <template>
      <div>
        <h1>Test Element</h1>
        <h3>Rendered Count: [[renderedCount]]</h3>
        <template is="dom-if" if="{{!renderedCount}}">
          <img src="https://emptyensemble.com/wp-content/themes/emptyensemble2015/assets/images/empty_ensemble_empty_set_logo.png" alt="Mountain View" style="width:250px;height:250px;">
        </template>
        <template is="dom-repeat" items="{{employees}}" as="employee" rendered-item-count="{{renderedCount}}">
          <template is="dom-repeat" items="{{employee.projects}}" filter="{{_filterProjects()}}" as="employeeProject">
            <span>Test 1 [[employeeProject.name]]</span>
            <br>
          </template>
        </template>
      </div>
    </template>
    <script>
      Polymer({
        is: 'test-element',
        properties: {
          employees: {
            type: Array,
            value: function() {
              return [{
                name: 'user1',
                projects: [{
                  name: 'proj1',
                  status: false
                }, {
                  name: 'proj2',
                  status: true
                }, {
                  name: 'proj3',
                  status: true
                }]
              }, {
                name: 'user2',
                projects: [{
                  name: 'proj4',
                  status: false
                }, {
                  name: 'proj5',
                  status: false
                }]
              }]
            }
          },
          renderedCount: {
            type: Number
          }
        },

        _filterProjects: function() {
          return function(item) {
            return item.status;
          };
        }
      });
    </script>
  </dom-module>
</body>

</html>


Solution

  • I have tried few ways to resolve this issue and identified two types on showing empty state. (Actually got the help from polymer slack channel and thought of sharing the information with some samples)

    You can try by changing the employee array in following code samples, by setting projects status true or false to see the empty state changing.

    1. Show empty state by employee - When any employee don't have success projects show an empty state

    <!DOCTYPE html>
    <html>
    
    <head>
      <script src="https://cdn.rawgit.com/download/polymer-cdn/1.6.0/lib/webcomponentsjs/webcomponents-lite.js"></script>
      <link rel="import" href="https://cdn.rawgit.com/download/polymer-cdn/1.6.0/lib/polymer/polymer.html" />
      <script src="script.js"></script>
    </head>
    
    <body>
      <test-element></test-element>
      <dom-module id="test-element">
        <template>
          <div>
            <h1>Company Projects</h1>
            <template is="dom-repeat" items="{{employees}}" as="employee" rendered-item-count="{{renderedCount}}">
              <br>
              <b><span>[[employee.name]]</span></b>
              <br>
              <div hidden$="{{_computeEmpty(employee.innercount)}}">
                <img src="https://emptyensemble.com/wp-content/themes/emptyensemble2015/assets/images/empty_ensemble_empty_set_logo.png" alt="Mountain View" style="width:250px;height:250px;">
              </div>
              <br>
              <template is="dom-repeat" items="{{employee.projects}}" filter="{{_filterProjects()}}" as="employeeProject" rendered-item-count="{{employee.innercount}}">
                <span>Project: [[employeeProject.name]]</span>
                <br>
    
              </template>
    
            </template>
          </div>
        </template>
    
        <script>
          Polymer({
            is: 'test-element',
            properties: {
              employees: {
                type: Array,
                value: function() {
                  return [{
                    name: 'user1',
                    projects: [{
                      name: 'proj1',
                      status: true
                    }, {
                      name: 'proj2',
                      status: false
                    }, {
                      name: 'proj3',
                      status: false
                    }]
                  }, {
                    name: 'user2',
                    projects: [{
                      name: 'proj4',
                      status: false
                    }, {
                      name: 'proj5',
                      status: false
                    }]
                  }]
                }
              },
              renderedCount: {
                type: Number
              },
              innercount: {
                type: Number
              }
            },
            _computeEmpty: function(projects) {
              return (projects > 0);
            },
            _filterProjects: function() {
              return function(item) {
                return item.status;
              };
            }
          });
        </script>
      </dom-module>
    </body>
    
    </html>

    1. Show empty state by company - When no employee have success projects show an empty state

    <!DOCTYPE html>
    <html>
    
    <head>
      <script src="https://cdn.rawgit.com/download/polymer-cdn/1.6.0/lib/webcomponentsjs/webcomponents-lite.js"></script>
      <link rel="import" href="https://cdn.rawgit.com/download/polymer-cdn/1.6.0/lib/polymer/polymer.html" />
      <script src="script.js"></script>
    </head>
    
    <body>
      <test-element></test-element>
      <dom-module id="test-element">
        <template>
          <div>
            <h1>Company Projects</h1>
            <br>
            <b><span>Succeeded Projects</span></b>
            <br>
            <br>
            <div hidden$="{{!showEmptyState}}">
              <img src="https://emptyensemble.com/wp-content/themes/emptyensemble2015/assets/images/empty_ensemble_empty_set_logo.png" alt="Mountain View" style="width:250px;height:250px;">
            </div>
            <template is="dom-repeat" items="{{employees}}" as="employee">
              <template is="dom-repeat" items="{{employee.projects}}" filter="{{_filterProjects()}}" as="employeeProject" rendered-item-count="{{renderedCount}}">
                <span>[[employee.name]]: [[employeeProject.name]]</span>
                <br>
    
              </template>
    
            </template>
          </div>
        </template>
    
        <script>
          Polymer({
            is: 'test-element',
            properties: {
              employees: {
                type: Array,
                value: function() {
                  return [{
                    name: 'user1',
                    projects: [{
                      name: 'proj1',
                      status: false
                    }, {
                      name: 'proj2',
                      status: false
                    }, {
                      name: 'proj3',
                      status: false
                    }]
                  }, {
                    name: 'user2',
                    projects: [{
                      name: 'proj4',
                      status: false
                    }, {
                      name: 'proj5',
                      status: false
                    }]
                  }]
                }
              },
              renderedCount: {
                type: Number,
                observer: '_onInnerRenderedCountChanged'
              },
              showEmptyState: {
                type: Boolean,
                value: true
              }
            },
            _onInnerRenderedCountChanged: function(newValue, oldValue) {
              if (newValue > 0) {
                this.set('showEmptyState', false);
              }
            },
            _filterProjects: function() {
              return function(item) {
                return item.status;
              };
            }
          });
        </script>
      </dom-module>
    </body>
    
    </html>