Search code examples
javascriptpolymerpolymer-2.xdrawer

Polymer: Uncaught TypeError: Cannot read property 'persistent' of undefined


when I try to hide drawer in Login page it occur error. I use dom-if for hiding menubar and according to it's syntax I used <template> tag. But it occur error.

Polymer code

<!-- Drawer content -->
<template is="dom-if" if="[[_isLogin()]]">
  <app-drawer id="drawer" slot="drawer" swipe-open="[[narrow]]">
    <app-toolbar>Menu</app-toolbar>
    <iron-selector selected="[[page]]" attr-for-selected="name" class="drawer-list" role="navigation">
      <a name="homepage" href="[[rootPath]]homepage">Homepage</a>
      <a name="profile" href="[[rootPath]]profile">Profile</a>
      <a name="temp" href="[[rootPath]]temp">Temp</a>
    </iron-selector>
  </app-drawer>
</template>

Script

_routePageChanged(page) {
  if(this._isLogin()) {
      // If no page was found in the route data, page will be an empty string.
      // Default to 'homepage' in that case.
      this.page = page || 'homepage';

      // Close a non-persistent drawer when the page & route are changed.
      if (!this.$.drawer.persistent) {
          this.$.drawer.close();
      }
  } else {
      this.page = 'login';
  }
}

Note: _isLogin() is there, it return true or false


Solution

  • As you can see in the docs here, the "Nodes created dynamically using data binding (including those in dom-repeat and dom-if templates) are not added to the this.$ hash"

    So, since that element is inside a dom-if, you won't be able to use this "shortcut" to get a reference to it. So you'll have to stick with the "old" getElementById, while keeping in mind that you are not querying the document, but the local shadow dom instead. So this:

      if (!this.$.drawer.persistent) {
          this.$.drawer.close();
      }
    

    could become something like:

      var drawer = this.shadowRoot.getElementById('drawer');
      if (drawer.persistent) {
        drawer.close();
      }
    

    UPDATE: since you're saying that it still doesn't work, I figured I should mention another thing you need to consider. In your code both showing that element and the condition to query for it are the same, returned by the _isLogin method.

    To be honest, I don't know if what I am about to suggest is the reason or the recommended solution, but I figured you should give it time to actually stamp the element into the page to be able to query for it (to work around the single execution thread and stuff like that). So as a workaround for this you could wrap your code in a setTimeout callback, like this:

    setTimeout(() => {
      var drawer = this.shadowRoot.getElementById('drawer');
      if (drawer.persistent) {
        drawer.close();
      }
    });
    

    Since the second parameter, the timeout, is not provided, you're basically saying "do this as soon as possible, but not right now".