Search code examples
javascriptpolymer

Polymer 2.0 dom-if based on function output


Relative Polymer newbie here but not new to JS. Would like to understand why the following code snip does not work. In short, I would have a user object which will be populated after the page has already loaded. A property of that object is roles which is just an array of strings.

The dom-if condition is calling hasRole('user'), the function will return true, however... I feel like I'm just missing some fundamental concept here and have been banging my head against google for a day or two.

I guess to be clear, the hasRole function gets called on page load but not after. And while I do realize I could have user.isAdmin be a bool, then I would need to create properties for each possible role, and would like the auth system to be more flexible than that.

Currently, the hidden "admin only" section never appears.

Sorry if this is simple or a stupid question or whatever, its just not something I fully understand yet and maybe dont even know the right terms to google.

I am using Polymer 2.0.0-rc.3

<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/polymer/lib/elements/dom-if.html">

<dom-module id="test1-app">
  <template>
    <style>
      :host {
        display: block;
      }
    </style>
    <button on-click="toggle">Toggle</button>
    This is visible...

    <template is="dom-if" if="{{hasRole('admin')}}">
        but this is hidden.
    </template>
  </template>

  <script>
    /** @polymerElement */
    class Test1App extends Polymer.Element {
      static get is() { return 'test1-app'; }
      static get properties() {
        return {
          user: {
            type: Object
          }
        };
      }
      toggle() {
        if(this.user) {
          this.user = null;
        }
        else {
          this.user = {
            name: 'Carl',
            roles: ['admin','user']
          }
        }
      }

      static get observers() {
        return [
          'userChanged(user.*)'
        ]
      }
      hasRole(role) {
        if(this.user && this.user.roles && this.user.roles.indexOf(role)>=0) {
          return true;

        }
        else {
          return false;
        }
      }

      userChanged() {
          //just observing for the sake of observing
          console.log(this.user);

      }

    }

    window.customElements.define(Test1App.is, Test1App);
  </script>
</dom-module>

Solution

  • your code looks good but hasRole function is only called once (at first render).

    Try use a property instead of a function ... this way dom-if will render according to that property value.

    This should work:

    <link rel="import" href="../../bower_components/polymer/polymer-element.html">
    <link rel="import" href="../../bower_components/polymer/lib/elements/dom-if.html">
    
    <dom-module id="test1-app">
      <template>
        <style>
          :host {
            display: block;
          }
        </style>
        <button on-click="toggle">Toggle</button>
        This is visible...
    
        <template is="dom-if" if="{{domif}}">
            but this is hidden.
        </template>
      </template>
    
      <script>
        /** @polymerElement */
        class Test1App extends Polymer.Element {
          static get is() { return 'test1-app'; }
          static get properties() {
            return {
              user: {
                type: Object
              },
              domif: {type: Boolean,
                      value: true}
            };
          }
          toggle() {
            this.domif = !this.domif;
            if(this.user) {
              this.user = null;
            }
            else {
              this.user = {
                name: 'Carl',
                roles: ['admin','user']
              }
            }
          }
    
          static get observers() {
            return [
              'userChanged(user.*)'
            ]
          }
          hasRole(role) {
            console.log('calling hasRole')
            if(this.user && this.user.roles && this.user.roles.indexOf(role)>=0) {
              this.domif = true;
              return true;
    
            }
            else {
              this.domif = false;
              return false;
            }
          }
    
          userChanged() {
              //just observing for the sake of observing
              console.log(this.user);
    
          }
    
        }
    
        window.customElements.define(Test1App.is, Test1App);
      </script>
    </dom-module>