2

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>
Let Me Tink About It
  • 15,156
  • 21
  • 98
  • 207
Carl
  • 23
  • 1
  • 5

3 Answers3

4

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>
  • What I'm trying to avoid is having "isAdmin", "isGuest", "isBanned" etc bools in the properties. Your answer will work, but the hope is to not have to change code for each role. Should I be creating some observer that whenever user.roles array changes it edits/recreates a subobject say users.permissions.isAdmin and so forth on the fly? I'm not sure that would work either but can try. – Carl May 04 '17 at 17:10
  • I voted this as the solution, as it lead my to a solution anyways if not the perfect one. I put in an observer which updates a permission object each time roles changed, it will name the properties of that object isAdmin isGuest etc, that way I dont have to create it over and over or alter code later on. Cheers. – Carl May 04 '17 at 17:46
0

If you are using native Polymer 2.0 elements (which you propably do as i can see) you should use <dom-if> element

https://www.polymer-project.org/2.0/docs/about_20#type-extension

If you are using hybrid elements in Polymer 2.0 you should wrap dom-if with <dom-bind>.

According to Polymer 2.0 upgrade guide:

If you have any template extension elements—dom-bind, dom-if, or dom-repeat—in the main document, convert them to the wrapped form.

https://www.polymer-project.org/2.0/docs/upgrade

You can find it under the section Custom elements API > Remove type-extension elements

Kuba Šimonovský
  • 2,013
  • 2
  • 17
  • 35
  • Could you give an example of what the template code should look like then in just this example? I tried wrapping in . I feel like I'm close but the hasRole function never gets called again. – Carl May 04 '17 at 14:48
  • Don't use ``. Instead, use ``. Unfortunately, the documentation does not make this clear yet. It needs improvement. – Let Me Tink About It Aug 06 '17 at 08:30
0

Change your dom-if condition like this

 <dom-if if={{condition}}>
    <template>
    code inside template
    </template>
    </dom-if>

This worked for me.